зеркало из https://github.com/mozilla/pjs.git
Bug 387969. Use CSS 'text-rendering' property to control text quality. r=pavlov,r+sr=bzbarsky
This commit is contained in:
Родитель
d573a81aec
Коммит
377804c1a1
|
@ -489,7 +489,13 @@ public:
|
|||
* When set, optional ligatures are disabled. Ligatures that are
|
||||
* required for legible text should still be enabled.
|
||||
*/
|
||||
TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0400
|
||||
TEXT_DISABLE_OPTIONAL_LIGATURES = 0x0400,
|
||||
/**
|
||||
* When set, the textrun should favour speed of construction over
|
||||
* quality. This may involve disabling ligatures and/or kerning or
|
||||
* other effects.
|
||||
*/
|
||||
TEXT_OPTIMIZE_SPEED = 0x0800
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -830,6 +830,16 @@ gfxPangoFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
|||
return run;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
CanTakeFastPath(PRUint32 aFlags)
|
||||
{
|
||||
// Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't
|
||||
// We need to always use Pango for RTL text, in case glyph mirroring is required
|
||||
return (aFlags &
|
||||
(gfxTextRunFactory::TEXT_OPTIMIZE_SPEED | gfxTextRunFactory::TEXT_IS_RTL)) ==
|
||||
gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
gfxPangoFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
|
@ -843,14 +853,17 @@ gfxPangoFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
|||
nsCAutoString utf8;
|
||||
PRInt32 headerLen = AppendDirectionalIndicatorUTF8(run->IsRightToLeft(), utf8);
|
||||
AppendUTF16toUTF8(Substring(aString, aString + aLength), utf8);
|
||||
PRUint32 allBits = 0;
|
||||
PRBool is8Bit = PR_FALSE;
|
||||
#if defined(ENABLE_XFT_FAST_PATH_8BIT)
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
allBits |= aString[i];
|
||||
if (CanTakeFastPath(aFlags)) {
|
||||
PRUint32 allBits;
|
||||
PRUint32 i;
|
||||
for (i = 0; i < aLength; ++i) {
|
||||
allBits |= aString[i];
|
||||
}
|
||||
is8Bit = (allBits & 0xFF00) == 0;
|
||||
}
|
||||
#endif
|
||||
PRBool is8Bit = (allBits & 0xFF00) == 0;
|
||||
InitTextRun(run, utf8.get(), utf8.Length(), headerLen, is8Bit);
|
||||
return run;
|
||||
}
|
||||
|
@ -864,8 +877,7 @@ gfxPangoFontGroup::InitTextRun(gfxTextRun *aTextRun, const gchar *aUTF8Text,
|
|||
CreateGlyphRunsXft(aTextRun, aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
|
||||
#else
|
||||
#if defined(ENABLE_XFT_FAST_PATH_8BIT)
|
||||
// We need to always use Pango for RTL text, in case glyph mirroring is required
|
||||
if (aTake8BitPath && !aTextRun->IsRightToLeft()) {
|
||||
if (aTake8BitPath && CanTakeFastPath(aTextRun->GetFlags())) {
|
||||
CreateGlyphRunsXft(aTextRun, aUTF8Text + aUTF8HeaderLength, aUTF8Length - aUTF8HeaderLength);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ protected:
|
|||
PRPackedBool mIsDoubleByteText;
|
||||
PRPackedBool mIsRTL;
|
||||
PRPackedBool mEnabledOptionalLigatures;
|
||||
PRPackedBool mOptimizeSpeed;
|
||||
|
||||
CacheHashKey(gfxTextRun *aBaseTextRun, void *aFontOrGroup,
|
||||
PRUint32 aStart, PRUint32 aLength, PRUint32 aHash)
|
||||
|
@ -102,7 +103,8 @@ protected:
|
|||
mStringHash(aHash),
|
||||
mIsDoubleByteText((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_IS_8BIT) == 0),
|
||||
mIsRTL(aBaseTextRun->IsRightToLeft()),
|
||||
mEnabledOptionalLigatures((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0)
|
||||
mEnabledOptionalLigatures((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0),
|
||||
mOptimizeSpeed((aBaseTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
@ -586,7 +588,8 @@ TextRunWordCache::CacheHashEntry::KeyEquals(const KeyTypePointer aKey) const
|
|||
GetFontOrGroup(fontGroup, mHashedByFont) != aKey->mFontOrGroup ||
|
||||
aKey->mAppUnitsPerDevUnit != mTextRun->GetAppUnitsPerDevUnit() ||
|
||||
aKey->mIsRTL != mTextRun->IsRightToLeft() ||
|
||||
aKey->mEnabledOptionalLigatures != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0))
|
||||
aKey->mEnabledOptionalLigatures != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES) == 0) ||
|
||||
aKey->mOptimizeSpeed != ((mTextRun->GetFlags() & gfxTextRunFactory::TEXT_OPTIMIZE_SPEED) != 0))
|
||||
return PR_FALSE;
|
||||
|
||||
if (mTextRun->GetFlags() & gfxFontGroup::TEXT_IS_8BIT) {
|
||||
|
@ -608,7 +611,8 @@ PLDHashNumber
|
|||
TextRunWordCache::CacheHashEntry::HashKey(const KeyTypePointer aKey)
|
||||
{
|
||||
return aKey->mStringHash + (long)aKey->mFontOrGroup + aKey->mAppUnitsPerDevUnit +
|
||||
aKey->mIsDoubleByteText + aKey->mIsRTL*2 + aKey->mEnabledOptionalLigatures*4;
|
||||
aKey->mIsDoubleByteText + aKey->mIsRTL*2 + aKey->mEnabledOptionalLigatures*4 +
|
||||
aKey->mOptimizeSpeed*8;
|
||||
}
|
||||
|
||||
static TextRunWordCache *gTextRunWordCache = nsnull;
|
||||
|
|
|
@ -504,6 +504,16 @@ gfxWindowsFontGroup::Copy(const gfxFontStyle *aStyle)
|
|||
return new gfxWindowsFontGroup(mFamilies, aStyle);
|
||||
}
|
||||
|
||||
static PRBool
|
||||
CanTakeFastPath(PRUint32 aFlags)
|
||||
{
|
||||
// Can take fast path only if OPTIMIZE_SPEED is set and IS_RTL isn't
|
||||
// We need to always use Uniscribe for RTL text, in case glyph mirroring is required
|
||||
return (aFlags &
|
||||
(gfxTextRunFactory::TEXT_OPTIMIZE_SPEED | gfxTextRunFactory::TEXT_IS_RTL)) ==
|
||||
gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
gfxWindowsFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
||||
const Parameters *aParams, PRUint32 aFlags)
|
||||
|
@ -522,8 +532,8 @@ gfxWindowsFontGroup::MakeTextRun(const PRUnichar *aString, PRUint32 aLength,
|
|||
#ifdef FORCE_UNISCRIBE
|
||||
const PRBool isComplex = PR_TRUE;
|
||||
#else
|
||||
const PRBool isComplex = ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK ||
|
||||
textRun->IsRightToLeft();
|
||||
const PRBool isComplex = !CanTakeFastPath(aFlags) ||
|
||||
ScriptIsComplex(aString, aLength, SIC_COMPLEX) == S_OK;
|
||||
#endif
|
||||
if (isComplex)
|
||||
InitTextRunUniscribe(aParams->mContext, textRun, aString, aLength);
|
||||
|
@ -547,7 +557,7 @@ gfxWindowsFontGroup::MakeTextRun(const PRUint8 *aString, PRUint32 aLength,
|
|||
#ifdef FORCE_UNISCRIBE
|
||||
const PRBool isComplex = PR_TRUE;
|
||||
#else
|
||||
const PRBool isComplex = textRun->IsRightToLeft();
|
||||
const PRBool isComplex = !CanTakeFastPath(aFlags);
|
||||
#endif
|
||||
|
||||
/* We can only call GDI "A" functions if this is a true 7bit ASCII string,
|
||||
|
|
|
@ -65,9 +65,11 @@
|
|||
#include "imgIContainer.h"
|
||||
#include "gfxRect.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxFont.h"
|
||||
#include "nsIImage.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#ifdef MOZ_SVG_FOREIGNOBJECT
|
||||
#include "nsSVGForeignObjectFrame.h"
|
||||
|
@ -2333,3 +2335,38 @@ nsLayoutUtils::FrameHasTransparency(nsIFrame* aFrame) {
|
|||
return PR_TRUE;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
IsNonzeroCoord(const nsStyleCoord& aCoord)
|
||||
{
|
||||
if (eStyleUnit_Coord == aCoord.GetUnit())
|
||||
return aCoord.GetCoordValue() != 0;
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/* static */ PRUint32
|
||||
nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
|
||||
const nsStyleText* aStyleText,
|
||||
const nsStyleFont* aStyleFont)
|
||||
{
|
||||
PRUint32 result = 0;
|
||||
if (IsNonzeroCoord(aStyleText->mLetterSpacing)) {
|
||||
result |= gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES;
|
||||
}
|
||||
#ifdef MOZ_SVG
|
||||
switch (aStyleContext->GetStyleSVG()->mTextRendering) {
|
||||
case NS_STYLE_TEXT_RENDERING_OPTIMIZESPEED:
|
||||
result |= gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
|
||||
break;
|
||||
case NS_STYLE_TEXT_RENDERING_AUTO:
|
||||
if (aStyleFont->mFont.size <
|
||||
aStyleContext->PresContext()->GetAutoQualityMinFontSize()) {
|
||||
result |= gfxTextRunFactory::TEXT_OPTIMIZE_SPEED;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -700,6 +700,17 @@ public:
|
|||
* @return a value suitable for passing to SetWindowTranslucency
|
||||
*/
|
||||
static PRBool FrameHasTransparency(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Get textrun construction flags determined by a given style; in particular
|
||||
* some combination of:
|
||||
* -- TEXT_DISABLE_OPTIONAL_LIGATURES if letter-spacing is in use
|
||||
* -- TEXT_OPTIMIZE_SPEED if the text-rendering CSS property and font size
|
||||
* and prefs indicate we should be optimizing for speed over quality
|
||||
*/
|
||||
static PRUint32 GetTextRunFlagsForStyle(nsStyleContext* aStyleContext,
|
||||
const nsStyleText* aStyleText,
|
||||
const nsStyleFont* aStyleFont);
|
||||
};
|
||||
|
||||
#endif // nsLayoutUtils_h__
|
||||
|
|
|
@ -669,6 +669,8 @@ nsPresContext::ClearStyleDataAndReflow()
|
|||
}
|
||||
}
|
||||
|
||||
static const char sMinFontSizePref[] = "browser.display.auto_quality_min_font_size";
|
||||
|
||||
void
|
||||
nsPresContext::PreferenceChanged(const char* aPrefName)
|
||||
{
|
||||
|
@ -687,6 +689,11 @@ nsPresContext::PreferenceChanged(const char* aPrefName)
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (!nsCRT::strcmp(aPrefName, sMinFontSizePref)) {
|
||||
mAutoQualityMinFontSizePixelsPref = nsContentUtils::GetIntPref(sMinFontSizePref);
|
||||
ClearStyleDataAndReflow();
|
||||
return;
|
||||
}
|
||||
// we use a zero-delay timer to coalesce multiple pref updates
|
||||
if (!mPrefChangedTimer)
|
||||
{
|
||||
|
@ -780,6 +787,9 @@ nsPresContext::Init(nsIDeviceContext* aDeviceContext)
|
|||
nsPresContext::PrefChangedCallback,
|
||||
this);
|
||||
|
||||
// This is observed thanks to the browser.display. observer above.
|
||||
mAutoQualityMinFontSizePixelsPref = nsContentUtils::GetIntPref(sMinFontSizePref);
|
||||
|
||||
rv = mEventManager->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
|
|
|
@ -470,6 +470,10 @@ public:
|
|||
float GetFullZoom() {return mDeviceContext->GetPixelScale();}
|
||||
void SetFullZoom(float aZoom);
|
||||
|
||||
nscoord GetAutoQualityMinFontSize() {
|
||||
return DevPixelsToAppUnits(mAutoQualityMinFontSizePixelsPref);
|
||||
}
|
||||
|
||||
static PRInt32 AppUnitsPerCSSPixel() { return nsIDeviceContext::AppUnitsPerCSSPixel(); }
|
||||
PRInt32 AppUnitsPerDevPixel() const { return mDeviceContext->AppUnitsPerDevPixel(); }
|
||||
PRInt32 AppUnitsPerInch() const { return mDeviceContext->AppUnitsPerInch(); }
|
||||
|
@ -755,6 +759,7 @@ protected:
|
|||
nsWeakPtr mContainer;
|
||||
|
||||
float mTextZoom; // Text zoom, defaults to 1.0
|
||||
PRInt32 mAutoQualityMinFontSizePixelsPref;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
nsBidiPresUtils* mBidiUtils;
|
||||
|
|
|
@ -1284,12 +1284,6 @@ static nscoord StyleToCoord(const nsStyleCoord& aCoord)
|
|||
}
|
||||
}
|
||||
|
||||
static PRBool
|
||||
ShouldDisableOptionalLigatures(const nsStyleText* aTextStyle)
|
||||
{
|
||||
return StyleToCoord(aTextStyle->mLetterSpacing) != 0;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
HasTerminalNewline(const nsTextFrame* aFrame)
|
||||
{
|
||||
|
@ -1320,9 +1314,13 @@ BuildTextRunsScanner::ContinueTextRunAcrossFrames(nsTextFrame* aFrame1, nsTextFr
|
|||
nsStyleContext* sc2 = aFrame2->GetStyleContext();
|
||||
if (sc1 == sc2)
|
||||
return PR_TRUE;
|
||||
return sc1->GetStyleFont()->mFont.BaseEquals(sc2->GetStyleFont()->mFont) &&
|
||||
const nsStyleFont* fontStyle1 = sc1->GetStyleFont();
|
||||
const nsStyleFont* fontStyle2 = sc2->GetStyleFont();
|
||||
const nsStyleText* textStyle2 = sc2->GetStyleText();
|
||||
return fontStyle1->mFont.BaseEquals(fontStyle2->mFont) &&
|
||||
sc1->GetStyleVisibility()->mLangGroup == sc2->GetStyleVisibility()->mLangGroup &&
|
||||
ShouldDisableOptionalLigatures(textStyle1) == ShouldDisableOptionalLigatures(sc2->GetStyleText());
|
||||
nsLayoutUtils::GetTextRunFlagsForStyle(sc1, textStyle1, fontStyle1) ==
|
||||
nsLayoutUtils::GetTextRunFlagsForStyle(sc2, textStyle2, fontStyle2);
|
||||
}
|
||||
|
||||
void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
|
||||
|
@ -1531,14 +1529,18 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
|
|||
nsTextFrame* nextBreakBeforeFrame = GetNextBreakBeforeFrame(&nextBreakIndex);
|
||||
|
||||
PRUint32 i;
|
||||
const nsStyleText* textStyle = nsnull;
|
||||
const nsStyleFont* fontStyle = nsnull;
|
||||
nsStyleContext* lastStyleContext = nsnull;
|
||||
for (i = 0; i < mMappedFlows.Length(); ++i) {
|
||||
MappedFlow* mappedFlow = &mMappedFlows[i];
|
||||
nsTextFrame* f = mappedFlow->mStartFrame;
|
||||
|
||||
mappedFlow->mTransformedTextOffset = currentTransformedTextOffset;
|
||||
|
||||
lastStyleContext = f->GetStyleContext();
|
||||
// Detect use of text-transform or font-variant anywhere in the run
|
||||
const nsStyleText* textStyle = f->GetStyleText();
|
||||
textStyle = f->GetStyleText();
|
||||
if (NS_STYLE_TEXT_TRANSFORM_NONE != textStyle->mTextTransform) {
|
||||
anyTextTransformStyle = PR_TRUE;
|
||||
}
|
||||
|
@ -1548,7 +1550,7 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
|
|||
if (NS_STYLE_TEXT_ALIGN_JUSTIFY == textStyle->mTextAlign && compressWhitespace) {
|
||||
textFlags |= gfxTextRunFactory::TEXT_ENABLE_SPACING;
|
||||
}
|
||||
const nsStyleFont* fontStyle = f->GetStyleFont();
|
||||
fontStyle = f->GetStyleFont();
|
||||
if (NS_STYLE_FONT_VARIANT_SMALL_CAPS == fontStyle->mFont.variant) {
|
||||
anySmallcapsStyle = PR_TRUE;
|
||||
}
|
||||
|
@ -1708,10 +1710,11 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
|
|||
if (mTrimNextRunLeadingWhitespace) {
|
||||
textFlags |= nsTextFrameUtils::TEXT_TRAILING_WHITESPACE;
|
||||
}
|
||||
if (ShouldDisableOptionalLigatures(firstFrame->GetStyleText())) {
|
||||
textFlags |= gfxTextRunFactory::TEXT_DISABLE_OPTIONAL_LIGATURES;
|
||||
}
|
||||
|
||||
// ContinueTextRunAcrossFrames guarantees that it doesn't matter which
|
||||
// frame's style is used, so use the last frame's
|
||||
textFlags |= nsLayoutUtils::GetTextRunFlagsForStyle(lastStyleContext,
|
||||
textStyle, fontStyle);
|
||||
|
||||
gfxSkipChars skipChars;
|
||||
skipChars.TakeFrom(&builder);
|
||||
// Convert linebreak coordinates to transformed string offsets
|
||||
|
|
|
@ -1351,8 +1351,10 @@ nsSVGGlyphFrame::GetTextRun(gfxContext *aCtx, const nsString &aText)
|
|||
if (!mFontGroup)
|
||||
return nsnull;
|
||||
|
||||
PRUint32 flags = nsLayoutUtils::GetTextRunFlagsForStyle(GetStyleContext(),
|
||||
GetStyleText(), GetStyleFont());
|
||||
return gfxTextRunCache::MakeTextRun(aText.get(), aText.Length(),
|
||||
mFontGroup, aCtx, 1, 0);
|
||||
mFontGroup, aCtx, 1, flags);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
|
@ -86,6 +86,8 @@ pref("browser.display.force_inline_alttext", false); // true = force ALT text fo
|
|||
// 2 = add extra leading both internal leading and external leading are zero
|
||||
pref("browser.display.normal_lineheight_calc_control", 2);
|
||||
pref("browser.display.show_image_placeholders", true); // true = show image placeholders while image is loaded and when image is broken
|
||||
// min font device pixel size at which to turn on high quality
|
||||
pref("browser.display.auto_quality_min_font_size", 60);
|
||||
pref("browser.anchor_color", "#0000EE");
|
||||
pref("browser.active_color", "#EE0000");
|
||||
pref("browser.visited_color", "#551A8B");
|
||||
|
|
Загрузка…
Ссылка в новой задаче