remove obsolete generateLineHeight
use canonical lfHeight so we can compare different LOGFONTs and map equivalent fonts (except for height) to the same typeface. To do this I add fSize to scale the output from GDI to get from the canonical int textSize to the actual fractional size. git-svn-id: http://skia.googlecode.com/svn/trunk@871 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
f9bb7a8e20
commit
b652427197
@ -20,6 +20,8 @@
|
||||
#include "SkStream.h"
|
||||
#include "SkKey.h"
|
||||
|
||||
extern SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&);
|
||||
|
||||
static const char gText[] =
|
||||
"When in the Course of human events it becomes necessary for one people "
|
||||
"to dissolve the political bands which have connected them with another "
|
||||
@ -31,7 +33,16 @@ static const char gText[] =
|
||||
class TextBoxView : public SkView {
|
||||
public:
|
||||
TextBoxView() {
|
||||
fTextSize = SkIntToScalar(32);
|
||||
LOGFONT lf;
|
||||
sk_bzero(&lf, sizeof(lf));
|
||||
lf.lfHeight = 9;
|
||||
SkTypeface* tf0 = SkCreateTypefaceFromLOGFONT(lf);
|
||||
lf.lfHeight = 12;
|
||||
SkTypeface* tf1 = SkCreateTypefaceFromLOGFONT(lf);
|
||||
// we assert that different sizes should not affect which face we get
|
||||
SkASSERT(tf0 == tf1);
|
||||
tf0->unref();
|
||||
tf1->unref();
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -61,36 +72,16 @@ protected:
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setTextSize(fTextSize);
|
||||
tbox.setText(gText, strlen(gText), paint);
|
||||
|
||||
tbox.draw(canvas, gText, strlen(gText), paint);
|
||||
}
|
||||
|
||||
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
|
||||
return new Click(this);
|
||||
}
|
||||
|
||||
virtual bool onClick(Click* click) {
|
||||
const SkScalar delta = SkIntToScalar(3);
|
||||
if (click->fState == Click::kUp_State) {
|
||||
if (click->fCurr.fY < this->height()/2) {
|
||||
fTextSize += delta;
|
||||
this->inval(NULL);
|
||||
return true;
|
||||
} else {
|
||||
if (fTextSize > delta) {
|
||||
fTextSize -= delta;
|
||||
this->inval(NULL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (int i = 9; i < 24; i += 2) {
|
||||
paint.setTextSize(SkIntToScalar(i));
|
||||
tbox.draw(canvas);
|
||||
canvas->translate(0, tbox.getTextHeight() + paint.getFontSpacing());
|
||||
}
|
||||
return this->INHERITED::onClick(click);
|
||||
}
|
||||
|
||||
private:
|
||||
SkScalar fTextSize;
|
||||
|
||||
typedef SkView INHERITED;
|
||||
};
|
||||
|
||||
|
@ -51,6 +51,18 @@ static uint8_t glyphbuf[BUFFERSIZE];
|
||||
// Give 1MB font cache budget
|
||||
#define FONT_CACHE_MEMORY_BUDGET (1024 * 1024)
|
||||
|
||||
/**
|
||||
* 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
|
||||
* lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
|
||||
* actual requested size.
|
||||
*/
|
||||
static const int gCanonicalTextSize = 64;
|
||||
|
||||
static void make_canonical(LOGFONT* lf) {
|
||||
lf->lfHeight = -gCanonicalTextSize;
|
||||
}
|
||||
|
||||
static inline FIXED SkFixedToFIXED(SkFixed x) {
|
||||
return *(FIXED*)(&x);
|
||||
}
|
||||
@ -85,6 +97,8 @@ public:
|
||||
SkTypeface(style, sk_atomic_inc(&gCurrId)+1), // 0 id is reserved so add 1
|
||||
fLogFont(logFont)
|
||||
{
|
||||
make_canonical(&fLogFont);
|
||||
|
||||
SkAutoMutexAcquire am(gMutex);
|
||||
fNext = gHead;
|
||||
gHead = this;
|
||||
@ -120,8 +134,11 @@ public:
|
||||
|
||||
static LogFontTypeface* FindByLogFont(const LOGFONT& lf)
|
||||
{
|
||||
LOGFONT canonical = lf;
|
||||
make_canonical(&canonical);
|
||||
|
||||
LogFontTypeface* curr = gHead;
|
||||
while (curr && memcmp(&curr->fLogFont, &lf, sizeof(LOGFONT))) {
|
||||
while (curr && memcmp(&curr->fLogFont, &canonical, sizeof(LOGFONT))) {
|
||||
curr = curr->fNext;
|
||||
}
|
||||
return curr;
|
||||
@ -155,15 +172,14 @@ static const LOGFONT& get_default_font() {
|
||||
}
|
||||
|
||||
SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& lf) {
|
||||
|
||||
LogFontTypeface* ptypeface = LogFontTypeface::FindByLogFont(lf);
|
||||
|
||||
if (NULL == ptypeface) {
|
||||
SkTypeface::Style style = GetFontStyle(lf);
|
||||
ptypeface = new LogFontTypeface(style, lf);
|
||||
} else {
|
||||
ptypeface->ref();
|
||||
}
|
||||
ptypeface->ref();
|
||||
}
|
||||
return ptypeface;
|
||||
}
|
||||
|
||||
@ -186,51 +202,48 @@ protected:
|
||||
virtual void generateMetrics(SkGlyph* glyph);
|
||||
virtual void generateImage(const SkGlyph& glyph);
|
||||
virtual void generatePath(const SkGlyph& glyph, SkPath* path);
|
||||
virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent);
|
||||
virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);
|
||||
//virtual SkDeviceContext getDC() {return ddc;}
|
||||
private:
|
||||
LOGFONT lf;
|
||||
MAT2 mat22;
|
||||
HDC ddc;
|
||||
HFONT savefont;
|
||||
HFONT font;
|
||||
SCRIPT_CACHE sc;
|
||||
SkScalar fScale; // to get from canonical size to real size
|
||||
MAT2 fMat22;
|
||||
HDC fDDC;
|
||||
HFONT fSavefont;
|
||||
HFONT fFont;
|
||||
SCRIPT_CACHE fSC;
|
||||
};
|
||||
|
||||
SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)
|
||||
: SkScalerContext(desc), ddc(0), font(0), savefont(0), sc(0) {
|
||||
: SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) {
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
|
||||
lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();
|
||||
fScale = fRec.fTextSize / gCanonicalTextSize;
|
||||
fMat22.eM11 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[0][0]));
|
||||
fMat22.eM12 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[0][1]));
|
||||
fMat22.eM21 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[1][0]));
|
||||
fMat22.eM22 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[1][1]));
|
||||
|
||||
mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
|
||||
mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
|
||||
mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]);
|
||||
mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);
|
||||
|
||||
ddc = ::CreateCompatibleDC(NULL);
|
||||
SetBkMode(ddc, TRANSPARENT);
|
||||
fDDC = ::CreateCompatibleDC(NULL);
|
||||
SetBkMode(fDDC, TRANSPARENT);
|
||||
|
||||
// Scaling by the DPI is inconsistent with how Skia draws elsewhere
|
||||
//SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
|
||||
SkScalar height = -fRec.fTextSize;
|
||||
lf.lfHeight = SkScalarRound(height);
|
||||
font = CreateFontIndirect(&lf);
|
||||
savefont = (HFONT)SelectObject(ddc, font);
|
||||
LOGFONT lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();
|
||||
lf.lfHeight = -gCanonicalTextSize;
|
||||
fFont = CreateFontIndirect(&lf);
|
||||
fSavefont = (HFONT)SelectObject(fDDC, fFont);
|
||||
}
|
||||
|
||||
SkScalerContext_Windows::~SkScalerContext_Windows() {
|
||||
if (ddc) {
|
||||
::SelectObject(ddc, savefont);
|
||||
::DeleteDC(ddc);
|
||||
ddc = NULL;
|
||||
if (fDDC) {
|
||||
::SelectObject(fDDC, fSavefont);
|
||||
::DeleteDC(fDDC);
|
||||
}
|
||||
if (font) {
|
||||
::DeleteObject(font);
|
||||
if (fFont) {
|
||||
::DeleteObject(fFont);
|
||||
}
|
||||
if (sc) {
|
||||
::ScriptFreeCache(&sc);
|
||||
if (fSC) {
|
||||
::ScriptFreeCache(&fSC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +258,7 @@ uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
|
||||
// TODO(ctguil): Support characters that generate more than one glyph.
|
||||
if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {
|
||||
// Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
|
||||
SkAssertResult(GetGlyphIndicesW(ddc, c, 1, &index, 0));
|
||||
SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));
|
||||
} else {
|
||||
// Use uniscribe to detemine glyph index for non-BMP characters.
|
||||
// Need to add extra item to SCRIPT_ITEM to work around a bug in older
|
||||
@ -259,7 +272,7 @@ uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
|
||||
SCRIPT_VISATTR vsa;
|
||||
int glyphs;
|
||||
SkAssertResult(SUCCEEDED(ScriptShape(
|
||||
ddc, &sc, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
|
||||
fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
|
||||
}
|
||||
return index;
|
||||
}
|
||||
@ -270,7 +283,7 @@ void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
|
||||
|
||||
void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
|
||||
|
||||
SkASSERT(ddc);
|
||||
SkASSERT(fDDC);
|
||||
|
||||
GLYPHMETRICS gm;
|
||||
memset(&gm, 0, sizeof(gm));
|
||||
@ -280,7 +293,7 @@ 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(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &mat22);
|
||||
uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
|
||||
|
||||
if (GDI_ERROR != ret) {
|
||||
if (ret == 0) {
|
||||
@ -310,31 +323,31 @@ void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPa
|
||||
if (!(mx || my))
|
||||
return;
|
||||
|
||||
SkASSERT(ddc);
|
||||
SkASSERT(fDDC);
|
||||
|
||||
OUTLINETEXTMETRIC otm;
|
||||
|
||||
uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);
|
||||
uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
|
||||
if (sizeof(otm) != ret) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mx) {
|
||||
mx->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent); // Actually a long.
|
||||
mx->fAscent = -SkIntToScalar(otm.otmAscent);
|
||||
mx->fDescent = -SkIntToScalar(otm.otmDescent);
|
||||
mx->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent); // Long
|
||||
mx->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading
|
||||
+ otm.otmTextMetrics.tmExternalLeading); // Long
|
||||
mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;
|
||||
mx->fAscent = -fScale * otm.otmAscent;
|
||||
mx->fDescent = -fScale * otm.otmDescent;
|
||||
mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;
|
||||
mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
|
||||
+ otm.otmTextMetrics.tmExternalLeading);
|
||||
}
|
||||
|
||||
if (my) {
|
||||
my->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent); // Actually a long.
|
||||
my->fAscent = -SkIntToScalar(otm.otmAscent);
|
||||
my->fDescent = -SkIntToScalar(otm.otmDescent);
|
||||
my->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent); // Long
|
||||
my->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading
|
||||
+ otm.otmTextMetrics.tmExternalLeading); // Long
|
||||
my->fTop = -fScale * otm.otmTextMetrics.tmAscent;
|
||||
my->fAscent = -fScale * otm.otmAscent;
|
||||
my->fDescent = -fScale * otm.otmDescent;
|
||||
my->fBottom = fScale * otm.otmTextMetrics.tmDescent;
|
||||
my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
|
||||
+ otm.otmTextMetrics.tmExternalLeading);
|
||||
}
|
||||
}
|
||||
|
||||
@ -342,7 +355,7 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
|
||||
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
|
||||
SkASSERT(ddc);
|
||||
SkASSERT(fDDC);
|
||||
|
||||
GLYPHMETRICS gm;
|
||||
memset(&gm, 0, sizeof(gm));
|
||||
@ -354,11 +367,11 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
|
||||
#endif
|
||||
|
||||
uint32_t bytecount = 0;
|
||||
uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &mat22);
|
||||
uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
|
||||
if (GDI_ERROR != total_size && total_size > 0) {
|
||||
uint8_t *pBuff = new uint8_t[total_size];
|
||||
if (NULL != pBuff) {
|
||||
total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &mat22);
|
||||
total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &fMat22);
|
||||
|
||||
SkASSERT(total_size != GDI_ERROR);
|
||||
|
||||
@ -402,7 +415,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
|
||||
SkAutoMutexAcquire ac(gFTMutex);
|
||||
|
||||
SkASSERT(&glyph && path);
|
||||
SkASSERT(ddc);
|
||||
SkASSERT(fDDC);
|
||||
|
||||
path->reset();
|
||||
|
||||
@ -413,7 +426,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
|
||||
#endif
|
||||
|
||||
GLYPHMETRICS gm;
|
||||
uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &mat22);
|
||||
uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
|
||||
|
||||
if (GDI_ERROR != total_size) {
|
||||
|
||||
@ -464,26 +477,6 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
|
||||
//OutputDebugString(buf);
|
||||
}
|
||||
|
||||
|
||||
// Note: not sure this is the correct implementation
|
||||
void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) {
|
||||
|
||||
SkASSERT(ddc);
|
||||
|
||||
OUTLINETEXTMETRIC otm;
|
||||
|
||||
uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);
|
||||
|
||||
if (sizeof(otm) == ret) {
|
||||
if (ascent)
|
||||
ascent->iset(0, otm.otmAscent);
|
||||
if (descent)
|
||||
descent->iset(0, otm.otmDescent);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {
|
||||
SkASSERT(!"SkFontHost::Serialize unimplemented");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user