aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/core.gyp1
-rw-r--r--include/core/SkFontHost.h8
-rw-r--r--src/ports/SkFontHost_sandbox_none.cpp15
-rwxr-xr-xsrc/ports/SkFontHost_win.cpp45
4 files changed, 62 insertions, 7 deletions
diff --git a/gyp/core.gyp b/gyp/core.gyp
index 341eb4f476..a31755a32f 100644
--- a/gyp/core.gyp
+++ b/gyp/core.gyp
@@ -152,6 +152,7 @@
'../src/ports/SkDebug_stdio.cpp',
'../src/ports/SkDebug_win.cpp',
+ '../src/ports/SkFontHost_sandbox_none.cpp',
'../src/ports/SkFontHost_win.cpp',
'../src/ports/SkThread_win.cpp',
diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h
index 1b18abaa5c..2ac5165d50 100644
--- a/include/core/SkFontHost.h
+++ b/include/core/SkFontHost.h
@@ -289,6 +289,14 @@ public:
*/
static uint32_t GetUnitsPerEm(SkFontID fontID);
#endif
+
+ /** If Skia is running in a constrained environment and the typeface
+ implementation is handle based, the typeface data may become
+ unavailable asynchronously. If a font host or scaler context method is
+ unable to access font data, it may call this function as a request to
+ make the handle contained in the typeface useable.
+ */
+ static void EnsureTypefaceAccessible(const SkTypeface& typeface);
};
#endif
diff --git a/src/ports/SkFontHost_sandbox_none.cpp b/src/ports/SkFontHost_sandbox_none.cpp
new file mode 100644
index 0000000000..54ab5b2e21
--- /dev/null
+++ b/src/ports/SkFontHost_sandbox_none.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkFontHost.h"
+#include "SkTypeface.h"
+#include "SkTypeface_win.h"
+
+//static
+void SkFontHost::EnsureTypefaceAccessible(const SkTypeface& typeface) {
+ //No sandbox, nothing to do.
+}
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 847b814826..7118307030 100755
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -203,6 +203,11 @@ SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
return 0;
}
+static void ensure_typeface_accessible(SkFontID fontID) {
+ LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID);
+ SkFontHost::EnsureTypefaceAccessible(*face);
+}
+
static void GetLogFontByID(SkFontID fontID, LOGFONT* lf) {
LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID);
if (face) {
@@ -393,9 +398,11 @@ const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
SetWorldTransform(fDC, &xform);
uint16_t glyphID = glyph.getGlyphID();
- ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
+ BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
GdiFlush();
-
+ if (0 == ret) {
+ return NULL;
+ }
*srcRBPtr = srcRB;
// offset to the start of the image
return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
@@ -592,6 +599,10 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
// Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller
// BlackBlox; we need the bigger one in case we need the image. fAdvance is the same.
uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
+ if (GDI_ERROR == ret) {
+ ensure_typeface_accessible(fRec.fFontID);
+ ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
+ }
if (GDI_ERROR != ret) {
if (ret == 0) {
@@ -650,6 +661,10 @@ void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPa
OUTLINETEXTMETRIC otm;
uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
+ if (GDI_ERROR == ret) {
+ ensure_typeface_accessible(fRec.fFontID);
+ ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
+ }
if (sizeof(otm) != ret) {
return;
}
@@ -876,9 +891,13 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
size_t srcRB;
const void* bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB);
- if (!bits) {
- sk_bzero(glyph.fImage, glyph.computeImageSize());
- return;
+ if (NULL == bits) {
+ ensure_typeface_accessible(fRec.fFontID);
+ bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB);
+ if (NULL == bits) {
+ sk_bzero(glyph.fImage, glyph.computeImageSize());
+ return;
+ }
}
if (table) {
@@ -942,6 +961,10 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
GLYPHMETRICS gm;
uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
+ if (GDI_ERROR == total_size) {
+ ensure_typeface_accessible(fRec.fFontID);
+ total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
+ }
if (GDI_ERROR != total_size) {
@@ -1033,8 +1056,12 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
// To request design units, create a logical font whose height is specified
// as unitsPerEm.
OUTLINETEXTMETRIC otm;
- if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) ||
- !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
+ unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
+ if (0 == otmRet) {
+ ensure_typeface_accessible(fontID);
+ otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
+ }
+ if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
goto Error;
}
lf.lfHeight = -SkToS32(otm.otmEMSquare);
@@ -1178,6 +1205,10 @@ SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
DWORD tables[2] = {kTTCTag, 0};
for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
+ if (bufferSize == GDI_ERROR) {
+ ensure_typeface_accessible(uniqueID);
+ bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
+ }
if (bufferSize != GDI_ERROR) {
stream = new SkMemoryStream(bufferSize);
if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(),