Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(904)

Unified Diff: src/ports/SkFontHost_win.cpp

Issue 17435003: Fix limit on size of glyph paths. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ports/SkFontHost_win.cpp
===================================================================
--- src/ports/SkFontHost_win.cpp (revision 9661)
+++ src/ports/SkFontHost_win.cpp (working copy)
@@ -19,6 +19,7 @@
#include "SkPath.h"
#include "SkStream.h"
#include "SkString.h"
+#include "SkTemplates.h"
#include "SkThread.h"
#include "SkTypeface_win.h"
#include "SkTypefaceCache.h"
@@ -46,18 +47,11 @@
// always packed xxRRGGBB
typedef uint32_t SkGdiRGB;
-template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
- return (T*)((char*)ptr + byteOffset);
-}
-
// define this in your Makefile or .gyp to enforce AA requests
// which GDI ignores at small sizes. This flag guarantees AA
// for rotated text, regardless of GDI's notions.
//#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
-// client3d has to undefine this for now
-#define CAN_USE_LOGFONT_NAME
-
static bool isLCD(const SkScalerContext::Rec& rec) {
return SkMask::kLCD16_Format == rec.fMaskFormat ||
SkMask::kLCD32_Format == rec.fMaskFormat;
@@ -91,9 +85,6 @@
using namespace skia_advanced_typeface_metrics_utils;
-static const uint16_t BUFFERSIZE = (16384 - 32);
-static uint8_t glyphbuf[BUFFERSIZE];
-
/**
* Since LOGFONT wants its textsize as an int, and we support fractional sizes,
* and since we have a cache of LOGFONTs for our tyepfaces, we always set the
@@ -554,8 +545,6 @@
return SkFixedToFIXED(SkFloatToFixed(x));
}
-SK_DECLARE_STATIC_MUTEX(gFTMutex);
-
#define HIRES_TEXTSIZE 2048
#define HIRES_SHIFT 11
static inline SkFixed HiResToFixed(int value) {
@@ -589,9 +578,8 @@
, fFont(0)
, fSavefont(0)
, fSC(0)
- , fGlyphCount(-1) {
- SkAutoMutexAcquire ac(gFTMutex);
-
+ , fGlyphCount(-1)
+{
LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface);
fDDC = ::CreateCompatibleDC(NULL);
@@ -924,10 +912,17 @@
* that shifting into other color spaces is imprecise.
*/
static const uint8_t* getInverseGammaTableGDI() {
+ // Since build_power_table is idempotent, many threads can build gTableGdi
+ // simultaneously.
static bool gInited;
static uint8_t gTableGdi[256];
- if (!gInited) {
+ if (gInited) {
+ // Need a L/L (read) barrier (acquire not needed). If gInited is observed
+ // true then gTableGdi is observable, but it must be requested.
+ } else {
build_power_table(gTableGdi, 2.3f);
+ // Need a S/S (write) barrier (release not needed) here so that this
+ // write to gInited becomes observable after gTableGdi.
gInited = true;
}
return gTableGdi;
@@ -941,15 +936,22 @@
* If this value is not specified, the default is a gamma of 1.4.
*/
static const uint8_t* getInverseGammaTableClearType() {
+ // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building
+ // gTableClearType with build_power_table is effectively idempotent.
static bool gInited;
static uint8_t gTableClearType[256];
- if (!gInited) {
+ if (gInited) {
+ // Need a L/L (read) barrier (acquire not needed). If gInited is observed
+ // true then gTableClearType is observable, but it must be requested.
+ } else {
UINT level = 0;
if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
// can't get the data, so use a default
level = 1400;
}
build_power_table(gTableClearType, level / 1000.0f);
+ // Need a S/S (write) barrier (release not needed) here so that this
+ // write to gInited becomes observable after gTableClearType.
gInited = true;
}
return gTableClearType;
@@ -1005,7 +1007,7 @@
return false;
}
}
- src = SkTAddByteOffset(src, srcRB);
+ src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
}
return true;
}
@@ -1050,7 +1052,7 @@
}
dst[byteCount] = byte;
}
- src = SkTAddByteOffset(src, srcRB);
+ src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
dst -= dstRB;
}
}
@@ -1066,7 +1068,7 @@
for (int i = 0; i < width; i++) {
dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
}
- src = SkTAddByteOffset(src, srcRB);
+ src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
dst -= dstRB;
}
}
@@ -1082,7 +1084,7 @@
for (int i = 0; i < width; i++) {
dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
}
- src = SkTAddByteOffset(src, srcRB);
+ src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
dst = (uint16_t*)((char*)dst - dstRB);
}
}
@@ -1098,7 +1100,7 @@
for (int i = 0; i < width; i++) {
dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
}
- src = SkTAddByteOffset(src, srcRB);
+ src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
dst = (uint32_t*)((char*)dst - dstRB);
}
}
@@ -1109,7 +1111,6 @@
}
void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
- SkAutoMutexAcquire ac(gFTMutex);
SkASSERT(fDDC);
const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
@@ -1148,7 +1149,7 @@
int b = (addr[x] >> 0) & 0xFF;
addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
}
- addr = SkTAddByteOffset(addr, srcRB);
+ addr = SkTAddOffset<SkGdiRGB>(addr, srcRB);
}
}
@@ -1200,23 +1201,49 @@
}
void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
-
- SkAutoMutexAcquire ac(gFTMutex);
-
SkASSERT(&glyph && path);
SkASSERT(fDDC);
path->reset();
GLYPHMETRICS gm;
- uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
+
+ // Out of all the fonts on a typical Windows box,
+ // 25% of glyphs require more than 2KB.
+ // 1% of glyphs require more than 4KB.
+ // 0.01% of glyphs require more than 8KB.
+ // 8KB is less than 1% of the normal 1MB stack on Windows.
+ // Note that some web fonts glyphs require more than 20KB.
+ static const uint16_t BUFFERSIZE = (1 << 13);
+ SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE);
+
+ const UINT flags = GGO_NATIVE | GGO_GLYPH_INDEX;
+ DWORD total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, BUFFERSIZE, glyphbuf, &fMat22);
if (GDI_ERROR == total_size) {
- LogFontTypeface::EnsureAccessible(this->getTypeface());
- total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
+ // GDI_ERROR because the BUFFERSIZE was too small, or because the data was not accessible.
+ // When the data is not accessable GetGlyphOutlineW fails rather quickly,
+ // so just try to get the size. If that fails then ensure the data is accessible.
+ total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
if (GDI_ERROR == total_size) {
- SkASSERT(false);
- return;
+ LogFontTypeface::EnsureAccessible(this->getTypeface());
+ total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
+ if (GDI_ERROR == total_size) {
+ SkASSERT(false);
+ return;
+ }
}
+
+ glyphbuf.reset(total_size);
+
+ DWORD ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf, &fMat22);
+ if (GDI_ERROR == ret) {
+ LogFontTypeface::EnsureAccessible(this->getTypeface());
+ ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf, &fMat22);
+ if (GDI_ERROR == ret) {
+ SkASSERT(false);
+ return;
+ }
+ }
}
const uint8_t* cur_glyph = glyphbuf;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698