Bug 814101: Respect system-wide cleartype setting. r=jrmuizel,jfkthame

This commit is contained in:
Bas Schouten 2012-11-23 02:53:12 +01:00
Родитель c2caba3ae9
Коммит b084ef8c84
6 изменённых файлов: 164 добавлений и 13 удалений

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

@ -73,7 +73,7 @@ struct DrawOptions {
Float mAlpha;
CompositionOp mCompositionOp : 8;
AntialiasMode mAntialiasMode : 2;
AntialiasMode mAntialiasMode : 3;
Snapping mSnapping : 1;
};

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

@ -900,8 +900,15 @@ DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
}
}
AntialiasMode aaMode = font->GetDefaultAAMode();
if (aOptions.mAntialiasMode != AA_DEFAULT) {
aaMode = aOptions.mAntialiasMode;
}
if (mFormat == FORMAT_B8G8R8A8 && mPermitSubpixelAA &&
aOptions.mCompositionOp == OP_OVER && aPattern.GetType() == PATTERN_COLOR) {
aOptions.mCompositionOp == OP_OVER && aPattern.GetType() == PATTERN_COLOR &&
aaMode == AA_SUBPIXEL) {
if (FillGlyphsManual(font, aBuffer,
static_cast<const ColorPattern*>(&aPattern)->mColor,
params, aOptions)) {
@ -913,6 +920,29 @@ DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
PrepareForDrawing(rt);
D2D1_TEXT_ANTIALIAS_MODE d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
switch (aaMode) {
case AA_NONE:
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_ALIASED;
break;
case AA_GRAY:
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
break;
case AA_SUBPIXEL:
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE;
break;
default:
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_DEFAULT;
}
if (d2dAAMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE &&
mFormat != FORMAT_B8G8R8X8) {
d2dAAMode = D2D1_TEXT_ANTIALIAS_MODE_GRAYSCALE;
}
rt->SetTextAntialiasMode(d2dAAMode);
if (rt != mRT || params != mTextRenderingParams) {
rt->SetTextRenderingParams(params);
if (rt == mRT) {

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

@ -138,7 +138,80 @@ public:
private:
std::vector<uint8_t> mData;
uint32_t mRefCnt;
};
};
static BYTE
GetSystemTextQuality()
{
BOOL font_smoothing;
UINT smoothing_type;
if (!SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) {
return DEFAULT_QUALITY;
}
if (font_smoothing) {
if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE,
0, &smoothing_type, 0)) {
return DEFAULT_QUALITY;
}
if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) {
return CLEARTYPE_QUALITY;
}
return ANTIALIASED_QUALITY;
}
return DEFAULT_QUALITY;
}
#define GASP_TAG 0x70736167
#define GASP_DOGRAY 0x2
static inline unsigned short
readShort(const char *aBuf)
{
return (*aBuf << 8) | *(aBuf + 1);
}
static bool
DoGrayscale(IDWriteFontFace *aDWFace, unsigned int ppem)
{
void *tableContext;
char *tableData;
UINT32 tableSize;
BOOL exists;
aDWFace->TryGetFontTable(GASP_TAG, (const void**)&tableData, &tableSize, &tableContext, &exists);
if (exists) {
if (tableSize < 4) {
aDWFace->ReleaseFontTable(tableContext);
return true;
}
struct gaspRange {
unsigned short maxPPEM; // Stored big-endian
unsigned short behavior; // Stored big-endian
};
unsigned short numRanges = readShort(tableData + 2);
if (tableSize < (UINT)4 + numRanges * 4) {
aDWFace->ReleaseFontTable(tableContext);
return true;
}
gaspRange *ranges = (gaspRange *)(tableData + 4);
for (int i = 0; i < numRanges; i++) {
if (readShort((char*)&ranges[i].maxPPEM) > ppem) {
if (!(readShort((char*)&ranges[i].behavior) & GASP_DOGRAY)) {
aDWFace->ReleaseFontTable(tableContext);
return false;
}
break;
}
}
aDWFace->ReleaseFontTable(tableContext);
}
return true;
}
IDWriteFontFileLoader* DWriteFontFileLoader::mInstance = NULL;
@ -322,5 +395,30 @@ ScaledFontDWrite::GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton
return true;
}
AntialiasMode
ScaledFontDWrite::GetDefaultAAMode()
{
AntialiasMode defaultMode = AA_SUBPIXEL;
switch (GetSystemTextQuality()) {
case CLEARTYPE_QUALITY:
defaultMode = AA_SUBPIXEL;
break;
case ANTIALIASED_QUALITY:
defaultMode = AA_GRAY;
break;
case DEFAULT_QUALITY:
defaultMode = AA_NONE;
break;
}
if (defaultMode == AA_GRAY) {
if (!DoGrayscale(mFontFace, mSize)) {
defaultMode = AA_NONE;
}
}
return defaultMode;
}
}
}

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

