speeding up gfxWindowsFont::ComputeMetrics. bug 342366. r=vlad

This commit is contained in:
pavlov%pavlov.net 2006-07-12 22:02:46 +00:00
Родитель 65a9f99929
Коммит 607772909f
2 изменённых файлов: 61 добавлений и 55 удалений

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

@ -362,14 +362,15 @@ public:
virtual const gfxFont::Metrics& GetMetrics();
HFONT GetHFONT();
cairo_font_face_t *CairoFontFace();
cairo_scaled_font_t *CairoScaledFont();
SCRIPT_CACHE *ScriptCache() { return &mScriptCache; }
HFONT GetHFONT() { return mFont; }
const gfxMatrix& CurrentMatrix() const { return mCTM; }
void UpdateCTM(const gfxMatrix& aMatrix);
protected:
HFONT MakeHFONT();
cairo_font_face_t *MakeCairoFontFace();
cairo_scaled_font_t *MakeCairoScaledFont();
void FillLogFont(PRInt16 weight);

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

@ -116,6 +116,17 @@ gfxWindowsFont::GetMetrics()
return *mMetrics;
}
HFONT
gfxWindowsFont::GetHFONT()
{
if (!mFont)
mFont = MakeHFONT();
NS_ASSERTION(mFont, "Failed to make HFONT");
return mFont;
}
cairo_font_face_t *
gfxWindowsFont::CairoFontFace()
{
@ -149,11 +160,11 @@ gfxWindowsFont::UpdateCTM(const gfxMatrix& aMatrix)
mCTM = aMatrix;
}
cairo_font_face_t *
gfxWindowsFont::MakeCairoFontFace()
HFONT
gfxWindowsFont::MakeHFONT()
{
if (mFont)
return cairo_win32_font_face_create_for_hfont(mFont);
return mFont;
if (!mWeightTable) {
nsString name(mName);
@ -230,6 +241,15 @@ gfxWindowsFont::MakeCairoFontFace()
if (dc)
ReleaseDC((HWND)nsnull, dc);
return mFont;
}
cairo_font_face_t *
gfxWindowsFont::MakeCairoFontFace()
{
// ensure mFont is around
MakeHFONT();
return cairo_win32_font_face_create_for_hfont(mFont);
}
@ -257,77 +277,62 @@ gfxWindowsFont::ComputeMetrics()
HDC dc = GetDC((HWND)nsnull);
SaveDC(dc);
HFONT font = GetHFONT();
cairo_scaled_font_t *scaledFont = CairoScaledFont();
cairo_win32_scaled_font_select_font(scaledFont, dc);
const double cairofontfactor = cairo_win32_scaled_font_get_metrics_factor(scaledFont);
const double multiplier = cairofontfactor * mStyle->size;
HGDIOBJ oldFont = SelectObject(dc, font);
// Get font metrics
OUTLINETEXTMETRIC oMetrics;
TEXTMETRIC& metrics = oMetrics.otmTextMetrics;
gfxFloat descentPos = 0;
if (0 < ::GetOutlineTextMetrics(dc, sizeof(oMetrics), &oMetrics)) {
// mXHeight = ROUND(oMetrics.otmsXHeight * mDev2App); XXX not really supported on windows
mMetrics->xHeight = ROUND((double)metrics.tmAscent * multiplier * 0.56); // 50% of ascent, best guess for true type
mMetrics->superscriptOffset = ROUND((double)oMetrics.otmptSuperscriptOffset.y * multiplier);
mMetrics->subscriptOffset = ROUND((double)oMetrics.otmptSubscriptOffset.y * multiplier);
if (0 < GetOutlineTextMetrics(dc, sizeof(oMetrics), &oMetrics)) {
mMetrics->superscriptOffset = (double)oMetrics.otmptSuperscriptOffset.y;
mMetrics->subscriptOffset = (double)oMetrics.otmptSubscriptOffset.y;
mMetrics->strikeoutSize = PR_MAX(1, (double)oMetrics.otmsStrikeoutSize);
mMetrics->strikeoutOffset = (double)oMetrics.otmsStrikeoutPosition;
mMetrics->underlineSize = PR_MAX(1, (double)oMetrics.otmsUnderscoreSize);
mMetrics->underlineOffset = (double)oMetrics.otmsUnderscorePosition;
mMetrics->strikeoutSize = PR_MAX(1, ROUND((double)oMetrics.otmsStrikeoutSize * multiplier));
mMetrics->strikeoutOffset = ROUND((double)oMetrics.otmsStrikeoutPosition * multiplier);
mMetrics->underlineSize = PR_MAX(1, ROUND((double)oMetrics.otmsUnderscoreSize * multiplier));
mMetrics->underlineOffset = ROUND((double)oMetrics.otmsUnderscorePosition * multiplier);
// Begin -- section of code to get the real x-height with GetGlyphOutline()
const MAT2 kIdentityMatrix = { {0, 1}, {0, 0}, {0, 0}, {0, 1} };
GLYPHMETRICS gm;
MAT2 mMat = { 1, 0, 0, 1 }; // glyph transform matrix (always identity in our context)
DWORD len = GetGlyphOutlineW(dc, PRUnichar('x'), GGO_METRICS, &gm, 0, nsnull, &mMat);
if (GDI_ERROR != len && gm.gmptGlyphOrigin.y > 0) {
mMetrics->xHeight = ROUND(gm.gmptGlyphOrigin.y * multiplier);
DWORD len = GetGlyphOutlineW(dc, PRUnichar('x'), GGO_METRICS, &gm, 0, nsnull, &kIdentityMatrix);
if (len == GDI_ERROR || gm.gmptGlyphOrigin.y <= 0) {
// 56% of ascent, best guess for true type
mMetrics->xHeight = ROUND((double)metrics.tmAscent * 0.56);
} else {
mMetrics->xHeight = gm.gmptGlyphOrigin.y;
}
// End -- getting x-height
}
else {
} else {
// Make a best-effort guess at extended metrics
// this is based on general typographic guidelines
::GetTextMetrics(dc, &metrics);
GetTextMetrics(dc, &metrics);
mMetrics->xHeight = ROUND((float)metrics.tmAscent * 0.56f); // 56% of ascent, best guess for non-true type
mMetrics->superscriptOffset = mMetrics->xHeight; // XXX temporary code!
mMetrics->subscriptOffset = mMetrics->xHeight; // XXX temporary code!
mMetrics->strikeoutSize = 1; // XXX this is a guess
mMetrics->superscriptOffset = mMetrics->xHeight;
mMetrics->subscriptOffset = mMetrics->xHeight;
mMetrics->strikeoutSize = 1;
mMetrics->strikeoutOffset = ROUND(mMetrics->xHeight / 2.0f); // 50% of xHeight
mMetrics->underlineSize = 1; // XXX this is a guess
mMetrics->underlineSize = 1;
mMetrics->underlineOffset = -ROUND((float)metrics.tmDescent * 0.30f); // 30% of descent
}
mMetrics->internalLeading = ROUND(metrics.tmInternalLeading * multiplier);
mMetrics->externalLeading = ROUND(metrics.tmExternalLeading * multiplier);
mMetrics->emHeight = ROUND((metrics.tmHeight - metrics.tmInternalLeading) * multiplier);
mMetrics->emAscent = ROUND((metrics.tmAscent - metrics.tmInternalLeading) * multiplier);
mMetrics->emDescent = ROUND(metrics.tmDescent * multiplier);
mMetrics->maxHeight = ROUND(metrics.tmHeight * multiplier);
mMetrics->maxAscent = ROUND(metrics.tmAscent * multiplier);
mMetrics->maxDescent = ROUND(metrics.tmDescent * multiplier);
mMetrics->maxAdvance = ROUND(metrics.tmMaxCharWidth * multiplier);
mMetrics->aveCharWidth = PR_MAX(1, ROUND(metrics.tmAveCharWidth * multiplier));
mMetrics->internalLeading = metrics.tmInternalLeading;
mMetrics->externalLeading = metrics.tmExternalLeading;
mMetrics->emHeight = (metrics.tmHeight - metrics.tmInternalLeading);
mMetrics->emAscent = (metrics.tmAscent - metrics.tmInternalLeading);
mMetrics->emDescent = metrics.tmDescent;
mMetrics->maxHeight = metrics.tmHeight;
mMetrics->maxAscent = metrics.tmAscent;
mMetrics->maxDescent = metrics.tmDescent;
mMetrics->maxAdvance = metrics.tmMaxCharWidth;
mMetrics->aveCharWidth = PR_MAX(1, metrics.tmAveCharWidth);
// Cache the width of a single space.
SIZE size;
::GetTextExtentPoint32(dc, " ", 1, &size);
//size.cx -= font->mOverhangCorrection;
mMetrics->spaceWidth = ROUND(size.cx * multiplier);
GetTextExtentPoint32(dc, " ", 1, &size);
mMetrics->spaceWidth = ROUND(size.cx);
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(dc, -1);
SelectObject(dc, oldFont);
ReleaseDC((HWND)nsnull, dc);
}