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:
reed@google.com 2011-03-01 15:18:14 +00:00
parent f9bb7a8e20
commit b652427197
2 changed files with 85 additions and 101 deletions

View File

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

View File

@ -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");
}