Bug 661471. Part 1: Create preference to force particular font families to use 'GDI Classic' rendering with DirectWrite. r=jdaggett,jfkthame

This commit is contained in:
Robert O'Callahan 2011-06-03 16:31:07 +12:00
parent 758cd772ae
commit 0e9af9395b
11 changed files with 150 additions and 47 deletions

View File

@ -78,7 +78,7 @@ typedef struct _cairo_d2d_device cairo_d2d_device_t;
struct _cairo_d2d_surface {
_cairo_d2d_surface() : d2d_clip(NULL), clipping(false), isDrawing(false),
textRenderingInit(false)
textRenderingState(TEXT_RENDERING_UNINITIALIZED)
{
_cairo_clip_init (&this->clip);
}
@ -128,7 +128,12 @@ struct _cairo_d2d_surface {
/** Indicates if our render target is currently in drawing mode */
bool isDrawing;
/** Indicates if text rendering is initialized */
bool textRenderingInit;
enum TextRenderingState {
TEXT_RENDERING_UNINITIALIZED,
TEXT_RENDERING_NORMAL,
TEXT_RENDERING_GDI_CLASSIC
};
TextRenderingState textRenderingState;
RefPtr<ID3D10RenderTargetView> buffer_rt_view;
RefPtr<ID3D10ShaderResourceView> buffer_sr_view;

View File

@ -4109,10 +4109,16 @@ _cairo_d2d_show_glyphs (void *surface,
return CAIRO_INT_STATUS_UNSUPPORTED;
}
cairo_d2d_surface_t *d2dsurf = static_cast<cairo_d2d_surface_t*>(surface);
if (!d2dsurf->textRenderingInit) {
RefPtr<IDWriteRenderingParams> params = DWriteFactory::RenderingParams();
cairo_bool_t forceGDIClassic =
scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE &&
reinterpret_cast<cairo_dwrite_scaled_font_t*>(scaled_font)->force_GDI_classic;
cairo_d2d_surface_t::TextRenderingState textRenderingState =
(forceGDIClassic ? cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC : cairo_d2d_surface_t::TEXT_RENDERING_NORMAL);
if (d2dsurf->textRenderingState != textRenderingState) {
RefPtr<IDWriteRenderingParams> params =
DWriteFactory::RenderingParams(forceGDIClassic);
d2dsurf->rt->SetTextRenderingParams(params);
d2dsurf->textRenderingInit = true;
d2dsurf->textRenderingState = textRenderingState;
}
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {

View File

@ -66,6 +66,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
DWRITE_MATRIX *transform,
DWRITE_GLYPH_RUN *run,
COLORREF color,
cairo_dwrite_scaled_font_t *scaled_font,
const RECT &area);
class D2DFactory
@ -119,6 +120,7 @@ private:
IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
IDWriteRenderingParams *DWriteFactory::mRenderingParams = NULL;
IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL;
FLOAT DWriteFactory::mGamma = -1.0;
FLOAT DWriteFactory::mEnhancedContrast = -1.0;
FLOAT DWriteFactory::mClearTypeLevel = -1.0;
@ -494,6 +496,7 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
}
dwriteFont->manual_show_glyphs_allowed = TRUE;
dwriteFont->force_GDI_classic = FALSE;
return _cairo_scaled_font_set_metrics (*font, &extents);
}
@ -991,7 +994,8 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
DWRITE_MATRIX matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
status = _dwrite_draw_glyphs_to_gdi_surface_gdi (surface, &matrix, &run, RGB(0,0,0), area);
status = _dwrite_draw_glyphs_to_gdi_surface_gdi (surface, &matrix, &run,
RGB(0,0,0), scaled_font, area);
if (status)
goto FAIL;
@ -1069,12 +1073,26 @@ cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrit
}
void
cairo_dwrite_scaled_font_allow_manual_show_glyphs(void* dwrite_scaled_font, cairo_bool_t allowed)
cairo_dwrite_scaled_font_allow_manual_show_glyphs(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed)
{
cairo_dwrite_scaled_font_t *font = static_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
font->manual_show_glyphs_allowed = allowed;
}
void
cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force)
{
cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
font->force_GDI_classic = force;
}
cairo_bool_t
cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font)
{
cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
return font->force_GDI_classic;
}
void
cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level,
int geometry, int mode)
@ -1087,13 +1105,15 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
DWRITE_MATRIX *transform,
DWRITE_GLYPH_RUN *run,
COLORREF color,
cairo_dwrite_scaled_font_t *scaled_font,
const RECT &area)
{
IDWriteGdiInterop *gdiInterop;
DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
IDWriteBitmapRenderTarget *rt;
IDWriteRenderingParams *params = DWriteFactory::RenderingParams();
IDWriteRenderingParams *params =
DWriteFactory::RenderingParams(scaled_font->force_GDI_classic);
gdiInterop->CreateBitmapRenderTarget(surface->dc,
area.right - area.left,
@ -1141,6 +1161,8 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget();
// XXX don't we need to set RenderingParams on this RenderTarget?
rv = rt->BindDC(surface->dc, &area);
printf("Rendering to surface: %p\n", surface->dc);
@ -1369,6 +1391,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
mat,
&run,
color,
dwritesf,
fontArea);
#ifdef CAIRO_TRY_D2D_TO_GDI
}
@ -1413,15 +1436,22 @@ DWriteFactory::CreateRenderingParams()
// For parameters that have not been explicitly set via the SetRenderingParams API,
// we copy values from default params (or our overridden value for contrast)
Instance()->CreateCustomRenderingParams(
mGamma >= 1.0 && mGamma <= 2.2 ? mGamma : defaultParams->GetGamma(),
contrast,
mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ? mClearTypeLevel : defaultParams->GetClearTypeLevel(),
mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
(DWRITE_PIXEL_GEOMETRY)mPixelGeometry : defaultParams->GetPixelGeometry(),
mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
(DWRITE_RENDERING_MODE)mRenderingMode : defaultParams->GetRenderingMode(),
FLOAT gamma =
mGamma >= 1.0 && mGamma <= 2.2 ? mGamma : defaultParams->GetGamma();
FLOAT clearTypeLevel =
mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ? mClearTypeLevel : defaultParams->GetClearTypeLevel();
DWRITE_PIXEL_GEOMETRY pixelGeometry =
mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
(DWRITE_PIXEL_GEOMETRY)mPixelGeometry : defaultParams->GetPixelGeometry();
DWRITE_RENDERING_MODE renderingMode =
mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
(DWRITE_RENDERING_MODE)mRenderingMode : defaultParams->GetRenderingMode();
Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
pixelGeometry, renderingMode,
&mRenderingParams);
Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
&mForceGDIClassicRenderingParams);
}
// Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent

View File

@ -44,6 +44,17 @@ typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
__out IUnknown **factory
);
/* cairo_scaled_font_t implementation */
struct _cairo_dwrite_scaled_font {
cairo_scaled_font_t base;
cairo_matrix_t mat;
cairo_matrix_t mat_inverse;
cairo_antialias_t antialias_mode;
DWRITE_MEASURING_MODE measuring_mode;
cairo_bool_t manual_show_glyphs_allowed;
cairo_bool_t force_GDI_classic;
};
typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
class DWriteFactory
{
@ -92,15 +103,17 @@ public:
return family;
}
static IDWriteRenderingParams *RenderingParams()
static IDWriteRenderingParams *RenderingParams(cairo_bool_t forceGDIClassic)
{
if (!mRenderingParams) {
if (!mRenderingParams || !mForceGDIClassicRenderingParams) {
CreateRenderingParams();
}
if (mRenderingParams) {
mRenderingParams->AddRef();
IDWriteRenderingParams *params =
forceGDIClassic ? mForceGDIClassicRenderingParams : mRenderingParams;
if (params) {
params->AddRef();
}
return mRenderingParams;
return params;
}
static void SetRenderingParams(FLOAT aGamma,
@ -119,6 +132,10 @@ public:
mRenderingParams->Release();
mRenderingParams = NULL;
}
if (mForceGDIClassicRenderingParams) {
mForceGDIClassicRenderingParams->Release();
mForceGDIClassicRenderingParams = NULL;
}
}
private:
@ -127,6 +144,7 @@ private:
static IDWriteFactory *mFactoryInstance;
static IDWriteFontCollection *mSystemCollection;
static IDWriteRenderingParams *mRenderingParams;
static IDWriteRenderingParams *mForceGDIClassicRenderingParams;
static FLOAT mGamma;
static FLOAT mEnhancedContrast;
static FLOAT mClearTypeLevel;
@ -142,17 +160,6 @@ struct _cairo_dwrite_font_face {
};
typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
/* cairo_scaled_font_t implementation */
struct _cairo_dwrite_scaled_font {
cairo_scaled_font_t base;
cairo_matrix_t mat;
cairo_matrix_t mat_inverse;
cairo_antialias_t antialias_mode;
DWRITE_MEASURING_MODE measuring_mode;
cairo_bool_t manual_show_glyphs_allowed;
};
typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix);
// This will create a DWrite glyph run from cairo glyphs and a scaled_font.

View File

@ -124,7 +124,13 @@ cairo_public cairo_font_face_t *
cairo_dwrite_font_face_create_for_dwrite_fontface(void *dwrite_font, void *dwrite_font_face);
void
cairo_dwrite_scaled_font_allow_manual_show_glyphs(void *dwrite_scaled_font, cairo_bool_t allowed);
cairo_dwrite_scaled_font_allow_manual_show_glyphs(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed);
void
cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force);
cairo_bool_t
cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font);
void
cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);

View File

@ -45,6 +45,7 @@
#include "nsIPrefService.h"
#include "nsIPrefBranch2.h"
#include "nsServiceManagerUtils.h"
#include "nsCharSeparatedTokenizer.h"
#include "gfxGDIFontList.h"
@ -156,6 +157,7 @@ gfxDWriteFontFamily::FindStyleVariations()
*/
gfxDWriteFontEntry *fe =
new gfxDWriteFontEntry(fullID, font);
fe->SetForceGDIClassic(mForceGDIClassic);
AddFontEntry(fe);
#ifdef PR_LOGGING
@ -950,6 +952,23 @@ gfxDWriteFontList::DelayedInitFontList()
}
}
nsCOMPtr<nsIPrefBranch2> pref = do_GetService(NS_PREFSERVICE_CONTRACTID);
nsXPIDLCString classicFamilies;
nsresult rv = pref->GetCharPref(
"gfx.font_rendering.cleartype_params.force_gdi_classic_for_families",
getter_Copies(classicFamilies));
if (NS_SUCCEEDED(rv)) {
nsCCharSeparatedTokenizer tokenizer(classicFamilies, ',');
while (tokenizer.hasMoreTokens()) {
NS_ConvertUTF8toUTF16 name(tokenizer.nextToken());
BuildKeyNameFromFontName(name);
gfxFontFamily *family = mFontFamilies.GetWeak(name);
if (family) {
static_cast<gfxDWriteFontFamily*>(family)->SetForceGDIClassic(true);
}
}
}
StartLoader(kDelayBeforeLoadingFonts, kIntervalBetweenLoadingFonts);
LOGREGISTRY(L"DelayedInitFontList end");

View File

@ -68,16 +68,20 @@ public:
* family object.
*/
gfxDWriteFontFamily(const nsAString& aName,
IDWriteFontFamily *aFamily)
: gfxFontFamily(aName), mDWFamily(aFamily) {}
IDWriteFontFamily *aFamily)
: gfxFontFamily(aName), mDWFamily(aFamily), mForceGDIClassic(false) {}
virtual ~gfxDWriteFontFamily();
virtual void FindStyleVariations();
virtual void LocalizedName(nsAString& aLocalizedName);
virtual void LocalizedName(nsAString& aLocalizedName);
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
protected:
/** This font family's directwrite fontfamily object */
nsRefPtr<IDWriteFontFamily> mDWFamily;
bool mForceGDIClassic;
};
/**
@ -94,7 +98,8 @@ public:
*/
gfxDWriteFontEntry(const nsAString& aFaceName,
IDWriteFont *aFont)
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nsnull)
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nsnull),
mForceGDIClassic(false)
{
mItalic = (aFont->GetStyle() == DWRITE_FONT_STYLE_ITALIC ||
aFont->GetStyle() == DWRITE_FONT_STYLE_OBLIQUE);
@ -124,7 +129,8 @@ public:
PRUint16 aWeight,
PRInt16 aStretch,
PRBool aItalic)
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nsnull)
: gfxFontEntry(aFaceName), mFont(aFont), mFontFile(nsnull),
mForceGDIClassic(false)
{
mWeight = aWeight;
mStretch = aStretch;
@ -148,7 +154,8 @@ public:
PRUint16 aWeight,
PRInt16 aStretch,
PRBool aItalic)
: gfxFontEntry(aFaceName), mFont(nsnull), mFontFile(aFontFile)
: gfxFontEntry(aFaceName), mFont(nsnull), mFontFile(aFontFile),
mForceGDIClassic(false)
{
mWeight = aWeight;
mStretch = aStretch;
@ -168,6 +175,9 @@ public:
PRBool IsCJKFont();
void SetForceGDIClassic(bool aForce) { mForceGDIClassic = aForce; }
bool GetForceGDIClassic() { return mForceGDIClassic; }
protected:
friend class gfxDWriteFont;
friend class gfxDWriteFontList;
@ -189,7 +199,8 @@ protected:
nsRefPtr<IDWriteFontFile> mFontFile;
DWRITE_FONT_FACE_TYPE mFaceType;
PRBool mIsCJK;
PRInt8 mIsCJK;
bool mForceGDIClassic;
};

View File

@ -151,8 +151,7 @@ gfxDWriteFont::gfxDWriteFont(gfxFontEntry *aFontEntry,
if ((anAAOption == gfxFont::kAntialiasDefault &&
UsingClearType() &&
(gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_NATURAL)) ||
GetMeasuringMode() == DWRITE_MEASURING_MODE_NATURAL) ||
anAAOption == gfxFont::kAntialiasSubpixel)
{
mUseSubpixelPositions = PR_TRUE;
@ -597,6 +596,11 @@ gfxDWriteFont::CairoScaledFont()
cairo_dwrite_scaled_font_allow_manual_show_glyphs(mCairoScaledFont,
mAllowManualShowGlyphs);
gfxDWriteFontEntry *fe =
static_cast<gfxDWriteFontEntry*>(mFontEntry.get());
cairo_dwrite_scaled_font_set_force_GDI_classic(mCairoScaledFont,
fe->GetForceGDIClassic());
}
NS_ASSERTION(mAdjustedSize == 0.0 ||
@ -685,6 +689,14 @@ gfxDWriteFont::GetGlyphWidth(gfxContext *aCtx, PRUint16 aGID)
return width;
}
DWRITE_MEASURING_MODE
gfxDWriteFont::GetMeasuringMode()
{
return static_cast<gfxDWriteFontEntry*>(mFontEntry.get())->GetForceGDIClassic()
? DWRITE_MEASURING_MODE_GDI_CLASSIC
: gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode();
}
gfxFloat
gfxDWriteFont::MeasureGlyphWidth(PRUint16 aGlyph)
{
@ -698,8 +710,7 @@ gfxDWriteFont::MeasureGlyphWidth(PRUint16 aGlyph)
} else {
hr = mFontFace->GetGdiCompatibleGlyphMetrics(
FLOAT(mAdjustedSize), 1.0f, nsnull,
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_GDI_NATURAL,
GetMeasuringMode() == DWRITE_MEASURING_MODE_GDI_NATURAL,
&aGlyph, 1, &metrics, FALSE);
if (SUCCEEDED(hr)) {
return NS_lround(metrics.advanceWidth * mFUnitsConvFactor);

View File

@ -102,6 +102,8 @@ protected:
static void DestroyBlobFunc(void* userArg);
DWRITE_MEASURING_MODE GetMeasuringMode();
nsRefPtr<IDWriteFontFace> mFontFace;
cairo_font_face_t *mCairoFontFace;
cairo_scaled_font_t *mCairoScaledFont;

View File

@ -953,8 +953,9 @@ GetRoundOffsetsToPixels(gfxContext *aContext,
// show_glyphs is implemented on the font and so is used for
// all surface types; however, it may pixel-snap depending on
// the dwrite rendering mode
if (gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_NATURAL) {
if (!cairo_dwrite_scaled_font_get_force_GDI_classic(scaled_font) &&
gfxWindowsPlatform::GetPlatform()->DWriteMeasuringMode() ==
DWRITE_MEASURING_MODE_NATURAL) {
return;
}
#endif

View File

@ -1819,6 +1819,11 @@ pref("gfx.font_rendering.cleartype_params.cleartype_level", -1);
pref("gfx.font_rendering.cleartype_params.pixel_structure", -1);
pref("gfx.font_rendering.cleartype_params.rendering_mode", -1);
// A comma-separated list of font family names. Fonts in these families will
// be forced to use "GDI Classic" ClearType mode, ignoring the value
// of gfx.font_rendering.cleartype_params.rendering_mode.
pref("gfx.font_rendering.cleartype_params.force_gdi_classic_for_families", "");
pref("ui.key.menuAccessKeyFocuses", true);
// override double-click word selection behavior.