зеркало из https://github.com/mozilla/gecko-dev.git
Bug 619521 - Part 1: Send a notification of any scripts for which font coverage is lacking. r=jdaggett
This commit is contained in:
Родитель
961f45f728
Коммит
b77ae133f8
|
@ -3252,6 +3252,22 @@ CanvasRenderingContext2D::GetHitRegionRect(Element* aElement, nsRect& aRect)
|
|||
*/
|
||||
struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcessor
|
||||
{
|
||||
CanvasBidiProcessor()
|
||||
: nsBidiPresUtils::BidiProcessor()
|
||||
{
|
||||
if (Preferences::GetBool(GFX_MISSING_FONTS_NOTIFY_PREF)) {
|
||||
mMissingFonts = new gfxMissingFontRecorder();
|
||||
}
|
||||
}
|
||||
|
||||
~CanvasBidiProcessor()
|
||||
{
|
||||
// notify front-end code if we encountered missing glyphs in any script
|
||||
if (mMissingFonts) {
|
||||
mMissingFonts->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
typedef CanvasRenderingContext2D::ContextState ContextState;
|
||||
|
||||
virtual void SetText(const char16_t* text, int32_t length, nsBidiDirection direction)
|
||||
|
@ -3268,7 +3284,8 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
|
|||
length,
|
||||
mThebes,
|
||||
mAppUnitsPerDevPixel,
|
||||
flags);
|
||||
flags,
|
||||
mMissingFonts);
|
||||
}
|
||||
|
||||
virtual nscoord GetWidth()
|
||||
|
@ -3514,6 +3531,10 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess
|
|||
// current font
|
||||
gfxFontGroup* mFontgrp;
|
||||
|
||||
// to record any unsupported characters found in the text,
|
||||
// and notify front-end if it is interested
|
||||
nsAutoPtr<gfxMissingFontRecorder> mMissingFonts;
|
||||
|
||||
// dev pixel conversion factor
|
||||
int32_t mAppUnitsPerDevPixel;
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@ public:
|
|||
reinterpret_cast<const uint8_t*>(aString), aLength,
|
||||
aRC->ThebesContext(),
|
||||
aMetrics->AppUnitsPerDevPixel(),
|
||||
ComputeFlags(aMetrics));
|
||||
ComputeFlags(aMetrics),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
AutoTextRun(nsFontMetrics* aMetrics, nsRenderingContext* aRC,
|
||||
|
@ -43,7 +44,8 @@ public:
|
|||
aString, aLength,
|
||||
aRC->ThebesContext(),
|
||||
aMetrics->AppUnitsPerDevPixel(),
|
||||
ComputeFlags(aMetrics));
|
||||
ComputeFlags(aMetrics),
|
||||
nullptr);
|
||||
}
|
||||
|
||||
gfxTextRun *get() { return mTextRun; }
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::unicode;
|
||||
using mozilla::services::GetObserverService;
|
||||
|
||||
static const char16_t kEllipsisChar[] = { 0x2026, 0x0 };
|
||||
static const char16_t kASCIIPeriodsChar[] = { '.', '.', '.', 0x0 };
|
||||
|
@ -2039,12 +2040,12 @@ gfxFontGroup::MakeHyphenTextRun(gfxContext *aCtx, uint32_t aAppUnitsPerDevUnit)
|
|||
gfxFont *font = GetFirstValidFont(uint32_t(hyphen));
|
||||
if (font->HasCharacter(hyphen)) {
|
||||
return MakeTextRun(&hyphen, 1, aCtx, aAppUnitsPerDevUnit,
|
||||
gfxFontGroup::TEXT_IS_PERSISTENT);
|
||||
gfxFontGroup::TEXT_IS_PERSISTENT, nullptr);
|
||||
}
|
||||
|
||||
static const uint8_t dash = '-';
|
||||
return MakeTextRun(&dash, 1, aCtx, aAppUnitsPerDevUnit,
|
||||
gfxFontGroup::TEXT_IS_PERSISTENT);
|
||||
gfxFontGroup::TEXT_IS_PERSISTENT, nullptr);
|
||||
}
|
||||
|
||||
gfxFloat
|
||||
|
@ -2065,7 +2066,8 @@ gfxFontGroup::GetHyphenWidth(gfxTextRun::PropertyProvider *aProvider)
|
|||
|
||||
gfxTextRun *
|
||||
gfxFontGroup::MakeTextRun(const uint8_t *aString, uint32_t aLength,
|
||||
const Parameters *aParams, uint32_t aFlags)
|
||||
const Parameters *aParams, uint32_t aFlags,
|
||||
gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
if (aLength == 0) {
|
||||
return MakeEmptyTextRun(aParams, aFlags);
|
||||
|
@ -2089,7 +2091,7 @@ gfxFontGroup::MakeTextRun(const uint8_t *aString, uint32_t aLength,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
InitTextRun(aParams->mContext, textRun, aString, aLength);
|
||||
InitTextRun(aParams->mContext, textRun, aString, aLength, aMFR);
|
||||
|
||||
textRun->FetchGlyphExtents(aParams->mContext);
|
||||
|
||||
|
@ -2098,7 +2100,8 @@ gfxFontGroup::MakeTextRun(const uint8_t *aString, uint32_t aLength,
|
|||
|
||||
gfxTextRun *
|
||||
gfxFontGroup::MakeTextRun(const char16_t *aString, uint32_t aLength,
|
||||
const Parameters *aParams, uint32_t aFlags)
|
||||
const Parameters *aParams, uint32_t aFlags,
|
||||
gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
if (aLength == 0) {
|
||||
return MakeEmptyTextRun(aParams, aFlags);
|
||||
|
@ -2116,7 +2119,7 @@ gfxFontGroup::MakeTextRun(const char16_t *aString, uint32_t aLength,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
InitTextRun(aParams->mContext, textRun, aString, aLength);
|
||||
InitTextRun(aParams->mContext, textRun, aString, aLength, aMFR);
|
||||
|
||||
textRun->FetchGlyphExtents(aParams->mContext);
|
||||
|
||||
|
@ -2128,7 +2131,8 @@ void
|
|||
gfxFontGroup::InitTextRun(gfxContext *aContext,
|
||||
gfxTextRun *aTextRun,
|
||||
const T *aString,
|
||||
uint32_t aLength)
|
||||
uint32_t aLength,
|
||||
gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
NS_ASSERTION(aLength > 0, "don't call InitTextRun for a zero-length run");
|
||||
|
||||
|
@ -2208,7 +2212,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
|||
// the text is still purely 8-bit; bypass the script-run itemizer
|
||||
// and treat it as a single Latin run
|
||||
InitScriptRun(aContext, aTextRun, aString,
|
||||
0, aLength, MOZ_SCRIPT_LATIN);
|
||||
0, aLength, MOZ_SCRIPT_LATIN, aMFR);
|
||||
} else {
|
||||
const char16_t *textPtr;
|
||||
if (transformedString) {
|
||||
|
@ -2256,7 +2260,7 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
|||
#endif
|
||||
|
||||
InitScriptRun(aContext, aTextRun, textPtr + runStart,
|
||||
runStart, runLimit - runStart, runScript);
|
||||
runStart, runLimit - runStart, runScript, aMFR);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2292,6 +2296,14 @@ gfxFontGroup::InitTextRun(gfxContext *aContext,
|
|||
aTextRun->SortGlyphRuns();
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsPUA(uint32_t aUSV)
|
||||
{
|
||||
// We could look up the General Category of the codepoint here,
|
||||
// but it's simpler to check PUA codepoint ranges.
|
||||
return (aUSV >= 0xE000 && aUSV <= 0xF8FF) || (aUSV >= 0xF0000);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
||||
|
@ -2301,7 +2313,8 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
|||
uint32_t aOffset, // position of the script run
|
||||
// within the textrun
|
||||
uint32_t aLength, // length of the script run
|
||||
int32_t aRunScript)
|
||||
int32_t aRunScript,
|
||||
gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
NS_ASSERTION(aLength > 0, "don't call InitScriptRun for a 0-length run");
|
||||
NS_ASSERTION(aTextRun->GetShapingState() != gfxTextRun::eShapingState_Aborted,
|
||||
|
@ -2322,6 +2335,7 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
|||
ComputeRanges(fontRanges, aString, aLength, aRunScript,
|
||||
aTextRun->GetFlags() & gfxTextRunFactory::TEXT_ORIENT_MASK);
|
||||
uint32_t numRanges = fontRanges.Length();
|
||||
bool missingChars = false;
|
||||
|
||||
for (uint32_t r = 0; r < numRanges; r++) {
|
||||
const gfxTextRange& range = fontRanges[r];
|
||||
|
@ -2468,11 +2482,15 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
|||
index + 1 < aLength &&
|
||||
NS_IS_LOW_SURROGATE(aString[index + 1]))
|
||||
{
|
||||
uint32_t usv =
|
||||
SURROGATE_TO_UCS4(ch, aString[index + 1]);
|
||||
aTextRun->SetMissingGlyph(aOffset + index,
|
||||
SURROGATE_TO_UCS4(ch,
|
||||
aString[index + 1]),
|
||||
usv,
|
||||
mainFont);
|
||||
index++;
|
||||
if (!mSkipDrawing && !IsPUA(usv)) {
|
||||
missingChars = true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2507,11 +2525,18 @@ gfxFontGroup::InitScriptRun(gfxContext *aContext,
|
|||
|
||||
// record char code so we can draw a box with the Unicode value
|
||||
aTextRun->SetMissingGlyph(aOffset + index, ch, mainFont);
|
||||
if (!mSkipDrawing && !IsPUA(ch)) {
|
||||
missingChars = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runStart += matchedLength;
|
||||
}
|
||||
|
||||
if (aMFR && missingChars) {
|
||||
aMFR->RecordScript(aRunScript);
|
||||
}
|
||||
}
|
||||
|
||||
gfxTextRun *
|
||||
|
@ -2537,7 +2562,8 @@ gfxFontGroup::GetEllipsisTextRun(int32_t aAppUnitsPerDevPixel,
|
|||
refCtx, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevPixel
|
||||
};
|
||||
gfxTextRun* textRun =
|
||||
MakeTextRun(ellipsis.get(), ellipsis.Length(), ¶ms, TEXT_IS_PERSISTENT);
|
||||
MakeTextRun(ellipsis.get(), ellipsis.Length(), ¶ms,
|
||||
TEXT_IS_PERSISTENT, nullptr);
|
||||
if (!textRun) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -3109,3 +3135,41 @@ gfxFontGroup::Shutdown()
|
|||
}
|
||||
|
||||
nsILanguageAtomService* gfxFontGroup::gLangService = nullptr;
|
||||
|
||||
void
|
||||
gfxMissingFontRecorder::Flush()
|
||||
{
|
||||
static bool mNotifiedFontsInitialized = false;
|
||||
static uint32_t mNotifiedFonts[gfxMissingFontRecorder::kNumScriptBitsWords];
|
||||
if (!mNotifiedFontsInitialized) {
|
||||
memset(&mNotifiedFonts, 0, sizeof(mNotifiedFonts));
|
||||
mNotifiedFontsInitialized = true;
|
||||
}
|
||||
|
||||
nsAutoString fontNeeded;
|
||||
for (uint32_t i = 0; i < kNumScriptBitsWords; ++i) {
|
||||
mMissingFonts[i] &= ~mNotifiedFonts[i];
|
||||
if (!mMissingFonts[i]) {
|
||||
continue;
|
||||
}
|
||||
for (uint32_t j = 0; j < 32; ++j) {
|
||||
if (!(mMissingFonts[i] & (1 << j))) {
|
||||
continue;
|
||||
}
|
||||
mNotifiedFonts[i] |= (1 << j);
|
||||
if (!fontNeeded.IsEmpty()) {
|
||||
fontNeeded.Append(PRUnichar(','));
|
||||
}
|
||||
uint32_t tag = GetScriptTagForCode(i * 32 + j);
|
||||
fontNeeded.Append(char16_t(tag >> 24));
|
||||
fontNeeded.Append(char16_t((tag >> 16) & 0xff));
|
||||
fontNeeded.Append(char16_t((tag >> 8) & 0xff));
|
||||
fontNeeded.Append(char16_t(tag & 0xff));
|
||||
}
|
||||
mMissingFonts[i] = 0;
|
||||
}
|
||||
if (!fontNeeded.IsEmpty()) {
|
||||
nsCOMPtr<nsIObserverService> service = GetObserverService();
|
||||
service->NotifyObservers(nullptr, "font-needed", fontNeeded.get());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/MemoryReporting.h"
|
||||
#include "DrawMode.h"
|
||||
#include "harfbuzz/hb.h"
|
||||
#include "nsUnicodeScriptCodes.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
|
@ -27,6 +28,7 @@ class gfxUserFontSet;
|
|||
class gfxTextContextPaint;
|
||||
class nsIAtom;
|
||||
class nsILanguageAtomService;
|
||||
class gfxMissingFontRecorder;
|
||||
|
||||
/**
|
||||
* Callback for Draw() to use when drawing text with mode
|
||||
|
@ -769,7 +771,8 @@ public:
|
|||
* This calls FetchGlyphExtents on the textrun.
|
||||
*/
|
||||
virtual gfxTextRun *MakeTextRun(const char16_t *aString, uint32_t aLength,
|
||||
const Parameters *aParams, uint32_t aFlags);
|
||||
const Parameters *aParams, uint32_t aFlags,
|
||||
gfxMissingFontRecorder *aMFR);
|
||||
/**
|
||||
* Make a textrun for a given string.
|
||||
* If aText is not persistent (aFlags & TEXT_IS_PERSISTENT), the
|
||||
|
@ -777,7 +780,8 @@ public:
|
|||
* This calls FetchGlyphExtents on the textrun.
|
||||
*/
|
||||
virtual gfxTextRun *MakeTextRun(const uint8_t *aString, uint32_t aLength,
|
||||
const Parameters *aParams, uint32_t aFlags);
|
||||
const Parameters *aParams, uint32_t aFlags,
|
||||
gfxMissingFontRecorder *aMFR);
|
||||
|
||||
/**
|
||||
* Textrun creation helper for clients that don't want to pass
|
||||
|
@ -787,12 +791,13 @@ public:
|
|||
gfxTextRun *MakeTextRun(const T *aString, uint32_t aLength,
|
||||
gfxContext *aRefContext,
|
||||
int32_t aAppUnitsPerDevUnit,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags,
|
||||
gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
gfxTextRunFactory::Parameters params = {
|
||||
aRefContext, nullptr, nullptr, nullptr, 0, aAppUnitsPerDevUnit
|
||||
};
|
||||
return MakeTextRun(aString, aLength, ¶ms, aFlags);
|
||||
return MakeTextRun(aString, aLength, ¶ms, aFlags, aMFR);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1088,7 +1093,8 @@ protected:
|
|||
void InitTextRun(gfxContext *aContext,
|
||||
gfxTextRun *aTextRun,
|
||||
const T *aString,
|
||||
uint32_t aLength);
|
||||
uint32_t aLength,
|
||||
gfxMissingFontRecorder *aMFR);
|
||||
|
||||
// InitTextRun helper to handle a single script run, by finding font ranges
|
||||
// and calling each font's InitTextRun() as appropriate
|
||||
|
@ -1098,7 +1104,8 @@ protected:
|
|||
const T *aString,
|
||||
uint32_t aScriptRunStart,
|
||||
uint32_t aScriptRunEnd,
|
||||
int32_t aRunScript);
|
||||
int32_t aRunScript,
|
||||
gfxMissingFontRecorder *aMFR);
|
||||
|
||||
// Helper for font-matching:
|
||||
// When matching the italic case, allow use of the regular face
|
||||
|
@ -1124,4 +1131,56 @@ protected:
|
|||
|
||||
static nsILanguageAtomService* gLangService;
|
||||
};
|
||||
|
||||
// A "missing font recorder" is to be used during text-run creation to keep
|
||||
// a record of any scripts encountered for which font coverage was lacking;
|
||||
// when Flush() is called, it sends a notification that front-end code can use
|
||||
// to download fonts on demand (or whatever else it wants to do).
|
||||
|
||||
#define GFX_MISSING_FONTS_NOTIFY_PREF "gfx.missing_fonts.notify"
|
||||
|
||||
class gfxMissingFontRecorder {
|
||||
public:
|
||||
gfxMissingFontRecorder()
|
||||
{
|
||||
MOZ_COUNT_CTOR(gfxMissingFontRecorder);
|
||||
memset(&mMissingFonts, 0, sizeof(mMissingFonts));
|
||||
}
|
||||
|
||||
~gfxMissingFontRecorder()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (uint32_t i = 0; i < kNumScriptBitsWords; i++) {
|
||||
NS_ASSERTION(mMissingFonts[i] == 0,
|
||||
"failed to flush the missing-font recorder");
|
||||
}
|
||||
#endif
|
||||
MOZ_COUNT_DTOR(gfxMissingFontRecorder);
|
||||
}
|
||||
|
||||
// record this script code in our mMissingFonts bitset
|
||||
void RecordScript(int32_t aScriptCode)
|
||||
{
|
||||
mMissingFonts[uint32_t(aScriptCode) >> 5] |=
|
||||
(1 << (uint32_t(aScriptCode) & 0x1f));
|
||||
}
|
||||
|
||||
// send a notification of any missing-scripts that have been
|
||||
// recorded, and clear the mMissingFonts set for re-use
|
||||
void Flush();
|
||||
|
||||
// forget any missing-scripts that have been recorded up to now;
|
||||
// called before discarding a recorder we no longer care about
|
||||
void Clear()
|
||||
{
|
||||
memset(&mMissingFonts, 0, sizeof(mMissingFonts));
|
||||
}
|
||||
|
||||
private:
|
||||
// Number of 32-bit words needed for the missing-script flags
|
||||
static const uint32_t kNumScriptBitsWords =
|
||||
((MOZ_NUM_SCRIPT_CODES + 31) / 32);
|
||||
uint32_t mMissingFonts[kNumScriptBitsWords];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -64,6 +64,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "gfxTextRun.h"
|
||||
|
||||
// Needed for Start/Stop of Image Animation
|
||||
#include "imgIContainer.h"
|
||||
|
@ -249,6 +250,10 @@ nsPresContext::nsPresContext(nsIDocument* aDocument, nsPresContextType aType)
|
|||
if (log && log->level >= PR_LOG_WARNING) {
|
||||
mTextPerf = new gfxTextPerfMetrics();
|
||||
}
|
||||
|
||||
if (Preferences::GetBool(GFX_MISSING_FONTS_NOTIFY_PREF)) {
|
||||
mMissingFonts = new gfxMissingFontRecorder();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -341,6 +346,9 @@ nsPresContext::LastRelease()
|
|||
if (IsRoot()) {
|
||||
static_cast<nsRootPresContext*>(this)->CancelDidPaintTimer();
|
||||
}
|
||||
if (mMissingFonts) {
|
||||
mMissingFonts->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
|
||||
|
@ -873,6 +881,20 @@ nsPresContext::PreferenceChanged(const char* aPrefName)
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (prefName.EqualsLiteral(GFX_MISSING_FONTS_NOTIFY_PREF)) {
|
||||
if (Preferences::GetBool(GFX_MISSING_FONTS_NOTIFY_PREF)) {
|
||||
if (!mMissingFonts) {
|
||||
mMissingFonts = new gfxMissingFontRecorder();
|
||||
// trigger reflow to detect missing fonts on the current page
|
||||
mPrefChangePendingNeedsReflow = true;
|
||||
}
|
||||
} else {
|
||||
if (mMissingFonts) {
|
||||
mMissingFonts->Clear();
|
||||
}
|
||||
mMissingFonts = nullptr;
|
||||
}
|
||||
}
|
||||
if (StringBeginsWith(prefName, NS_LITERAL_CSTRING("font."))) {
|
||||
// Changes to font family preferences don't change anything in the
|
||||
// computed style data, so the style system won't generate a reflow
|
||||
|
@ -2194,6 +2216,14 @@ nsPresContext::RebuildCounterStyles()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::NotifyMissingFonts()
|
||||
{
|
||||
if (mMissingFonts) {
|
||||
mMissingFonts->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsPresContext::EnsureSafeToHandOutCSSRules()
|
||||
{
|
||||
|
|
|
@ -65,6 +65,7 @@ class nsAnimationManager;
|
|||
class nsRefreshDriver;
|
||||
class nsIWidget;
|
||||
class nsDeviceContext;
|
||||
class gfxMissingFontRecorder;
|
||||
|
||||
namespace mozilla {
|
||||
class EventStateManager;
|
||||
|
@ -876,6 +877,9 @@ public:
|
|||
// user font set is changed and fonts become unavailable).
|
||||
void UserFontSetUpdated();
|
||||
|
||||
gfxMissingFontRecorder *MissingFontRecorder() { return mMissingFonts; }
|
||||
void NotifyMissingFonts();
|
||||
|
||||
mozilla::dom::FontFaceSet* Fonts();
|
||||
|
||||
void FlushCounterStyles();
|
||||
|
@ -1251,6 +1255,8 @@ protected:
|
|||
// text performance metrics
|
||||
nsAutoPtr<gfxTextPerfMetrics> mTextPerf;
|
||||
|
||||
nsAutoPtr<gfxMissingFontRecorder> mMissingFonts;
|
||||
|
||||
nsRect mVisibleArea;
|
||||
nsSize mPageSize;
|
||||
float mPageScale;
|
||||
|
|
|
@ -9119,6 +9119,8 @@ PresShell::DidDoReflow(bool aInterruptible, bool aWasInterrupted)
|
|||
mTouchCaret->UpdatePositionIfNeeded();
|
||||
}
|
||||
|
||||
mPresContext->NotifyMissingFonts();
|
||||
|
||||
if (!aWasInterrupted) {
|
||||
ClearReflowOnZoomPending();
|
||||
}
|
||||
|
|
|
@ -529,7 +529,8 @@ MathVariant(uint32_t aCh, uint8_t aMathVar)
|
|||
|
||||
void
|
||||
MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
|
||||
gfxContext* aRefContext)
|
||||
gfxContext* aRefContext,
|
||||
gfxMissingFontRecorder* aMFR)
|
||||
{
|
||||
gfxFontGroup* fontGroup = aTextRun->GetFontGroup();
|
||||
|
||||
|
@ -766,7 +767,7 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
|
|||
} else {
|
||||
cachedChild = newFontGroup->MakeTextRun(
|
||||
convertedString.BeginReading(), convertedString.Length(),
|
||||
&innerParams, flags);
|
||||
&innerParams, flags, aMFR);
|
||||
child = cachedChild.get();
|
||||
}
|
||||
if (!child)
|
||||
|
@ -778,7 +779,7 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
|
|||
child->SetPotentialLineBreaks(0, canBreakBeforeArray.Length(),
|
||||
canBreakBeforeArray.Elements(), aRefContext);
|
||||
if (transformedChild) {
|
||||
transformedChild->FinishSettingProperties(aRefContext);
|
||||
transformedChild->FinishSettingProperties(aRefContext, aMFR);
|
||||
}
|
||||
|
||||
if (mergeNeeded) {
|
||||
|
|
|
@ -22,7 +22,8 @@ public:
|
|||
mSSTYScriptLevel(aSSTYScriptLevel) {}
|
||||
|
||||
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
|
||||
gfxContext* aRefContext) MOZ_OVERRIDE;
|
||||
gfxContext* aRefContext,
|
||||
gfxMissingFontRecorder* aMFR) MOZ_OVERRIDE;
|
||||
enum {
|
||||
// Style effects which may override single character <mi> behaviour
|
||||
MATH_FONT_STYLING_NORMAL = 0x1, // fontstyle="normal" has been set.
|
||||
|
|
|
@ -561,10 +561,11 @@ template<typename T>
|
|||
gfxTextRun *
|
||||
MakeTextRun(const T *aText, uint32_t aLength,
|
||||
gfxFontGroup *aFontGroup, const gfxFontGroup::Parameters* aParams,
|
||||
uint32_t aFlags)
|
||||
uint32_t aFlags, gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
nsAutoPtr<gfxTextRun> textRun(aFontGroup->MakeTextRun(aText, aLength,
|
||||
aParams, aFlags));
|
||||
aParams, aFlags,
|
||||
aMFR));
|
||||
if (!textRun) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -842,6 +843,7 @@ public:
|
|||
mCurrentFramesAllSameTextRun(nullptr),
|
||||
mContext(aContext),
|
||||
mLineContainer(aLineContainer),
|
||||
mMissingFonts(aPresContext->MissingFontRecorder()),
|
||||
mBidiEnabled(aPresContext->BidiEnabled()),
|
||||
mSkipIncompleteTextRuns(false),
|
||||
mWhichTextRun(aWhichTextRun),
|
||||
|
@ -971,7 +973,7 @@ public:
|
|||
aCapitalize, mContext);
|
||||
}
|
||||
|
||||
void Finish() {
|
||||
void Finish(gfxMissingFontRecorder* aMFR) {
|
||||
NS_ASSERTION(!(mTextRun->GetFlags() &
|
||||
(gfxTextRunFactory::TEXT_UNUSED_FLAGS |
|
||||
nsTextFrameUtils::TEXT_UNUSED_FLAG)),
|
||||
|
@ -979,7 +981,7 @@ public:
|
|||
if (mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED) {
|
||||
nsTransformedTextRun* transformedTextRun =
|
||||
static_cast<nsTransformedTextRun*>(mTextRun);
|
||||
transformedTextRun->FinishSettingProperties(mContext);
|
||||
transformedTextRun->FinishSettingProperties(mContext, aMFR);
|
||||
}
|
||||
// The way nsTransformedTextRun is implemented, its glyph runs aren't
|
||||
// available until after nsTransformedTextRun::FinishSettingProperties()
|
||||
|
@ -1007,6 +1009,7 @@ private:
|
|||
// The common ancestor of the current frame and the previous leaf frame
|
||||
// on the line, or null if there was no previous leaf frame.
|
||||
nsIFrame* mCommonAncestorWithLastFrame;
|
||||
gfxMissingFontRecorder* mMissingFonts;
|
||||
// mMaxTextLength is an upper bound on the size of the text in all mapped frames
|
||||
// The value UINT32_MAX represents overflow; text will be discarded
|
||||
uint32_t mMaxTextLength;
|
||||
|
@ -1506,7 +1509,7 @@ void BuildTextRunsScanner::FlushLineBreaks(gfxTextRun* aTrailingTextRun)
|
|||
// TODO cause frames associated with the textrun to be reflowed, if they
|
||||
// aren't being reflowed already!
|
||||
}
|
||||
mBreakSinks[i]->Finish();
|
||||
mBreakSinks[i]->Finish(mMissingFonts);
|
||||
}
|
||||
mBreakSinks.Clear();
|
||||
|
||||
|
@ -2138,27 +2141,31 @@ BuildTextRunsScanner::BuildTextRunForFrames(void* aTextBuffer)
|
|||
if (mDoubleByteText) {
|
||||
const char16_t* text = static_cast<const char16_t*>(textPtr);
|
||||
if (transformingFactory) {
|
||||
textRun = transformingFactory->MakeTextRun(text, transformedLength, ¶ms,
|
||||
fontGroup, textFlags, styles.Elements());
|
||||
textRun = transformingFactory->MakeTextRun(text, transformedLength,
|
||||
¶ms, fontGroup, textFlags,
|
||||
styles.Elements(), true);
|
||||
if (textRun) {
|
||||
// ownership of the factory has passed to the textrun
|
||||
transformingFactory.forget();
|
||||
}
|
||||
} else {
|
||||
textRun = MakeTextRun(text, transformedLength, fontGroup, ¶ms, textFlags);
|
||||
textRun = MakeTextRun(text, transformedLength, fontGroup, ¶ms,
|
||||
textFlags, mMissingFonts);
|
||||
}
|
||||
} else {
|
||||
const uint8_t* text = static_cast<const uint8_t*>(textPtr);
|
||||
textFlags |= gfxFontGroup::TEXT_IS_8BIT;
|
||||
if (transformingFactory) {
|
||||
textRun = transformingFactory->MakeTextRun(text, transformedLength, ¶ms,
|
||||
fontGroup, textFlags, styles.Elements());
|
||||
textRun = transformingFactory->MakeTextRun(text, transformedLength,
|
||||
¶ms, fontGroup, textFlags,
|
||||
styles.Elements(), true);
|
||||
if (textRun) {
|
||||
// ownership of the factory has passed to the textrun
|
||||
transformingFactory.forget();
|
||||
}
|
||||
} else {
|
||||
textRun = MakeTextRun(text, transformedLength, fontGroup, ¶ms, textFlags);
|
||||
textRun = MakeTextRun(text, transformedLength, fontGroup, ¶ms,
|
||||
textFlags, mMissingFonts);
|
||||
}
|
||||
}
|
||||
if (!textRun) {
|
||||
|
|
|
@ -596,7 +596,7 @@ nsCaseTransformTextRunFactory::TransformString(
|
|||
|
||||
void
|
||||
nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
|
||||
gfxContext* aRefContext)
|
||||
gfxContext* aRefContext, gfxMissingFontRecorder *aMFR)
|
||||
{
|
||||
nsAutoString convertedString;
|
||||
nsAutoTArray<bool,50> charsToMergeArray;
|
||||
|
@ -631,7 +631,7 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
|
|||
} else {
|
||||
cachedChild = fontGroup->MakeTextRun(
|
||||
convertedString.BeginReading(), convertedString.Length(),
|
||||
&innerParams, flags);
|
||||
&innerParams, flags, aMFR);
|
||||
child = cachedChild.get();
|
||||
}
|
||||
if (!child)
|
||||
|
@ -643,7 +643,7 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
|
|||
child->SetPotentialLineBreaks(0, canBreakBeforeArray.Length(),
|
||||
canBreakBeforeArray.Elements(), aRefContext);
|
||||
if (transformedChild) {
|
||||
transformedChild->FinishSettingProperties(aRefContext);
|
||||
transformedChild->FinishSettingProperties(aRefContext, aMFR);
|
||||
}
|
||||
|
||||
if (mergeNeeded) {
|
||||
|
|
|
@ -21,13 +21,17 @@ public:
|
|||
nsTransformedTextRun* MakeTextRun(const uint8_t* aString, uint32_t aLength,
|
||||
const gfxFontGroup::Parameters* aParams,
|
||||
gfxFontGroup* aFontGroup, uint32_t aFlags,
|
||||
nsStyleContext** aStyles, bool aOwnsFactory = true);
|
||||
nsStyleContext** aStyles,
|
||||
bool aOwnsFactory);
|
||||
nsTransformedTextRun* MakeTextRun(const char16_t* aString, uint32_t aLength,
|
||||
const gfxFontGroup::Parameters* aParams,
|
||||
gfxFontGroup* aFontGroup, uint32_t aFlags,
|
||||
nsStyleContext** aStyles, bool aOwnsFactory = true);
|
||||
nsStyleContext** aStyles,
|
||||
bool aOwnsFactory);
|
||||
|
||||
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) = 0;
|
||||
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
|
||||
gfxContext* aRefContext,
|
||||
gfxMissingFontRecorder* aMFR) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -48,7 +52,9 @@ public:
|
|||
: mInnerTransformingTextRunFactory(aInnerTransformingTextRunFactory),
|
||||
mAllUppercase(aAllUppercase) {}
|
||||
|
||||
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun, gfxContext* aRefContext) MOZ_OVERRIDE;
|
||||
virtual void RebuildTextRun(nsTransformedTextRun* aTextRun,
|
||||
gfxContext* aRefContext,
|
||||
gfxMissingFontRecorder* aMFR) MOZ_OVERRIDE;
|
||||
|
||||
// Perform a transformation on the given string, writing the result into
|
||||
// aConvertedString. If aAllUppercase is true, the transform is (global)
|
||||
|
@ -105,11 +111,12 @@ public:
|
|||
* are done and before we request any data from the textrun. Also always
|
||||
* called after a Create.
|
||||
*/
|
||||
void FinishSettingProperties(gfxContext* aRefContext)
|
||||
void FinishSettingProperties(gfxContext* aRefContext,
|
||||
gfxMissingFontRecorder* aMFR)
|
||||
{
|
||||
if (mNeedsRebuild) {
|
||||
mNeedsRebuild = false;
|
||||
mFactory->RebuildTextRun(this, aRefContext);
|
||||
mFactory->RebuildTextRun(this, aRefContext, aMFR);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -389,7 +389,7 @@ nsPropertiesTable::MakeTextRun(gfxContext* aThebesContext,
|
|||
"nsPropertiesTable can only access glyphs by code point");
|
||||
return aFontGroup->
|
||||
MakeTextRun(aGlyph.code, aGlyph.Length(), aThebesContext,
|
||||
aAppUnitsPerDevPixel, 0);
|
||||
aAppUnitsPerDevPixel, 0, nullptr);
|
||||
}
|
||||
|
||||
// An instance of nsOpenTypeTable is associated with one gfxFontEntry that
|
||||
|
@ -470,7 +470,7 @@ nsOpenTypeTable::UpdateCache(gfxContext* aThebesContext,
|
|||
if (mCharCache != aChar) {
|
||||
nsAutoPtr<gfxTextRun> textRun;
|
||||
textRun = aFontGroup->
|
||||
MakeTextRun(&aChar, 1, aThebesContext, aAppUnitsPerDevPixel, 0);
|
||||
MakeTextRun(&aChar, 1, aThebesContext, aAppUnitsPerDevPixel, 0, nullptr);
|
||||
const gfxTextRun::CompressedGlyph& data = textRun->GetCharacterGlyphs()[0];
|
||||
if (data.IsSimpleGlyph()) {
|
||||
mGlyphID = data.GetSimpleGlyph();
|
||||
|
@ -1553,7 +1553,8 @@ nsMathMLChar::StretchInternal(nsPresContext* aPresContext,
|
|||
nsAutoPtr<gfxTextRun> textRun;
|
||||
textRun = fm->GetThebesFontGroup()->
|
||||
MakeTextRun(static_cast<const char16_t*>(mData.get()), len, aThebesContext,
|
||||
aPresContext->AppUnitsPerDevPixel(), 0);
|
||||
aPresContext->AppUnitsPerDevPixel(), 0,
|
||||
aPresContext->MissingFontRecorder());
|
||||
aDesiredStretchSize = MeasureTextRun(aThebesContext, textRun);
|
||||
mGlyphs[0] = textRun;
|
||||
|
||||
|
|
|
@ -592,6 +592,10 @@ pref("gfx.bundled_fonts.enabled", true);
|
|||
pref("gfx.bundled_fonts.force-enabled", false);
|
||||
#endif
|
||||
|
||||
// Do we fire a notification about missing fonts, so the front-end can decide
|
||||
// whether to try and do something about it (e.g. download additional fonts)?
|
||||
pref("gfx.missing_fonts.notify", false);
|
||||
|
||||
pref("gfx.filter.nearest.force-enabled", false);
|
||||
|
||||
// prefs controlling the font (name/cmap) loader that runs shortly after startup
|
||||
|
|
Загрузка…
Ссылка в новой задаче