зеркало из https://github.com/mozilla/pjs.git
speeding up gfxWindowsFont::ComputeMetrics. bug 342366. r=vlad
This commit is contained in:
Родитель
65a9f99929
Коммит
607772909f
|
@ -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);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче