Add paging support for handle based typefaces.

http://codereview.appspot.com/5379043/
http://codereview.appspot.com/5364052/


git-svn-id: http://skia.googlecode.com/svn/trunk@2693 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bungeman@google.com 2011-11-15 22:26:41 +00:00
Родитель 79841fe3cb
Коммит 39698b1bd7
4 изменённых файлов: 62 добавлений и 7 удалений

Просмотреть файл

@ -152,6 +152,7 @@
'../src/ports/SkDebug_stdio.cpp', '../src/ports/SkDebug_stdio.cpp',
'../src/ports/SkDebug_win.cpp', '../src/ports/SkDebug_win.cpp',
'../src/ports/SkFontHost_sandbox_none.cpp',
'../src/ports/SkFontHost_win.cpp', '../src/ports/SkFontHost_win.cpp',
'../src/ports/SkThread_win.cpp', '../src/ports/SkThread_win.cpp',

Просмотреть файл

@ -289,6 +289,14 @@ public:
*/ */
static uint32_t GetUnitsPerEm(SkFontID fontID); static uint32_t GetUnitsPerEm(SkFontID fontID);
#endif #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 #endif

Просмотреть файл

@ -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.
}

Просмотреть файл

@ -203,6 +203,11 @@ SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) {
return 0; 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) { static void GetLogFontByID(SkFontID fontID, LOGFONT* lf) {
LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID); LogFontTypeface* face = (LogFontTypeface*)SkTypefaceCache::FindByID(fontID);
if (face) { if (face) {
@ -393,9 +398,11 @@ const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
SetWorldTransform(fDC, &xform); SetWorldTransform(fDC, &xform);
uint16_t glyphID = glyph.getGlyphID(); 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(); GdiFlush();
if (0 == ret) {
return NULL;
}
*srcRBPtr = srcRB; *srcRBPtr = srcRB;
// offset to the start of the image // offset to the start of the image
return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB; 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 // 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. // 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); 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 (GDI_ERROR != ret) {
if (ret == 0) { if (ret == 0) {
@ -650,6 +661,10 @@ void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPa
OUTLINETEXTMETRIC otm; OUTLINETEXTMETRIC otm;
uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &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) { if (sizeof(otm) != ret) {
return; return;
} }
@ -876,9 +891,13 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
size_t srcRB; size_t srcRB;
const void* bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB); const void* bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB);
if (!bits) { if (NULL == bits) {
sk_bzero(glyph.fImage, glyph.computeImageSize()); ensure_typeface_accessible(fRec.fFontID);
return; bits = fOffscreen.draw(glyph, isBW, fgColor, &srcRB);
if (NULL == bits) {
sk_bzero(glyph.fImage, glyph.computeImageSize());
return;
}
} }
if (table) { if (table) {
@ -942,6 +961,10 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
GLYPHMETRICS gm; GLYPHMETRICS gm;
uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22); 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) { if (GDI_ERROR != total_size) {
@ -1033,8 +1056,12 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics(
// To request design units, create a logical font whose height is specified // To request design units, create a logical font whose height is specified
// as unitsPerEm. // as unitsPerEm.
OUTLINETEXTMETRIC otm; OUTLINETEXTMETRIC otm;
if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm) || unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
!GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { if (0 == otmRet) {
ensure_typeface_accessible(fontID);
otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
}
if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
goto Error; goto Error;
} }
lf.lfHeight = -SkToS32(otm.otmEMSquare); lf.lfHeight = -SkToS32(otm.otmEMSquare);
@ -1178,6 +1205,10 @@ SkStream* SkFontHost::OpenStream(SkFontID uniqueID) {
DWORD tables[2] = {kTTCTag, 0}; DWORD tables[2] = {kTTCTag, 0};
for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) { for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); 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) { if (bufferSize != GDI_ERROR) {
stream = new SkMemoryStream(bufferSize); stream = new SkMemoryStream(bufferSize);
if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(),