@ -32,6 +32,8 @@ public:
virtual bool GetFontFileData(FontFileDataOutput aDataCallback, void *aBaton);
virtual AntialiasMode GetDefaultAAMode();
#ifdef USE_SKIA
virtual SkTypeface* GetSkTypeface()
{

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

@ -87,7 +87,7 @@ enum FontStyle
enum CompositionOp { OP_OVER, OP_ADD, OP_ATOP, OP_OUT, OP_IN, OP_SOURCE, OP_DEST_IN, OP_DEST_OUT, OP_DEST_OVER, OP_DEST_ATOP, OP_XOR, OP_COUNT };
enum ExtendMode { EXTEND_CLAMP, EXTEND_REPEAT, EXTEND_REFLECT };
enum FillRule { FILL_WINDING, FILL_EVEN_ODD };
enum AntialiasMode { AA_NONE, AA_GRAY, AA_SUBPIXEL };
enum AntialiasMode { AA_NONE, AA_GRAY, AA_SUBPIXEL, AA_DEFAULT };
enum Snapping { SNAP_NONE, SNAP_ALIGNED };
enum Filter { FILTER_LINEAR, FILTER_POINT };
enum PatternType { PATTERN_COLOR, PATTERN_SURFACE, PATTERN_LINEAR_GRADIENT, PATTERN_RADIAL_GRADIENT };

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

@ -1577,6 +1577,19 @@ struct GlyphBuffer {
#undef GLYPH_BUFFER_SIZE
};
static AntialiasMode Get2DAAMode(gfxFont::AntialiasOption aAAOption) {
switch (aAAOption) {
case gfxFont::kAntialiasSubpixel:
return AA_SUBPIXEL;
case gfxFont::kAntialiasGrayscale:
return AA_GRAY;
case gfxFont::kAntialiasNone:
return AA_NONE;
default:
return AA_DEFAULT;
}
}
struct GlyphBufferAzure {
#define GLYPH_BUFFER_SIZE (2048/sizeof(Glyph))
Glyph mGlyphBuffer[GLYPH_BUFFER_SIZE];
@ -1591,7 +1604,8 @@ struct GlyphBufferAzure {
void Flush(DrawTarget *aDT, gfxTextObjectPaint *aObjectPaint, ScaledFont *aFont,
gfxFont::DrawMode aDrawMode, bool aReverse, const GlyphRenderingOptions *aOptions,
gfxContext *aThebesContext, const Matrix *aInvFontMatrix, bool aFinish = false)
gfxContext *aThebesContext, const Matrix *aInvFontMatrix, const DrawOptions &aDrawOptions,
bool aFinish = false)
{
// Ensure there's enough room for a glyph to be added to the buffer
if ((!aFinish && mNumGlyphs < GLYPH_BUFFER_SIZE) || !mNumGlyphs) {
@ -1645,7 +1659,7 @@ struct GlyphBufferAzure {
}
aDT->FillGlyphs(aFont, buf, *pat,
DrawOptions(), aOptions);
aDrawOptions, aOptions);
if (mat) {
*mat = saved;
@ -1654,10 +1668,10 @@ struct GlyphBufferAzure {
aDT->FillGlyphs(aFont, buf, SurfacePattern(state.sourceSurface,
EXTEND_CLAMP,
state.surfTransform),
DrawOptions(), aOptions);
aDrawOptions, aOptions);
} else {
aDT->FillGlyphs(aFont, buf, ColorPattern(state.color),
DrawOptions(), aOptions);
aDrawOptions, aOptions);
}
}
if (aDrawMode & gfxFont::GLYPH_PATH) {
@ -1930,6 +1944,9 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
RefPtr<GlyphRenderingOptions> renderingOptions =
GetGlyphRenderingOptions();
DrawOptions drawOptions;
drawOptions.mAntialiasMode = Get2DAAMode(mAntialiasOption);
if (mScaledFont) {
cairo_matrix_t matrix;
cairo_scaled_font_get_font_matrix(mScaledFont, &matrix);
@ -1992,7 +2009,8 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
glyph->mPosition = matInv * glyph->mPosition;
glyphs.Flush(dt, aObjectPaint, scaledFont,
aDrawMode, isRTL, renderingOptions,
aContext, passedInvMatrix);
aContext, passedInvMatrix,
drawOptions);
// synthetic bolding by multi-striking with 1-pixel offsets
// at least once, more if there's room (large font sizes)
@ -2011,7 +2029,8 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
strikeOffset += synBoldOnePixelOffset;
glyphs.Flush(dt, aObjectPaint, scaledFont,
aDrawMode, isRTL, renderingOptions,
aContext, passedInvMatrix);
aContext, passedInvMatrix,
drawOptions);
} while (--strikeCount > 0);
}
} else {
@ -2057,7 +2076,8 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
glyph->mPosition.y = ToDeviceUnits(y + details->mYOffset, devUnitsPerAppUnit);
glyph->mPosition = matInv * glyph->mPosition;
glyphs.Flush(dt, aObjectPaint, scaledFont, aDrawMode,
isRTL, renderingOptions, aContext, passedInvMatrix);
isRTL, renderingOptions, aContext, passedInvMatrix,
drawOptions);
if (IsSyntheticBold()) {
double strikeOffset = synBoldOnePixelOffset;
@ -2075,7 +2095,7 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
doubleglyph->mPosition = matInv * doubleglyph->mPosition;
glyphs.Flush(dt, aObjectPaint, scaledFont,
aDrawMode, isRTL, renderingOptions,
aContext, passedInvMatrix);
aContext, passedInvMatrix, drawOptions);
} while (--strikeCount > 0);
}
}
@ -2095,7 +2115,8 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
}
glyphs.Flush(dt, aObjectPaint, scaledFont, aDrawMode, isRTL,
renderingOptions, aContext, passedInvMatrix, true);
renderingOptions, aContext, passedInvMatrix,
drawOptions, true);
dt->SetTransform(oldMat);