mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07: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
198bbca1c1
commit
68c074dcb8
@ -2114,6 +2114,23 @@ NeedsGlyphExtents(gfxFont *aFont, gfxTextRun *aTextRun)
|
|||||||
aFont->GetFontEntry()->IsUserFont();
|
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::RunMetrics
|
||||||
gfxFont::Measure(gfxTextRun *aTextRun,
|
gfxFont::Measure(gfxTextRun *aTextRun,
|
||||||
uint32_t aStart, uint32_t aEnd,
|
uint32_t aStart, uint32_t aEnd,
|
||||||
@ -2189,16 +2206,22 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
|||||||
if (aSpacing) {
|
if (aSpacing) {
|
||||||
x += direction*aSpacing[0].mBefore;
|
x += direction*aSpacing[0].mBefore;
|
||||||
}
|
}
|
||||||
|
uint32_t spaceGlyph = GetSpaceGlyph();
|
||||||
|
bool allGlyphsInvisible = true;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = aStart; i < aEnd; ++i) {
|
for (i = aStart; i < aEnd; ++i) {
|
||||||
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
|
const gfxTextRun::CompressedGlyph *glyphData = &charGlyphs[i];
|
||||||
if (glyphData->IsSimpleGlyph()) {
|
if (glyphData->IsSimpleGlyph()) {
|
||||||
double advance = glyphData->GetSimpleAdvance();
|
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
|
// Only get the real glyph horizontal extent if we were asked
|
||||||
// for the tight bounding box or we're in quality mode
|
// for the tight bounding box or we're in quality mode
|
||||||
if ((aBoundingBoxType != LOOSE_INK_EXTENTS || needsGlyphExtents) &&
|
if ((aBoundingBoxType != LOOSE_INK_EXTENTS || needsGlyphExtents) &&
|
||||||
extents) {
|
extents){
|
||||||
uint32_t glyphIndex = glyphData->GetSimpleGlyph();
|
|
||||||
uint16_t extentsWidth = extents->GetContainedGlyphWidthAppUnits(glyphIndex);
|
uint16_t extentsWidth = extents->GetContainedGlyphWidthAppUnits(glyphIndex);
|
||||||
if (extentsWidth != gfxGlyphExtents::INVALID_WIDTH &&
|
if (extentsWidth != gfxGlyphExtents::INVALID_WIDTH &&
|
||||||
aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||||
@ -2221,6 +2244,7 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
|||||||
}
|
}
|
||||||
x += direction*advance;
|
x += direction*advance;
|
||||||
} else {
|
} else {
|
||||||
|
allGlyphsInvisible = false;
|
||||||
uint32_t glyphCount = glyphData->GetGlyphCount();
|
uint32_t glyphCount = glyphData->GetGlyphCount();
|
||||||
if (glyphCount > 0) {
|
if (glyphCount > 0) {
|
||||||
const gfxTextRun::DetailedGlyph *details =
|
const gfxTextRun::DetailedGlyph *details =
|
||||||
@ -2261,14 +2285,18 @@ gfxFont::Measure(gfxTextRun *aTextRun,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
if (allGlyphsInvisible) {
|
||||||
UnionRange(x, &advanceMin, &advanceMax);
|
metrics.mBoundingBox.SetEmpty();
|
||||||
gfxRect fontBox(advanceMin, -metrics.mAscent,
|
} else {
|
||||||
advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
|
if (aBoundingBoxType == LOOSE_INK_EXTENTS) {
|
||||||
metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox);
|
UnionRange(x, &advanceMin, &advanceMax);
|
||||||
}
|
gfxRect fontBox(advanceMin, -metrics.mAscent,
|
||||||
if (isRTL) {
|
advanceMax - advanceMin, metrics.mAscent + metrics.mDescent);
|
||||||
metrics.mBoundingBox -= gfxPoint(x, 0);
|
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
|
// If the font may be rendered with a fake-italic effect, we need to allow
|
||||||
|
@ -1846,6 +1846,8 @@ protected:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsSpaceGlyphInvisible(gfxContext *aRefContext, gfxTextRun *aTextRun);
|
||||||
|
|
||||||
void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
void AddGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
||||||
void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
void RemoveGlyphChangeObserver(GlyphChangeObserver *aObserver);
|
||||||
|
|
||||||
|
@ -85,6 +85,8 @@ gfxFontEntry::gfxFontEntry() :
|
|||||||
mHasSpaceFeaturesKerning(false),
|
mHasSpaceFeaturesKerning(false),
|
||||||
mHasSpaceFeaturesNonKerning(false),
|
mHasSpaceFeaturesNonKerning(false),
|
||||||
mSkipDefaultFeatureSpaceCheck(false),
|
mSkipDefaultFeatureSpaceCheck(false),
|
||||||
|
mSpaceGlyphIsInvisible(false),
|
||||||
|
mSpaceGlyphIsInvisibleInitialized(false),
|
||||||
mCheckedForGraphiteTables(false),
|
mCheckedForGraphiteTables(false),
|
||||||
mHasCmapTable(false),
|
mHasCmapTable(false),
|
||||||
mGrFaceInitialized(false),
|
mGrFaceInitialized(false),
|
||||||
@ -120,6 +122,8 @@ gfxFontEntry::gfxFontEntry(const nsAString& aName, bool aIsStandardFace) :
|
|||||||
mHasSpaceFeaturesKerning(false),
|
mHasSpaceFeaturesKerning(false),
|
||||||
mHasSpaceFeaturesNonKerning(false),
|
mHasSpaceFeaturesNonKerning(false),
|
||||||
mSkipDefaultFeatureSpaceCheck(false),
|
mSkipDefaultFeatureSpaceCheck(false),
|
||||||
|
mSpaceGlyphIsInvisible(false),
|
||||||
|
mSpaceGlyphIsInvisibleInitialized(false),
|
||||||
mCheckedForGraphiteTables(false),
|
mCheckedForGraphiteTables(false),
|
||||||
mHasCmapTable(false),
|
mHasCmapTable(false),
|
||||||
mGrFaceInitialized(false),
|
mGrFaceInitialized(false),
|
||||||
|
@ -403,6 +403,8 @@ public:
|
|||||||
bool mHasSpaceFeaturesKerning : 1;
|
bool mHasSpaceFeaturesKerning : 1;
|
||||||
bool mHasSpaceFeaturesNonKerning : 1;
|
bool mHasSpaceFeaturesNonKerning : 1;
|
||||||
bool mSkipDefaultFeatureSpaceCheck : 1;
|
bool mSkipDefaultFeatureSpaceCheck : 1;
|
||||||
|
bool mSpaceGlyphIsInvisible : 1;
|
||||||
|
bool mSpaceGlyphIsInvisibleInitialized : 1;
|
||||||
bool mHasGraphiteTables : 1;
|
bool mHasGraphiteTables : 1;
|
||||||
bool mCheckedForGraphiteTables : 1;
|
bool mCheckedForGraphiteTables : 1;
|
||||||
bool mHasCmapTable : 1;
|
bool mHasCmapTable : 1;
|
||||||
|
@ -5695,36 +5695,22 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
|
|||||||
// or from the ::-moz-selection pseudo-class if specified there
|
// or from the ::-moz-selection pseudo-class if specified there
|
||||||
nsCSSShadowArray* shadow = textStyle->GetTextShadow();
|
nsCSSShadowArray* shadow = textStyle->GetTextShadow();
|
||||||
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
GetSelectionTextShadow(this, type, aTextPaintStyle, &shadow);
|
||||||
|
|
||||||
// Draw shadows, if any
|
|
||||||
if (shadow) {
|
if (shadow) {
|
||||||
gfxTextRun::Metrics shadowMetrics =
|
nscoord leftEdge = iOffset;
|
||||||
mTextRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS,
|
if (mTextRun->IsRightToLeft()) {
|
||||||
nullptr, &aProvider);
|
leftEdge -= mTextRun->GetAdvanceWidth(offset, length, &aProvider) +
|
||||||
if (GetStateBits() & TEXT_HYPHEN_BREAK) {
|
hyphenWidth;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
PaintShadows(shadow, offset, length, dirtyRect, aFramePt, textBaselinePt,
|
||||||
|
leftEdge, aProvider, foreground, aClipEdges, aCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw text segment
|
// Draw text segment
|
||||||
gfxFloat advance;
|
gfxFloat advance;
|
||||||
|
|
||||||
DrawText(aCtx, aDirtyRect, aFramePt, textBaselinePt,
|
DrawText(aCtx, aDirtyRect, aFramePt, textBaselinePt,
|
||||||
offset, length, aProvider, aTextPaintStyle, foreground, aClipEdges,
|
offset, length, aProvider, aTextPaintStyle, foreground, aClipEdges,
|
||||||
advance, hyphenWidth > 0, nullptr, nullptr, aCallbacks);
|
advance, hyphenWidth > 0, nullptr, nullptr, aCallbacks);
|
||||||
if (hyphenWidth) {
|
advance += hyphenWidth;
|
||||||
advance += hyphenWidth;
|
|
||||||
}
|
|
||||||
iterator.UpdateWithAdvance(advance);
|
iterator.UpdateWithAdvance(advance);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -6040,6 +6026,44 @@ nsTextFrame::MeasureCharClippedText(PropertyProvider& aProvider,
|
|||||||
return maxLength != 0;
|
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
|
void
|
||||||
nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
@ -6109,20 +6133,9 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt,
|
|||||||
nscolor foregroundColor = textPaintStyle.GetTextColor();
|
nscolor foregroundColor = textPaintStyle.GetTextColor();
|
||||||
if (!aCallbacks) {
|
if (!aCallbacks) {
|
||||||
const nsStyleText* textStyle = StyleText();
|
const nsStyleText* textStyle = StyleText();
|
||||||
if (textStyle->HasTextShadow()) {
|
PaintShadows(textStyle->mTextShadow, startOffset, maxLength,
|
||||||
// Text shadow happens with the last value being painted at the back,
|
aDirtyRect, framePt, textBaselinePt, snappedLeftEdge, provider,
|
||||||
// ie. it is painted first.
|
foregroundColor, clipEdges, ctx);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gfxFloat advanceWidth;
|
gfxFloat advanceWidth;
|
||||||
|
@ -584,6 +584,17 @@ protected:
|
|||||||
nscoord aLeftSideOffset,
|
nscoord aLeftSideOffset,
|
||||||
gfxRect& aBoundingBox);
|
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 {
|
struct LineDecoration {
|
||||||
nsIFrame* mFrame;
|
nsIFrame* mFrame;
|
||||||
|
|
||||||
|
@ -908,6 +908,10 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
|
|||||||
gfxTextRun::Metrics metrics =
|
gfxTextRun::Metrics metrics =
|
||||||
textRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS,
|
textRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS,
|
||||||
nullptr, nullptr);
|
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,
|
// Determine the rectangle that covers the rendered run's fill,
|
||||||
// taking into account the measured vertical overflow due to
|
// taking into account the measured vertical overflow due to
|
||||||
|
Loading…
Reference in New Issue
Block a user