bug 724231 - ensure synthetic font styles under GDI are truly synthetic, rather than using a potentially incompatible font face. r=jdaggett

This commit is contained in:
Jonathan Kew 2012-02-14 08:24:26 +00:00
Родитель a96aef28c1
Коммит d03fa2690f
3 изменённых файлов: 69 добавлений и 22 удалений

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

@ -229,6 +229,12 @@ gfxGDIFont::ShapeWord(gfxContext *aContext,
#endif
}
if (ok && IsSyntheticBold()) {
float synBoldOffset =
GetSyntheticBoldOffset() * CalcXScale(aContext);
aShapedWord->AdjustAdvancesForSyntheticBold(synBoldOffset);
}
return ok;
}
@ -292,6 +298,8 @@ gfxGDIFont::Measure(gfxTextRun *aTextRun,
return metrics;
}
#define OBLIQUE_SKEW_FACTOR 0.3
void
gfxGDIFont::Initialize()
{
@ -322,6 +330,13 @@ gfxGDIFont::Initialize()
}
}
// (bug 724231) for local user fonts, we don't use GDI's synthetic bold,
// as it could lead to a different, incompatible face being used
// but instead do our own multi-striking
if (mNeedsBold && GetFontEntry()->IsLocalUserFont()) {
mApplySyntheticBold = true;
}
// this may end up being zero
mAdjustedSize = ROUND(mAdjustedSize);
FillLogFont(logFont, mAdjustedSize);
@ -434,6 +449,11 @@ gfxGDIFont::Initialize()
SanitizeMetrics(mMetrics, GetFontEntry()->mIsBadUnderlineFont);
}
if (IsSyntheticBold()) {
mMetrics->aveCharWidth += GetSyntheticBoldOffset();
mMetrics->maxAdvance += GetSyntheticBoldOffset();
}
mFontFace = cairo_win32_font_face_create_for_logfontw_hfont(&logFont,
mFont);
@ -441,6 +461,20 @@ gfxGDIFont::Initialize()
cairo_matrix_init_identity(&ctm);
cairo_matrix_init_scale(&sizeMatrix, mAdjustedSize, mAdjustedSize);
bool italic = (mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE));
if (italic && !mFontEntry->IsItalic()) {
double skewfactor = OBLIQUE_SKEW_FACTOR;
cairo_matrix_t style;
cairo_matrix_init(&style,
1, //xx
0, //yx
-1 * skewfactor, //xy
1, //yy
0, //x0
0); //y0
cairo_matrix_multiply(&sizeMatrix, &sizeMatrix, &style);
}
cairo_font_options_t *fontOptions = cairo_font_options_create();
if (mAntialiasOption != kAntialiasDefault) {
cairo_font_options_set_antialias(fontOptions,
@ -482,22 +516,23 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize)
{
GDIFontEntry *fe = static_cast<GDIFontEntry*>(GetFontEntry());
PRUint16 weight = mNeedsBold ? 700 : fe->Weight();
bool italic = (mStyle.style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE));
// if user font, disable italics/bold if defined to be italics/bold face
// this avoids unwanted synthetic italics/bold
if (fe->mIsUserFont) {
if (fe->IsItalic())
italic = false; // avoid synthetic italic
if (fe->IsBold() || !mNeedsBold) {
PRUint16 weight;
if (fe->IsUserFont()) {
if (fe->IsLocalUserFont()) {
// for local user fonts, don't change the original weight
// in the entry's logfont, because that could alter the
// choice of actual face used (bug 724231)
weight = 0;
} else {
// avoid GDI synthetic bold which occurs when weight
// specified is >= font data weight + 200
weight = 200;
weight = mNeedsBold ? 700 : 200;
}
} else {
weight = mNeedsBold ? 700 : fe->Weight();
}
fe->FillLogFont(&aLogFont, italic, weight, aSize,
fe->FillLogFont(&aLogFont, weight, aSize,
(mAntialiasOption == kAntialiasSubpixel) ? true : false);
}

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

@ -322,7 +322,7 @@ GDIFontEntry::GetFontTable(PRUint32 aTableTag,
}
void
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont, bool aItalic,
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
PRUint16 aWeight, gfxFloat aSize,
bool aUseCleartype)
{
@ -330,16 +330,28 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont, bool aItalic,
aLogFont->lfHeight = (LONG)-ROUND(aSize);
if (aLogFont->lfHeight == 0)
if (aLogFont->lfHeight == 0) {
aLogFont->lfHeight = -1;
}
// always force lfItalic if we want it. Font selection code will
// do its best to give us an italic font entry, but if no face exists
// it may give us a regular one based on weight. Windows should
// do fake italic for us in that case.
aLogFont->lfItalic = aItalic;
aLogFont->lfWeight = aWeight;
aLogFont->lfQuality = (aUseCleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY);
// If a non-zero weight is passed in, use this to override the original
// weight in the entry's logfont. This is used to control synthetic bolding
// for installed families with no bold face, and for downloaded fonts
// (but NOT for local user fonts, because it could cause a different,
// glyph-incompatible face to be used)
if (aWeight) {
aLogFont->lfWeight = aWeight;
}
// for non-local() user fonts, we never want to apply italics here;
// if the face is described as italic, we should use it as-is,
// and if it's not, but then the element is styled italic, we'll use
// a cairo transform to create fake italic (oblique)
if (IsUserFont() && !IsLocalUserFont()) {
aLogFont->lfItalic = 0;
}
aLogFont->lfQuality = (aUseCleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY);
}
#define MISSING_GLYPH 0x1F // glyph index returned for missing characters

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

@ -146,8 +146,8 @@ public:
virtual bool IsSymbolFont();
void FillLogFont(LOGFONTW *aLogFont, bool aItalic,
PRUint16 aWeight, gfxFloat aSize, bool aUseCleartype);
void FillLogFont(LOGFONTW *aLogFont, PRUint16 aWeight, gfxFloat aSize,
bool aUseCleartype);
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
DWORD fontType)