mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-10 17:24:29 +00:00
Bug 1099977. Part 2: Make gfxFont::Measure return an empty bounding-box when all glyphs are invisible. r=jfkthame
--HG-- extra : rebase_source : 41a9f586ef2992d96b789d6bd55daae18f15ed2f
This commit is contained in:
parent
d4b40be62c
commit
0c9928a13e
@ -2114,6 +2114,23 @@ NeedsGlyphExtents(gfxFont *aFont, gfxTextRun *aTextRun)
|
||||
aFont->GetFontEntry()->IsUserFont();
|
||||
}
|
||||
|
||||
bool
|
||||
gfxFont::IsSpaceGlyphInvisible(gfxContext *aRefContext, gfxTextRun *aTextRun)
|
||||
{
|
||||
if (!mFontEntry->mSpaceGlyphIsInvisibleInitialized &&
|
||||
GetAdjustedSize() >= 1.0) {
|
||||
gfxGlyphExtents *extents =
|
||||
GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit());
|
||||
gfxRect glyphExtents;
|
||||
mFontEntry->mSpaceGlyphIsInvisible =
|
||||
extents->GetTightGlyphExtentsAppUnits(this, eHorizontal,
|
||||
aRefContext, GetSpaceGlyph(), &glyphExtents) &&
|
||||
glyphExtents.IsEmpty();
|
||||
mFontEntry->mSpaceGlyphIsInvisibleInitialized = true;
|
||||
}
|
||||
return mFontEntry->mSpaceGlyphIsInvisible;
|
||||
}
|
||||
|
||||
gfxFont::RunMetrics
|
||||
gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
uint32_t aStart, uint32_t aEnd,
|
||||
@ -2189,16 +2206,22 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
if (aSpacing) {
|
||||
x += direction*aSpacing[0].mBefore;
|
||||
}
|
||||
uint32_t spaceGlyph = GetSpaceGlyph();
|
||||
bool allGlyphsInvisible = true;
|
||||
uint32_t i;
|
||||
for (i = aStart; i < aEnd; ++i) {
|
||||
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
|
||||
if (glyphData->IsSimpleGlyph()) {
|
||||
double advance = glyphData->GetSimpleAdvance();
|
||||
uint32_t glyphIndex = glyphData->GetSimpleGlyph();
|
||||
if (glyphIndex != spaceGlyph ||
|
||||
!IsSpaceGlyphInvisible(aRefContext, aTextRun)) {
|
||||
allGlyphsInvisible = false;
|
||||
}
|
||||
// Only get the real glyph horizontal extent if we were asked
|
||||
// for the tight bounding box or we're in quality mode
|
||||
if ((aBoundingBoxType != LOOSE_INK_EXTENTS || needsGlyphExtents) &&
|
||||
extents) {
|
||||
uint32_t glyphIndex = glyphData->GetSimpleGlyph();
|
||||
extents){
|
||||
uint16_t extentsWidth = extents->GetContainedGlyphWidthAppUnits(glyphIndex);
|
||||
if (extentsWidth != gfxGlyphExtents::INVALID_WIDTH &&
|
||||
aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||
@ -2221,6 +2244,7 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
}
|
||||
x += direction*advance;
|
||||
} else {
|
||||
allGlyphsInvisible = false;
|
||||
uint32_t glyphCount = glyphData->GetGlyphCount();
|
||||
if (glyphCount > 0) {
|
||||
const gfxTextRun::DetailedGlyph *details =
|
||||
@ -2261,14 +2285,18 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
||||
}
|
||||
}
|
||||
|
||||
if (aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||
UnionRange(x, &advanceMin, &advanceMax);
|
||||
gfxRect fontBox(advanceMin, -metrics.mAscent,
|
||||
advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
|
||||
metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox);
|
||||
}
|
||||
if (isRTL) {
|
||||
metrics.mBoundingBox -= gfxPoint(x, 0);
|
||||
if (allGlyphsInvisible) {
|
||||
metrics.mBoundingBox.SetEmpty();
|
||||
} else {
|
||||
if (aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||
UnionRange(x, &advanceMin, &advanceMax);
|
||||
gfxRect fontBox(advanceMin, -metrics.mAscent,
|
||||
advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
|
||||
metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox);
|
||||
}
|
||||
if (isRTL) {
|
||||
metrics.mBoundingBox -= gfxPoint(x, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// If the font may be rendered with a fake-italic effect, we need to allow
|
||||
|
@ -1846,6 +1846,8 @@ protected:
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool IsSpaceGlyphInvisible(gfxContext *aRefContext, gfxTextRun *aTextRun);
|
||||
|
||||
void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
||||
void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
||||
|
||||
|
@ -85,6 +85,8 @@ gfxFontEntry::gfxFontEntry() :
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mSpaceGlyphIsInvisible(false),
|
||||
mSpaceGlyphIsInvisibleInitialized(false),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
@ -120,6 +122,8 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
|
||||
mHasSpaceFeaturesKerning(false),
|
||||
mHasSpaceFeaturesNonKerning(false),
|
||||
mSkipDefaultFeatureSpaceCheck(false),
|
||||
mSpaceGlyphIsInvisible(false),
|
||||
mSpaceGlyphIsInvisibleInitialized(false),
|
||||
mCheckedForGraphiteTables(false),
|
||||
mHasCmapTable(false),
|
||||
mGrFaceInitialized(false),
|
||||
|
@ -403,6 +403,8 @@ public:
|
||||
bool mHasSpaceFeaturesKerning : 1;
|
||||
bool mHasSpaceFeaturesNonKerning : 1;
|
||||
bool mSkipDefaultFeatureSpaceCheck : 1;
|
||||
bool mSpaceGlyphIsInvisible : 1;
|
||||
bool mSpaceGlyphIsInvisibleInitialized : 1;
|
||||
bool mHasGraphiteTables : 1;
|
||||
bool mCheckedForGraphiteTables : 1;
|
||||
bool mHasCmapTable : 1;
|
||||
|
@ -5695,36 +5695,22 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
||||
// or from the ::-moz-selection pseudo-class if specified there
|
||||
nsCSSShadowArray* shadow = textStyle->GetTextShadow();
|
||||
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
||||
|
||||
// Draw shadows, if any
|
||||
if (shadow) {
|
||||
gfxTextRun::Metrics shadowMetrics =
|
||||
mTextRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS,
|
||||
nullptr, &aProvider);
|
||||
if (GetStateBits() & TEXT_HYPHEN_BREAK) {
|
||||
AddHyphenToMetrics(this, mTextRun, &shadowMetrics,
|
||||
gfxFont::LOOSE_INK_EXTENTS, aCtx);
|
||||
}
|
||||
for (uint32_t i = shadow->Length(); i > 0; --i) {
|
||||
PaintOneShadow(offset, length,
|
||||
shadow->ShadowAt(i - 1), &aProvider,
|
||||
dirtyRect, aFramePt, textBaselinePt, aCtx,
|
||||
foreground, aClipEdges,
|
||||
iOffset - (mTextRun->IsRightToLeft() ?
|
||||
shadowMetrics.mBoundingBox.width : 0),
|
||||
shadowMetrics.mBoundingBox);
|
||||
nscoord leftEdge = iOffset;
|
||||
if (mTextRun->IsRightToLeft()) {
|
||||
leftEdge -= mTextRun->GetAdvanceWidth(offset, length, &aProvider) +
|
||||
hyphenWidth;
|
||||
}
|
||||
PaintShadows(shadow, offset, length, dirtyRect, aFramePt, textBaselinePt,
|
||||
leftEdge, aProvider, foreground, aClipEdges, aCtx);
|
||||
}
|
||||
|
||||
// Draw text segment
|
||||
gfxFloat advance;
|
||||
|
||||
DrawText(aCtx, aDirtyRect, aFramePt, textBaselinePt,
|
||||
offset, length, aProvider, aTextPaintStyle, foreground, aClipEdges,
|
||||
advance, hyphenWidth > 0, nullptr, nullptr, aCallbacks);
|
||||
if (hyphenWidth) {
|
||||
advance += hyphenWidth;
|
||||
}
|
||||
advance += hyphenWidth;
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
}
|
||||
return true;
|
||||
@ -6040,6 +6026,44 @@ nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider,
|
||||
return maxLength != 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::PaintShadows(nsCSSShadowArray* aShadow,
|
||||
uint32_t aOffset, uint32_t aLength,
|
||||
const nsRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
nscoord aLeftEdgeOffset,
|
||||
PropertyProvider& aProvider,
|
||||
nscolor aForegroundColor,
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
||||
gfxContext* aCtx)
|
||||
{
|
||||
if (!aShadow) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfxTextRun::Metrics shadowMetrics =
|
||||
mTextRun->MeasureText(aOffset, aLength, gfxFont::LOOSE_INK_EXTENTS,
|
||||
nullptr, &aProvider);
|
||||
if (GetStateBits() & TEXT_HYPHEN_BREAK) {
|
||||
AddHyphenToMetrics(this, mTextRun, &shadowMetrics,
|
||||
gfxFont::LOOSE_INK_EXTENTS, aCtx);
|
||||
}
|
||||
// Add bounds of text decorations
|
||||
gfxRect decorationRect(0, -shadowMetrics.mAscent,
|
||||
shadowMetrics.mAdvanceWidth, shadowMetrics.mAscent + shadowMetrics.mDescent);
|
||||
shadowMetrics.mBoundingBox.UnionRect(shadowMetrics.mBoundingBox,
|
||||
decorationRect);
|
||||
for (uint32_t i = aShadow->Length(); i > 0; --i) {
|
||||
PaintOneShadow(aOffset, aLength,
|
||||
aShadow->ShadowAt(i - 1), &aProvider,
|
||||
aDirtyRect, aFramePt, aTextBaselinePt, aCtx,
|
||||
aForegroundColor, aClipEdges,
|
||||
aLeftEdgeOffset,
|
||||
shadowMetrics.mBoundingBox);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
const nsRect& aDirtyRect,
|
||||
@ -6109,20 +6133,9 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||
nscolor foregroundColor = textPaintStyle.GetTextColor();
|
||||
if (!aCallbacks) {
|
||||
const nsStyleText* textStyle = StyleText();
|
||||
if (textStyle->HasTextShadow()) {
|
||||
// Text shadow happens with the last value being painted at the back,
|
||||
// ie. it is painted first.
|
||||
gfxTextRun::Metrics shadowMetrics =
|
||||
mTextRun->MeasureText(startOffset, maxLength, gfxFont::LOOSE_INK_EXTENTS,
|
||||
nullptr, &provider);
|
||||
for (uint32_t i = textStyle->mTextShadow->Length(); i > 0; --i) {
|
||||
PaintOneShadow(startOffset, maxLength,
|
||||
textStyle->mTextShadow->ShadowAt(i - 1), &provider,
|
||||
aDirtyRect, framePt, textBaselinePt, ctx,
|
||||
foregroundColor, clipEdges,
|
||||
snappedLeftEdge, shadowMetrics.mBoundingBox);
|
||||
}
|
||||
}
|
||||
PaintShadows(textStyle->mTextShadow, startOffset, maxLength,
|
||||
aDirtyRect, framePt, textBaselinePt, snappedLeftEdge, provider,
|
||||
foregroundColor, clipEdges, ctx);
|
||||
}
|
||||
|
||||
gfxFloat advanceWidth;
|
||||
|
@ -584,6 +584,17 @@ protected:
|
||||
nscoord aLeftSideOffset,
|
||||
gfxRect& aBoundingBox);
|
||||
|
||||
void PaintShadows(nsCSSShadowArray* aShadow,
|
||||
uint32_t aOffset, uint32_t aLength,
|
||||
const nsRect& aDirtyRect,
|
||||
const gfxPoint& aFramePt,
|
||||
const gfxPoint& aTextBaselinePt,
|
||||
nscoord aLeftEdgeOffset,
|
||||
PropertyProvider& aProvider,
|
||||
nscolor aForegroundColor,
|
||||
const nsCharClipDisplayItem::ClipEdges& aClipEdges,
|
||||
gfxContext* aCtx);
|
||||
|
||||
struct LineDecoration {
|
||||
nsIFrame* mFrame;
|
||||
|
||||
|
@ -908,6 +908,10 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
|
||||
gfxTextRun::Metrics metrics =
|
||||
textRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS,
|
||||
nullptr, nullptr);
|
||||
// Make sure it includes the font-box.
|
||||
gfxRect fontBox(0, -metrics.mAscent,
|
||||
metrics.mAdvanceWidth, metrics.mAscent + metrics.mDescent);
|
||||
metrics.mBoundingBox.UnionRect(metrics.mBoundingBox, fontBox);
|
||||
|
||||
// Determine the rectangle that covers the rendered run's fill,
|
||||
// taking into account the measured vertical overflow due to
|
||||
|
Loading…
x
Reference in New Issue
Block a user