bug 594889 - improve glyph spacing with DirectWrite fonts when ClearType is disabled by using GDI-compatible instead of 'ideal' metrics. r=bas a=blocking2.0

This commit is contained in:
Jonathan Kew 2011-01-04 16:58:31 +00:00
parent 8056d8607f
commit 20bd210d2f
3 changed files with 134 additions and 20 deletions

View File

@ -68,6 +68,51 @@ GetCairoAntialiasOption(gfxFont::AntialiasOption anAntialiasOption)
}
}
// Code to determine whether Windows is set to use ClearType font smoothing;
// based on private functions in cairo-win32-font.c
#ifndef SPI_GETFONTSMOOTHINGTYPE
#define SPI_GETFONTSMOOTHINGTYPE 0x200a
#endif
#ifndef FE_FONTSMOOTHINGCLEARTYPE
#define FE_FONTSMOOTHINGCLEARTYPE 2
#endif
static bool
HasClearType()
{
OSVERSIONINFO versionInfo;
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
return (GetVersionEx(&versionInfo) &&
(versionInfo.dwMajorVersion > 5 ||
(versionInfo.dwMajorVersion == 5 &&
versionInfo.dwMinorVersion >= 1))); // XP or newer
}
static bool
UsingClearType()
{
BOOL fontSmoothing;
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &fontSmoothing, 0) ||
!fontSmoothing)
{
return false;
}
if (!HasClearType()) {
return false;
}
UINT type;
if (SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, &type, 0) &&
type == FE_FONTSMOOTHINGCLEARTYPE)
{
return true;
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
// gfxDWriteFont
gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
@ -79,6 +124,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
, mCairoScaledFont(nsnull)
, mNeedsOblique(PR_FALSE)
, mNeedsBold(aNeedsBold)
, mUsingClearType(PR_FALSE)
{
gfxDWriteFontEntry *fe =
static_cast<gfxDWriteFontEntry*>(aFontEntry);
@ -101,6 +147,12 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
return;
}
if ((anAAOption == gfxFont::kAntialiasDefault && UsingClearType()) ||
anAAOption == gfxFont::kAntialiasSubpixel)
{
mUsingClearType = PR_TRUE;
}
ComputeMetrics();
if (FontCanSupportHarfBuzz()) {
@ -427,3 +479,29 @@ gfxDWriteFont::GetFontTable(PRUint32 aTag)
return nsnull;
}
PRInt32
gfxDWriteFont::GetHintedGlyphWidth(gfxContext *aCtx, PRUint16 aGID)
{
if (!mGlyphWidths.IsInitialized()) {
mGlyphWidths.Init(200);
}
PRInt32 width;
if (mGlyphWidths.Get(aGID, &width)) {
return width;
}
DWRITE_GLYPH_METRICS glyphMetrics;
HRESULT hr = mFontFace->GetGdiCompatibleGlyphMetrics(
GetAdjustedSize(), 1.0f, nsnull, TRUE,
&aGID, 1, &glyphMetrics, FALSE);
if (NS_SUCCEEDED(hr)) {
width = NS_lround(glyphMetrics.advanceWidth * mFUnitsConvFactor) << 16;
mGlyphWidths.Put(aGID, width);
return width;
}
return -1;
}

View File

@ -79,6 +79,12 @@ public:
// use DWrite API to get direct access to system font data
virtual hb_blob_t *GetFontTable(PRUint32 aTag);
virtual PRBool ProvidesHintedWidths() const {
return !mUsingClearType;
}
virtual PRInt32 GetHintedGlyphWidth(gfxContext *aCtx, PRUint16 aGID);
protected:
virtual void CreatePlatformShaper();
@ -95,8 +101,13 @@ protected:
cairo_scaled_font_t *mCairoScaledFont;
gfxFont::Metrics mMetrics;
PRBool mNeedsOblique;
PRBool mNeedsBold;
// cache of glyph widths in 16.16 fixed-point pixels
nsDataHashtable<nsUint32HashKey,PRInt32> mGlyphWidths;
PRPackedBool mNeedsOblique;
PRPackedBool mNeedsBold;
PRPackedBool mUsingClearType;
};
#endif

View File

@ -175,24 +175,49 @@ trymoreglyphs:
continue;
}
hr = analyzer->GetGlyphPlacements(aString + range.start,
clusters.Elements(),
textProperties.Elements(),
range.Length(),
indices.Elements(),
glyphProperties.Elements(),
actualGlyphs,
font->GetFontFace(),
font->GetAdjustedSize(),
FALSE,
FALSE,
&runHead->mScript,
NULL,
NULL,
NULL,
0,
advances.Elements(),
glyphOffsets.Elements());
if (mFont->ProvidesHintedWidths()) {
hr = analyzer->GetGdiCompatibleGlyphPlacements(
aString + range.start,
clusters.Elements(),
textProperties.Elements(),
range.Length(),
indices.Elements(),
glyphProperties.Elements(),
actualGlyphs,
font->GetFontFace(),
font->GetAdjustedSize(),
1.0,
nsnull,
TRUE,
FALSE,
FALSE,
&runHead->mScript,
NULL,
NULL,
NULL,
0,
advances.Elements(),
glyphOffsets.Elements());
} else {
hr = analyzer->GetGlyphPlacements(aString + range.start,
clusters.Elements(),
textProperties.Elements(),
range.Length(),
indices.Elements(),
glyphProperties.Elements(),
actualGlyphs,
font->GetFontFace(),
font->GetAdjustedSize(),
FALSE,
FALSE,
&runHead->mScript,
NULL,
NULL,
NULL,
0,
advances.Elements(),
glyphOffsets.Elements());
}
if (FAILED(hr)) {
NS_WARNING("Analyzer failed to get glyph placements.");
result = PR_FALSE;