tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 66524bcb3f11b9198d77a26aeb76f97b34d8b3b8
parent a51ea84980cd8d8edde54757dcee04cb1a9d9abe
Author: agoloman <agoloman@mozilla.com>
Date:   Sat, 18 Oct 2025 06:28:56 +0300

Revert "Bug 1994197 - patch 4 - Also use integer nscoords for textrun ascent/descent metrics and bounding box. r=firefox-svg-reviewers,longsonr" for causing wr failures @text-combine-upright-gen-con-001.html.

This reverts commit d4927b88663c8cfac60eb8a3c5fddbe843ce4af4.

Revert "Bug 1994197 - patch 3 - Convert gfxTextRun text advance computation to nscoord values. r=layout-reviewers,emilio"

This reverts commit c2168d7fb8942ae962c2464c1ca6199b5370bedb.

Revert "Bug 1994197 - patch 2 - Convert more text measurement to use integer nscoord values. r=layout-reviewers,TYLin"

This reverts commit 995e0ca47eb8f541ff932ba5faaab823ff8e9635.

Revert "Bug 1994197 - patch 1 - Use integer nscoord values rather than gfxFloat for gfxFont::Spacing fields. r=layout-reviewers,TYLin"

This reverts commit 8c9d04dcc3a214f277c90dd8c4be2c3f7a50a8cd.

Diffstat:
Mdom/canvas/CanvasRenderingContext2D.cpp | 28++++++++++++----------------
Mgfx/src/nsFontMetrics.cpp | 18++++++++++--------
Mgfx/thebes/gfxFont.cpp | 92+++++++++++++++++++++++++++++++++++--------------------------------------------
Mgfx/thebes/gfxFont.h | 23+++++++++++++----------
Mgfx/thebes/gfxGlyphExtents.cpp | 6+++---
Mgfx/thebes/gfxGlyphExtents.h | 10+++++-----
Mgfx/thebes/gfxTextRun.cpp | 82+++++++++++++++++++++++++++++++++++++------------------------------------------
Mgfx/thebes/gfxTextRun.h | 23+++++++++++++----------
Mlayout/generic/nsTextFrame.cpp | 101++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mlayout/generic/nsTextFrame.h | 12++++++------
Mlayout/mathml/nsMathMLChar.cpp | 10+++++-----
Mlayout/svg/SVGTextFrame.cpp | 17++++++++++-------
Atesting/web-platform/meta/css/css-values/ch-unit-012.html.ini | 3+++
Mtesting/web-platform/meta/css/css-writing-modes/text-combine-upright-gen-con-001.html.ini | 1-
Mtesting/web-platform/mozilla/meta/mathml/tables/dir-6a.html.ini | 1-
15 files changed, 213 insertions(+), 214 deletions(-)

diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp @@ -4665,7 +4665,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final } aSpacing++; } - return mProcessor.mLetterSpacing != 0 || mProcessor.mWordSpacing != 0; + return mProcessor.mLetterSpacing != 0.0 || mProcessor.mWordSpacing != 0.0; } mozilla::StyleHyphens GetHyphensOption() const { @@ -4677,9 +4677,9 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final gfxTextRun::HyphenType* aBreakBefore) const { MOZ_ASSERT_UNREACHABLE("no hyphenation in canvas2d text!"); } - nscoord GetHyphenWidth() const { + gfxFloat GetHyphenWidth() const { MOZ_ASSERT_UNREACHABLE("no hyphenation in canvas2d text!"); - return 0; + return 0.0; } already_AddRefed<DrawTarget> GetDrawTarget() const { MOZ_ASSERT_UNREACHABLE("no hyphenation in canvas2d text!"); @@ -4736,13 +4736,11 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final // this only measures the height; the total width is gotten from the // the return value of ProcessText. if (mDoMeasureBoundingBox) { - // The bounding box is tracked in device pixels. - gfxRect bbox = nsLayoutUtils::RectToGfxRect(textRunMetrics.mBoundingBox, - mAppUnitsPerDevPixel); - mBoundingBox = mBoundingBox.Union(bbox); + textRunMetrics.mBoundingBox.Scale(1.0 / mAppUnitsPerDevPixel); + mBoundingBox = mBoundingBox.Union(textRunMetrics.mBoundingBox); } - return textRunMetrics.mAdvanceWidth; + return NSToCoordRound(textRunMetrics.mAdvanceWidth); } already_AddRefed<gfxPattern> GetGradientFor(Style aStyle) { @@ -4938,8 +4936,8 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final mozilla::gfx::PaletteCache& mPaletteCache; // spacing adjustments to be applied - nscoord mLetterSpacing = 0; - nscoord mWordSpacing = 0; + gfx::Float mLetterSpacing = 0.0f; + gfx::Float mWordSpacing = 0.0f; // to record any unsupported characters found in the text, // and notify front-end if it is interested @@ -5106,9 +5104,8 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText( if (state.letterSpacing != 0.0 || state.wordSpacing != 0.0) { processor.mLetterSpacing = - NSToCoordRound(state.letterSpacing * processor.mAppUnitsPerDevPixel); - processor.mWordSpacing = - NSToCoordRound(state.wordSpacing * processor.mAppUnitsPerDevPixel); + state.letterSpacing * processor.mAppUnitsPerDevPixel; + processor.mWordSpacing = state.wordSpacing * processor.mAppUnitsPerDevPixel; processor.mTextRunFlags |= gfx::ShapedTextFlags::TEXT_ENABLE_SPACING; if (state.letterSpacing != 0.0) { processor.mTextRunFlags |= @@ -5235,7 +5232,7 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText( // based on the text position and advance. if (!doCalculateBounds) { processor.mBoundingBox.width = totalWidth; - processor.mBoundingBox.MoveBy(processor.mPt.x, processor.mPt.y); + processor.mBoundingBox.MoveBy(gfxPoint(processor.mPt.x, processor.mPt.y)); } processor.mPt.x *= processor.mAppUnitsPerDevPixel; @@ -5288,8 +5285,7 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText( if (aOp == CanvasRenderingContext2D::TextDrawOperation::FILL && !doCalculateBounds) { - RedrawUser(gfxRect(boundingBox.x, boundingBox.y, boundingBox.width, - boundingBox.height)); + RedrawUser(boundingBox); } else { Redraw(); } diff --git a/gfx/src/nsFontMetrics.cpp b/gfx/src/nsFontMetrics.cpp @@ -89,7 +89,7 @@ class StubPropertyProvider final : public gfxTextRun::PropertyProvider { "This shouldn't be called because we never call BreakAndMeasureText"); return mozilla::StyleHyphens::None; } - nscoord GetHyphenWidth() const override { + gfxFloat GetHyphenWidth() const override { NS_ERROR("This shouldn't be called because we never enable hyphens"); return 0; } @@ -312,7 +312,8 @@ nscoord nsFontMetrics::GetWidth(const char* aString, uint32_t aLength, StubPropertyProvider provider; AutoTextRun textRun(this, aDrawTarget, aString, aLength); if (textRun.get()) { - return textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider); + return NSToCoordRound( + textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider)); } return 0; } @@ -328,7 +329,8 @@ nscoord nsFontMetrics::GetWidth(const char16_t* aString, uint32_t aLength, StubPropertyProvider provider; AutoTextRun textRun(this, aDrawTarget, aString, aLength); if (textRun.get()) { - return textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider); + return NSToCoordRound( + textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider)); } return 0; } @@ -399,11 +401,11 @@ static nsBoundingMetrics GetTextBoundingMetrics( gfxTextRun::Metrics theMetrics = textRun->MeasureText( gfxTextRun::Range(0, aLength), aType, aDrawTarget, &provider); - m.leftBearing = theMetrics.mBoundingBox.X(); - m.rightBearing = theMetrics.mBoundingBox.XMost(); - m.ascent = -theMetrics.mBoundingBox.Y(); - m.descent = theMetrics.mBoundingBox.YMost(); - m.width = theMetrics.mAdvanceWidth; + m.leftBearing = NSToCoordFloor(theMetrics.mBoundingBox.X()); + m.rightBearing = NSToCoordCeil(theMetrics.mBoundingBox.XMost()); + m.ascent = NSToCoordCeil(-theMetrics.mBoundingBox.Y()); + m.descent = NSToCoordCeil(theMetrics.mBoundingBox.YMost()); + m.width = NSToCoordRound(theMetrics.mAdvanceWidth); } return m; } diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp @@ -32,7 +32,6 @@ #include "gfxUserFontSet.h" #include "nsCRT.h" #include "nsContentUtils.h" -#include "nsLayoutUtils.h" #include "nsSpecialCasingData.h" #include "nsTextRunTransformations.h" #include "nsUGenCategory.h" @@ -963,13 +962,13 @@ void gfxFont::RunMetrics::CombineWith(const RunMetrics& aOther, mAscent = std::max(mAscent, aOther.mAscent); mDescent = std::max(mDescent, aOther.mDescent); if (aOtherIsOnLeft) { - mBoundingBox = (mBoundingBox + nsPoint(aOther.mAdvanceWidth, 0)) + mBoundingBox = (mBoundingBox + gfxPoint(aOther.mAdvanceWidth, 0)) .Union(aOther.mBoundingBox); } else { mBoundingBox = - mBoundingBox.Union(aOther.mBoundingBox + nsPoint(mAdvanceWidth, 0)); + mBoundingBox.Union(aOther.mBoundingBox + gfxPoint(mAdvanceWidth, 0)); } - mAdvanceWidth = NSCoordSaturatingAdd(mAdvanceWidth, aOther.mAdvanceWidth); + mAdvanceWidth += aOther.mAdvanceWidth; } gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont, @@ -2875,7 +2874,7 @@ bool gfxFont::HasColorGlyphFor(uint32_t aCh, uint32_t aNextCh) { return false; } -static void UnionRange(nscoord aX, nscoord* aDestMin, nscoord* aDestMax) { +static void UnionRange(gfxFloat aX, gfxFloat* aDestMin, gfxFloat* aDestMax) { *aDestMin = std::min(*aDestMin, aX); *aDestMax = std::max(*aDestMax, aX); } @@ -2896,7 +2895,7 @@ bool gfxFont::IsSpaceGlyphInvisible(DrawTarget* aRefDrawTarget, GetAdjustedSize() >= 1.0) { gfxGlyphExtents* extents = GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit()); - nsRect glyphExtents; + gfxRect glyphExtents; flag = extents->GetTightGlyphExtentsAppUnits( this, aRefDrawTarget, GetSpaceGlyph(), &glyphExtents) && glyphExtents.IsEmpty() @@ -2912,7 +2911,7 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, DrawTarget* aRefDrawTarget, Spacing* aSpacing, gfxGlyphExtents* aExtents, bool aIsRTL, bool aNeedsGlyphExtents, RunMetrics& aMetrics, - nscoord* aAdvanceMin, nscoord* aAdvanceMax) { + gfxFloat* aAdvanceMin, gfxFloat* aAdvanceMax) { const gfxTextRun::CompressedGlyph* charGlyphs = aTextRun->GetCharacterGlyphs(); uint32_t spaceGlyph = GetSpaceGlyph(); @@ -2936,7 +2935,7 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, gfxFontEntry::LazyFlag flag = mFontEntry->mSpaceGlyphIsInvisible; if (flag == gfxFontEntry::LazyFlag::Uninitialized && GetAdjustedSize() >= 1.0) { - nsRect glyphExtents; + gfxRect glyphExtents; flag = aExtents->GetTightGlyphExtentsAppUnitsLocked( this, aRefDrawTarget, spaceGlyph, &glyphExtents) && glyphExtents.IsEmpty() @@ -2959,11 +2958,11 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, UnionRange(x, aAdvanceMin, aAdvanceMax); UnionRange(x + extentsWidth, aAdvanceMin, aAdvanceMax); } else { - nsRect glyphRect; + gfxRect glyphRect; if (!aExtents->GetTightGlyphExtentsAppUnitsLocked( this, aRefDrawTarget, glyphIndex, &glyphRect)) { - glyphRect = nsRect(0, aMetrics.mBoundingBox.Y(), advance, - aMetrics.mBoundingBox.Height()); + glyphRect = gfxRect(0, aMetrics.mBoundingBox.Y(), advance, + aMetrics.mBoundingBox.Height()); } if (aIsRTL) { // In effect, swap left and right sidebearings of the glyph, for @@ -2986,15 +2985,15 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t j; for (j = 0; j < glyphCount; ++j, ++details) { uint32_t glyphIndex = details->mGlyphID; - nscoord advance = details->mAdvance; - nsRect glyphRect; + double advance = details->mAdvance; + gfxRect glyphRect; if (glyphData->IsMissing() || !aExtents->GetTightGlyphExtentsAppUnitsLocked( this, aRefDrawTarget, glyphIndex, &glyphRect)) { // We might have failed to get glyph extents due to // OOM or something - glyphRect = nsRect(0, -aMetrics.mAscent, advance, - aMetrics.mAscent + aMetrics.mDescent); + glyphRect = gfxRect(0, -aMetrics.mAscent, advance, + aMetrics.mAscent + aMetrics.mDescent); } if (aIsRTL) { // Swap left/right sidebearings of the glyph, because we're doing @@ -3055,9 +3054,9 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, "detailedGlyph record should not be missing!"); uint32_t j; for (j = 0; j < glyphCount; ++j, ++details) { - nscoord advance = details->mAdvance; - nsRect glyphRect(0, -aMetrics.mAscent, advance, - aMetrics.mAscent + aMetrics.mDescent); + double advance = details->mAdvance; + gfxRect glyphRect(0, -aMetrics.mAscent, advance, + aMetrics.mAscent + aMetrics.mDescent); if (aIsRTL) { // Swap left/right sidebearings of the glyph, because we're doing // mirrored measurement. @@ -3125,7 +3124,7 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun, : nsFontMetrics::eHorizontal; const gfxFont::Metrics& fontMetrics = GetMetrics(orientation); - nscoord baselineOffset = 0; + gfxFloat baselineOffset = 0; if (aTextRun->UseCenterBaseline() && orientation == nsFontMetrics::eHorizontal) { // For a horizontal font being used in vertical writing mode with @@ -3137,25 +3136,23 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun, // XXX Eventually we should probably use the BASE table, if present. // But it usually isn't, so we need an ad hoc adjustment for now. baselineOffset = - NSToCoordRound(appUnitsPerDevUnit * - (fontMetrics.emAscent - fontMetrics.emDescent) / 2.0); + appUnitsPerDevUnit * (fontMetrics.emAscent - fontMetrics.emDescent) / 2; } RunMetrics metrics; - metrics.mAscent = NSToCoordRound(fontMetrics.maxAscent * appUnitsPerDevUnit); - metrics.mDescent = - NSToCoordRound(fontMetrics.maxDescent * appUnitsPerDevUnit); + metrics.mAscent = fontMetrics.maxAscent * appUnitsPerDevUnit; + metrics.mDescent = fontMetrics.maxDescent * appUnitsPerDevUnit; if (aStart == aEnd) { // exit now before we look at aSpacing[0], which is undefined metrics.mAscent -= baselineOffset; metrics.mDescent += baselineOffset; metrics.mBoundingBox = - nsRect(0, -metrics.mAscent, 0, metrics.mAscent + metrics.mDescent); + gfxRect(0, -metrics.mAscent, 0, metrics.mAscent + metrics.mDescent); return metrics; } - nscoord advanceMin = 0, advanceMax = 0; + gfxFloat advanceMin = 0, advanceMax = 0; bool isRTL = aTextRun->IsRightToLeft(); bool needsGlyphExtents = NeedsGlyphExtents(this, aTextRun); gfxGlyphExtents* extents = @@ -3180,8 +3177,8 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun, metrics.mBoundingBox.SetEmpty(); } else if (aBoundingBoxType == LOOSE_INK_EXTENTS) { UnionRange(metrics.mAdvanceWidth, &advanceMin, &advanceMax); - nsRect fontBox(advanceMin, -metrics.mAscent, advanceMax - advanceMin, - metrics.mAscent + metrics.mDescent); + gfxRect fontBox(advanceMin, -metrics.mAscent, advanceMax - advanceMin, + metrics.mAscent + metrics.mDescent); metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox); } @@ -3212,10 +3209,9 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun, extendRightEdge = skew < 0.0 ? ceil(-skew * metrics.mBoundingBox.YMost()) : ceil(skew * -metrics.mBoundingBox.Y()); } - metrics.mBoundingBox.SetWidth( - metrics.mBoundingBox.Width() + - NSToCoordRound(extendLeftEdge + extendRightEdge)); - metrics.mBoundingBox.MoveByX(NSToCoordRound(-extendLeftEdge)); + metrics.mBoundingBox.SetWidth(metrics.mBoundingBox.Width() + + extendLeftEdge + extendRightEdge); + metrics.mBoundingBox.MoveByX(-extendLeftEdge); } if (baselineOffset != 0) { @@ -4115,27 +4111,16 @@ gfxGlyphExtents* gfxFont::GetOrCreateGlyphExtents(int32_t aAppUnitsPerDevUnit) { return glyphExtents; } -// Helper to convert device-pixel bounds to nsRect using aAppPerDev factor. -// Note: not using nsLayoutUtils::RoundGfxRectToAppRect here because it -// has different rounding behavior (using Rect::ScaleRoundOut rather than -// rounding the individual fields), which affects MathML glyph placement. -template <class T> -static inline nsRect ToAppRect(const T& aBounds, int32_t aAppPerDev) { - return nsRect(NSToCoordRound(aBounds.X() * aAppPerDev), - NSToCoordRound(aBounds.Y() * aAppPerDev), - NSToCoordRound(aBounds.Width() * aAppPerDev), - NSToCoordRound(aBounds.Height() * aAppPerDev)); -} - void gfxFont::SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID, bool aNeedTight, gfxGlyphExtents* aExtents) { - int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit(); gfxRect svgBounds; if (mFontEntry->TryGetSVGData(this) && mFontEntry->HasSVGGlyph(aGlyphID) && mFontEntry->GetSVGGlyphExtents(aDrawTarget, aGlyphID, GetAdjustedSize(), &svgBounds)) { - aExtents->SetTightGlyphExtents(aGlyphID, - ToAppRect(svgBounds, appUnitsPerDevUnit)); + gfxFloat d2a = aExtents->GetAppUnitsPerDevUnit(); + aExtents->SetTightGlyphExtents( + aGlyphID, gfxRect(svgBounds.X() * d2a, svgBounds.Y() * d2a, + svgBounds.Width() * d2a, svgBounds.Height() * d2a)); return; } @@ -4148,8 +4133,10 @@ void gfxFont::SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID, mFontEntry->mCOLR, shaper->GetHBFont(), aGlyphID, aDrawTarget, scaledFont, mFUnitsConvFactor); if (!r.IsEmpty()) { - aExtents->SetTightGlyphExtents(aGlyphID, - ToAppRect(r, appUnitsPerDevUnit)); + gfxFloat d2a = aExtents->GetAppUnitsPerDevUnit(); + aExtents->SetTightGlyphExtents( + aGlyphID, gfxRect(r.X() * d2a, r.Y() * d2a, r.Width() * d2a, + r.Height() * d2a)); return; } } @@ -4159,6 +4146,7 @@ void gfxFont::SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID, GetGlyphBounds(aGlyphID, &bounds, mAntialiasOption == kAntialiasNone); const Metrics& fontMetrics = GetMetrics(nsFontMetrics::eHorizontal); + int32_t appUnitsPerDevUnit = aExtents->GetAppUnitsPerDevUnit(); if (!aNeedTight && bounds.x >= 0.0 && bounds.y >= -fontMetrics.maxAscent && bounds.height + bounds.y <= fontMetrics.maxDescent) { uint32_t appUnitsWidth = @@ -4175,8 +4163,10 @@ void gfxFont::SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID, } #endif - aExtents->SetTightGlyphExtents(aGlyphID, - ToAppRect(bounds, appUnitsPerDevUnit)); + gfxFloat d2a = appUnitsPerDevUnit; + aExtents->SetTightGlyphExtents( + aGlyphID, gfxRect(bounds.x * d2a, bounds.y * d2a, bounds.width * d2a, + bounds.height * d2a)); } // Try to initialize font metrics by reading sfnt tables directly; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h @@ -1652,28 +1652,31 @@ class gfxFont { * We let layout specify spacing on either side of any * character. We need to specify both before and after * spacing so that substring measurement can do the right things. - * These values are in appunits. + * These values are in appunits. They're always an integral number of + * appunits, but we specify them in floats in case very large spacing + * values are required. */ struct Spacing { - nscoord mBefore; - nscoord mAfter; + gfxFloat mBefore; + gfxFloat mAfter; }; - /** - * Metrics for a particular string. These are in appUnits. + * Metrics for a particular string */ struct RunMetrics { + RunMetrics() { mAdvanceWidth = mAscent = mDescent = 0.0; } + void CombineWith(const RunMetrics& aOther, bool aOtherIsOnLeft); // can be negative (partly due to negative spacing). // Advance widths should be additive: the advance width of the // (offset1, length1) plus the advance width of (offset1 + length1, // length2) should be the advance width of (offset1, length1 + length2) - nscoord mAdvanceWidth = 0; + gfxFloat mAdvanceWidth; // For zero-width substrings, these must be zero! - nscoord mAscent = 0; // always non-negative - nscoord mDescent = 0; // always non-negative + gfxFloat mAscent; // always non-negative + gfxFloat mDescent; // always non-negative // Bounding box that is guaranteed to include everything drawn. // If a tight boundingBox was requested when these metrics were @@ -1681,7 +1684,7 @@ class gfxFont { // "loose" and may be larger than the true bounding box. // Coordinates are relative to the baseline left origin, so typically // mBoundingBox.y == -mAscent - nsRect mBoundingBox; + gfxRect mBoundingBox; }; /** @@ -1957,7 +1960,7 @@ class gfxFont { DrawTarget* aRefDrawTarget, Spacing* aSpacing, gfxGlyphExtents* aExtents, bool aIsRTL, bool aNeedsGlyphExtents, RunMetrics& aMetrics, - nscoord* aAdvanceMin, nscoord* aAdvanceMax); + gfxFloat* aAdvanceMin, gfxFloat* aAdvanceMax); bool MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, uint32_t aEnd, BoundingBoxType aBoundingBoxType, diff --git a/gfx/thebes/gfxGlyphExtents.cpp b/gfx/thebes/gfxGlyphExtents.cpp @@ -35,7 +35,7 @@ gfxGlyphExtents::~gfxGlyphExtents() { bool gfxGlyphExtents::GetTightGlyphExtentsAppUnitsLocked( gfxFont* aFont, DrawTarget* aDrawTarget, uint32_t aGlyphID, - nsRect* aExtents) { + gfxRect* aExtents) { HashEntry* entry = mTightGlyphExtents.GetEntry(aGlyphID); if (!entry) { // Some functions higher up in the call chain deliberately pass in a @@ -64,7 +64,7 @@ bool gfxGlyphExtents::GetTightGlyphExtentsAppUnitsLocked( } } - *aExtents = nsRect(entry->x, entry->y, entry->width, entry->height); + *aExtents = gfxRect(entry->x, entry->y, entry->width, entry->height); return true; } @@ -127,7 +127,7 @@ void gfxGlyphExtents::GlyphWidths::Set(uint32_t aGlyphID, uint16_t aWidth) { } void gfxGlyphExtents::SetTightGlyphExtents(uint32_t aGlyphID, - const nsRect& aExtentsAppUnits) { + const gfxRect& aExtentsAppUnits) { AutoWriteLock lock(mLock); HashEntry* entry = mTightGlyphExtents.PutEntry(aGlyphID); if (!entry) { diff --git a/gfx/thebes/gfxGlyphExtents.h b/gfx/thebes/gfxGlyphExtents.h @@ -77,10 +77,10 @@ class gfxGlyphExtents { // and extents were not (successfully) prefetched. bool GetTightGlyphExtentsAppUnitsLocked(gfxFont* aFont, DrawTarget* aDrawTarget, - uint32_t aGlyphID, nsRect* aExtents) + uint32_t aGlyphID, gfxRect* aExtents) MOZ_REQUIRES_SHARED(mLock); bool GetTightGlyphExtentsAppUnits(gfxFont* aFont, DrawTarget* aDrawTarget, - uint32_t aGlyphID, nsRect* aExtents) { + uint32_t aGlyphID, gfxRect* aExtents) { mozilla::AutoReadLock lock(mLock); return GetTightGlyphExtentsAppUnitsLocked(aFont, aDrawTarget, aGlyphID, aExtents); @@ -90,7 +90,7 @@ class gfxGlyphExtents { mozilla::AutoWriteLock lock(mLock); mContainedGlyphWidths.Set(aGlyphID, aWidth); } - void SetTightGlyphExtents(uint32_t aGlyphID, const nsRect& aExtentsAppUnits); + void SetTightGlyphExtents(uint32_t aGlyphID, const gfxRect& aExtentsAppUnits); int32_t GetAppUnitsPerDevUnit() { return mAppUnitsPerDevUnit; } @@ -103,7 +103,7 @@ class gfxGlyphExtents { // When constructing a new entry in the hashtable, we'll leave this // blank. The caller of Put() will fill this in. explicit HashEntry(KeyTypePointer aPtr) - : nsUint32HashKey(aPtr), x(0), y(0), width(0), height(0) {} + : nsUint32HashKey(aPtr), x(0.0), y(0.0), width(0.0), height(0.0) {} HashEntry(HashEntry&& aOther) : nsUint32HashKey(std::move(aOther)), x(aOther.x), @@ -111,7 +111,7 @@ class gfxGlyphExtents { width(aOther.width), height(aOther.height) {} - nscoord x, y, width, height; + float x, y, width, height; }; enum { diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp @@ -29,7 +29,6 @@ #include "mozilla/StaticPresData.h" #include "mozilla/UniquePtr.h" #include "mozilla/Unused.h" -#include "nsLayoutUtils.h" #include "nsStyleConsts.h" #include "nsStyleUtil.h" #include "nsUnicodeProperties.h" @@ -282,7 +281,7 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( } result.mRange.end = i; - nscoord ligatureWidth = GetAdvanceForGlyphs(result.mRange); + int32_t ligatureWidth = GetAdvanceForGlyphs(result.mRange); // Count the number of started clusters we have seen uint32_t totalClusterCount = 0; uint32_t partClusterIndex = 0; @@ -308,7 +307,7 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( // so that measuring all parts of a ligature and summing them is equal to // the ligature width. if (aPartRange.end == result.mRange.end) { - nscoord allParts = totalClusterCount * (ligatureWidth / totalClusterCount); + gfxFloat allParts = totalClusterCount * (ligatureWidth / totalClusterCount); result.mPartWidth += ligatureWidth - allParts; } @@ -332,15 +331,13 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( if (aPartRange.start == result.mRange.start) { if (aProvider->GetSpacing(Range(aPartRange.start, aPartRange.start + 1), &spacing)) { - result.mPartWidth = - NSCoordSaturatingAdd(result.mPartWidth, spacing.mBefore); + result.mPartWidth += spacing.mBefore; } } if (aPartRange.end == result.mRange.end) { if (aProvider->GetSpacing(Range(aPartRange.end - 1, aPartRange.end), &spacing)) { - result.mPartWidth = - NSCoordSaturatingAdd(result.mPartWidth, spacing.mAfter); + result.mPartWidth += spacing.mAfter; } } } @@ -348,19 +345,17 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( return result; } -nscoord gfxTextRun::ComputePartialLigatureWidth( +gfxFloat gfxTextRun::ComputePartialLigatureWidth( Range aPartRange, const PropertyProvider* aProvider) const { - if (aPartRange.start >= aPartRange.end) { - return 0; - } + if (aPartRange.start >= aPartRange.end) return 0; LigatureData data = ComputeLigatureData(aPartRange, aProvider); return data.mPartWidth; } -nscoord gfxTextRun::GetAdvanceForGlyphs(Range aRange) const { - nscoord advance = 0; +int32_t gfxTextRun::GetAdvanceForGlyphs(Range aRange) const { + int32_t advance = 0; for (auto i = aRange.start; i < aRange.end; ++i) { - advance = NSCoordSaturatingAdd(advance, GetAdvanceForGlyph(i)); + advance += GetAdvanceForGlyph(i); } return advance; } @@ -553,11 +548,12 @@ struct MOZ_STACK_CLASS BufferAlphaColor { ~BufferAlphaColor() = default; - void PushSolidColor(const nsRect& aBounds, const DeviceColor& aAlphaColor, + void PushSolidColor(const gfxRect& aBounds, const DeviceColor& aAlphaColor, uint32_t appsPerDevUnit) { mContext->Save(); - mContext->SnappedClip( - nsLayoutUtils::RectToGfxRect(aBounds, appsPerDevUnit)); + mContext->SnappedClip(gfxRect( + aBounds.X() / appsPerDevUnit, aBounds.Y() / appsPerDevUnit, + aBounds.Width() / appsPerDevUnit, aBounds.Height() / appsPerDevUnit)); mContext->SetDeviceColor( DeviceColor(aAlphaColor.r, aAlphaColor.g, aAlphaColor.b)); mContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, aAlphaColor.a); @@ -676,9 +672,9 @@ void gfxTextRun::Draw(const Range aRange, const gfx::Point aPt, aParams.provider); if (IsRightToLeft()) { metrics.mBoundingBox.MoveBy( - nsPoint(aPt.x - metrics.mAdvanceWidth, aPt.y)); + gfxPoint(aPt.x - metrics.mAdvanceWidth, aPt.y)); } else { - metrics.mBoundingBox.MoveBy(nsPoint(aPt.x, aPt.y)); + metrics.mBoundingBox.MoveBy(gfxPoint(aPt.x, aPt.y)); } gotMetrics = true; } @@ -979,19 +975,19 @@ uint32_t gfxTextRun::BreakAndMeasureText( } } - nscoord width = 0; - nscoord advance = 0; + gfxFloat width = 0; + gfxFloat advance = 0; // The number of space characters that can be trimmed or hang at a soft-wrap uint32_t trimmableChars = 0; // The amount of space removed by ignoring trimmableChars - nscoord trimmableAdvance = 0; + gfxFloat trimmableAdvance = 0; int32_t lastBreak = -1; int32_t lastBreakTrimmableChars = -1; - nscoord lastBreakTrimmableAdvance = -1; + gfxFloat lastBreakTrimmableAdvance = -1; // Cache the last candidate break int32_t lastCandidateBreak = -1; int32_t lastCandidateBreakTrimmableChars = -1; - nscoord lastCandidateBreakTrimmableAdvance = -1; + gfxFloat lastCandidateBreakTrimmableAdvance = -1; bool lastCandidateBreakUsedHyphenation = false; gfxBreakPriority lastCandidateBreakPriority = gfxBreakPriority::eNoBreak; bool aborted = false; @@ -1103,7 +1099,7 @@ uint32_t gfxTextRun::BreakAndMeasureText( : gfxBreakPriority::eWordWrapBreak; } - width = NSCoordSaturatingAdd(width, advance); + width += advance; advance = 0; if (width - trimmableAdvance > aWidth) { // No more text fits. Abort @@ -1139,24 +1135,23 @@ uint32_t gfxTextRun::BreakAndMeasureText( continue; } - nscoord charAdvance; + gfxFloat charAdvance; if (i >= ligatureRange.start && i < ligatureRange.end) { charAdvance = GetAdvanceForGlyphs(Range(i, i + 1)); if (haveSpacing) { PropertyProvider::Spacing* space = &spacingBuffer[i - bufferRange.start]; - charAdvance = - NSCoordSaturatingAdd(charAdvance, space->mBefore + space->mAfter); + charAdvance += space->mBefore + space->mAfter; } } else { charAdvance = ComputePartialLigatureWidth(Range(i, i + 1), &aProvider); } - advance = NSCoordSaturatingAdd(advance, charAdvance); + advance += charAdvance; if (aOutTrimmableWhitespace) { if (mCharacterGlyphs[i].CharIsSpace()) { ++trimmableChars; - trimmableAdvance = NSCoordSaturatingAdd(trimmableAdvance, charAdvance); + trimmableAdvance += charAdvance; } else { trimmableAdvance = 0; trimmableChars = 0; @@ -1165,7 +1160,7 @@ uint32_t gfxTextRun::BreakAndMeasureText( } if (!aborted) { - width = NSCoordSaturatingAdd(width, advance); + width += advance; } // There are three possibilities: @@ -1215,20 +1210,20 @@ uint32_t gfxTextRun::BreakAndMeasureText( return charsFit; } -nscoord gfxTextRun::GetAdvanceWidth(Range aRange, - const PropertyProvider* aProvider, - PropertyProvider::Spacing* aSpacing) const { +gfxFloat gfxTextRun::GetAdvanceWidth( + Range aRange, const PropertyProvider* aProvider, + PropertyProvider::Spacing* aSpacing) const { NS_ASSERTION(aRange.end <= GetLength(), "Substring out of range"); Range ligatureRange = aRange; bool adjusted = ShrinkToLigatureBoundaries(&ligatureRange); - nscoord result = + gfxFloat result = adjusted ? ComputePartialLigatureWidth( Range(aRange.start, ligatureRange.start), aProvider) + ComputePartialLigatureWidth( Range(ligatureRange.end, aRange.end), aProvider) - : 0; + : 0.0; if (aSpacing) { aSpacing->mBefore = aSpacing->mAfter = 0; @@ -1244,7 +1239,7 @@ nscoord gfxTextRun::GetAdvanceWidth(Range aRange, spacingBuffer.Elements())) { for (i = 0; i < ligatureRange.Length(); ++i) { PropertyProvider::Spacing* space = &spacingBuffer[i]; - result = NSCoordSaturatingAdd(result, space->mBefore + space->mAfter); + result += space->mBefore + space->mAfter; } if (aSpacing) { aSpacing->mBefore = spacingBuffer[0].mBefore; @@ -1254,34 +1249,33 @@ nscoord gfxTextRun::GetAdvanceWidth(Range aRange, } } - return NSCoordSaturatingAdd(result, GetAdvanceForGlyphs(ligatureRange)); + return result + GetAdvanceForGlyphs(ligatureRange); } -nscoord gfxTextRun::GetMinAdvanceWidth(Range aRange) { +gfxFloat gfxTextRun::GetMinAdvanceWidth(Range aRange) { MOZ_ASSERT(aRange.end <= GetLength(), "Substring out of range"); Range ligatureRange = aRange; bool adjusted = ShrinkToLigatureBoundaries(&ligatureRange); - nscoord result = + gfxFloat result = adjusted ? std::max(ComputePartialLigatureWidth( Range(aRange.start, ligatureRange.start), nullptr), ComputePartialLigatureWidth( Range(ligatureRange.end, aRange.end), nullptr)) - : 0; + : 0.0; // Compute min advance width by assuming each grapheme cluster takes its own // line. - nscoord clusterAdvance = 0; + gfxFloat clusterAdvance = 0; for (uint32_t i = ligatureRange.start; i < ligatureRange.end; ++i) { if (mCharacterGlyphs[i].CharIsSpace()) { // Skip space char to prevent its advance width contributing to the // result. That is, don't consider a space can be in its own line. continue; } - clusterAdvance = - NSCoordSaturatingAdd(clusterAdvance, GetAdvanceForGlyph(i)); + clusterAdvance += GetAdvanceForGlyph(i); if (i + 1 == ligatureRange.end || IsClusterStart(i + 1)) { result = std::max(result, clusterAdvance); clusterAdvance = 0; diff --git a/gfx/thebes/gfxTextRun.h b/gfx/thebes/gfxTextRun.h @@ -230,7 +230,7 @@ class gfxTextRun : public gfxShapedText { // Returns the extra width that will be consumed by a hyphen. This should // be constant for a given textrun. - virtual nscoord GetHyphenWidth() const = 0; + virtual gfxFloat GetHyphenWidth() const = 0; // Return orientation flags to be used when creating a hyphen textrun. virtual mozilla::gfx::ShapedTextFlags GetShapedTextFlags() const = 0; @@ -338,10 +338,10 @@ class gfxTextRun : public gfxShapedText { * the substring would be returned in it. NOTE: the spacing is * included in the advance width. */ - nscoord GetAdvanceWidth(Range aRange, const PropertyProvider* aProvider, - PropertyProvider::Spacing* aSpacing = nullptr) const; + gfxFloat GetAdvanceWidth(Range aRange, const PropertyProvider* aProvider, + PropertyProvider::Spacing* aSpacing = nullptr) const; - nscoord GetAdvanceWidth() const { + gfxFloat GetAdvanceWidth() const { return GetAdvanceWidth(Range(this), nullptr); } @@ -349,7 +349,7 @@ class gfxTextRun : public gfxShapedText { * Computes the minimum advance width for a substring assuming line * breaking is allowed everywhere. */ - nscoord GetMinAdvanceWidth(Range aRange); + gfxFloat GetMinAdvanceWidth(Range aRange); /** * Clear all stored line breaks for the given range (both before and after), @@ -724,11 +724,11 @@ class gfxTextRun : public gfxShapedText { Range mRange; // appunits advance to the start of the ligature part within the ligature; // never includes any spacing - nscoord mPartAdvance; + gfxFloat mPartAdvance; // appunits width of the ligature part; includes before-spacing // when the part is at the start of the ligature, and after-spacing // when the part is as the end of the ligature - nscoord mPartWidth; + gfxFloat mPartWidth; bool mClipBeforePart; bool mClipAfterPart; @@ -822,7 +822,7 @@ class gfxTextRun : public gfxShapedText { // **** general helpers **** // Get the total advance for a range of glyphs. - nscoord GetAdvanceForGlyphs(Range aRange) const; + int32_t GetAdvanceForGlyphs(Range aRange) const; // Spacing for characters outside the range aSpacingStart/aSpacingEnd // is assumed to be zero; such characters are not passed to aProvider. @@ -844,8 +844,8 @@ class gfxTextRun : public gfxShapedText { // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero LigatureData ComputeLigatureData(Range aPartRange, const PropertyProvider* aProvider) const; - nscoord ComputePartialLigatureWidth(Range aPartRange, - const PropertyProvider* aProvider) const; + gfxFloat ComputePartialLigatureWidth(Range aPartRange, + const PropertyProvider* aProvider) const; void DrawPartialLigature(gfxFont* aFont, Range aRange, mozilla::gfx::Point* aPt, const PropertyProvider* aProvider, @@ -856,6 +856,9 @@ class gfxTextRun : public gfxShapedText { // aRange->start == aRange->end. // Returns whether any adjustment was made. bool ShrinkToLigatureBoundaries(Range* aRange) const; + // result in appunits + gfxFloat GetPartialLigatureWidth(Range aRange, + const PropertyProvider* aProvider) const; void AccumulatePartialLigatureMetrics( gfxFont* aFont, Range aRange, gfxFont::BoundingBoxType aBoundingBoxType, DrawTarget* aRefDrawTarget, const PropertyProvider* aProvider, diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp @@ -272,11 +272,11 @@ TextAutospace::BoundarySet TextAutospace::InitBoundarySet( } // namespace mozilla struct TabWidth { - TabWidth(uint32_t aOffset, nscoord aWidth) - : mOffset(aOffset), mWidth(aWidth) {} + TabWidth(uint32_t aOffset, uint32_t aWidth) + : mOffset(aOffset), mWidth(float(aWidth)) {} uint32_t mOffset; // DOM offset relative to the current frame's offset. - nscoord mWidth; // extra space to be added at this position (in app units) + float mWidth; // extra space to be added at this position (in app units) }; struct nsTextFrame::TabWidthStore { @@ -3464,7 +3464,7 @@ nsTextFrame::PropertyProvider::PropertyProvider( mLength(aLength), mWordSpacing(WordSpacing(aFrame, *aTextStyle)), mLetterSpacing(LetterSpacing(aFrame, *aTextStyle)), - mMinTabAdvance(-1), + mMinTabAdvance(-1.0), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(aOffsetFromBlockOriginForTabs), mJustificationArrayStart(0), @@ -3494,7 +3494,7 @@ nsTextFrame::PropertyProvider::PropertyProvider( mLength(aFrame->GetContentLength()), mWordSpacing(WordSpacing(aFrame, *mTextStyle)), mLetterSpacing(LetterSpacing(aFrame, *mTextStyle)), - mMinTabAdvance(-1), + mMinTabAdvance(-1.0), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(0), mJustificationArrayStart(0), @@ -3514,7 +3514,7 @@ already_AddRefed<DrawTarget> nsTextFrame::PropertyProvider::GetDrawTarget() } gfxFloat nsTextFrame::PropertyProvider::MinTabAdvance() const { - if (mMinTabAdvance < 0) { + if (mMinTabAdvance < 0.0) { mMinTabAdvance = GetMinTabAdvanceAppUnits(mTextRun); } return mMinTabAdvance; @@ -3863,7 +3863,7 @@ static gfxFloat ComputeTabWidthAppUnits(const nsIFrame* aFrame) { MOZ_ASSERT(tabSize.IsNumber()); gfxFloat spaces = tabSize.number._0; - MOZ_ASSERT(spaces >= 0.0); + MOZ_ASSERT(spaces >= 0); const nsIFrame* cb = aFrame->GetContainingBlock(0, aFrame->StyleDisplay()); const auto* styleText = cb->StyleText(); @@ -3879,8 +3879,8 @@ static gfxFloat ComputeTabWidthAppUnits(const nsIFrame* aFrame) { RefPtr font = fm->GetThebesFontGroup()->GetFirstValidFont(' '); auto metrics = font->GetMetrics(vertical ? nsFontMetrics::eVertical : nsFontMetrics::eHorizontal); - nscoord spaceWidth = NSToCoordRound(metrics.spaceWidth * - cb->PresContext()->AppUnitsPerDevPixel()); + nscoord spaceWidth = nscoord( + NS_round(metrics.spaceWidth * cb->PresContext()->AppUnitsPerDevPixel())); return spaces * (spaceWidth + styleText->mLetterSpacing.Resolve(fm->EmHeight()) + styleText->mWordSpacing.Resolve(spaceWidth)); @@ -4091,24 +4091,24 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange, // 0 - Gecko legacy model, spacing added to trailing side of letter // 1 - WebKit/Blink-compatible, spacing added to right-hand side // 2 - Symmetrical spacing, half added to each side - nscoord before, after; + gfxFloat before, after; switch (StaticPrefs::layout_css_letter_spacing_model()) { default: // use Gecko legacy behavior if pref value is unknown case 0: - before = 0; + before = 0.0; after = mLetterSpacing; break; case 1: if (mTextRun->IsRightToLeft()) { before = mLetterSpacing; - after = 0; + after = 0.0; } else { - before = 0; + before = 0.0; after = mLetterSpacing; } break; case 2: - before = NSToCoordRound(mLetterSpacing * 0.5); + before = mLetterSpacing / 2.0; after = mLetterSpacing - before; break; } @@ -4170,12 +4170,12 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange, uint32_t runOffsetInSubstring = run.GetSkippedOffset() - aRange.start; gfxSkipCharsIterator iter = run.GetPos(); for (int32_t i = 0; i < run.GetRunLength(); ++i) { - if (!atStart && before != 0 && + if (!atStart && before != 0.0 && CanAddSpacingBefore(mTextRun, run.GetSkippedOffset() + i, newlineIsSignificant)) { aSpacing[runOffsetInSubstring + i].mBefore += before; } - if (after != 0 && + if (after != 0.0 && CanAddSpacingAfter(mTextRun, run.GetSkippedOffset() + i, newlineIsSignificant)) { // End of a cluster, not in a ligature: put letter-spacing after it @@ -4266,13 +4266,12 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange, } // aX and the result are in whole appunits. -static nscoord AdvanceToNextTab(nscoord aX, gfxFloat aTabWidth, - gfxFloat aMinAdvance) { +static gfxFloat AdvanceToNextTab(gfxFloat aX, gfxFloat aTabWidth, + gfxFloat aMinAdvance) { // Advance aX to the next multiple of aTabWidth. We must advance // by at least aMinAdvance. gfxFloat nextPos = aX + aMinAdvance; - return NSToCoordRound(aTabWidth > 0 ? ceil(nextPos / aTabWidth) * aTabWidth - : nextPos); + return aTabWidth > 0.0 ? ceil(nextPos / aTabWidth) * aTabWidth : nextPos; } void nsTextFrame::PropertyProvider::CalcTabWidths(Range aRange, @@ -4333,10 +4332,11 @@ void nsTextFrame::PropertyProvider::CalcTabWidths(Range aRange, mTabWidths = new TabWidthStore(mFrame->GetContentOffset()); mFrame->SetProperty(TabWidthProperty(), mTabWidths); } - nscoord nextTab = AdvanceToNextTab(mOffsetFromBlockOriginForTabs, - aTabWidth, MinTabAdvance()); + double nextTab = AdvanceToNextTab(mOffsetFromBlockOriginForTabs, + aTabWidth, MinTabAdvance()); mTabWidths->mWidths.AppendElement( - TabWidth(i - startOffset, nextTab - mOffsetFromBlockOriginForTabs)); + TabWidth(i - startOffset, + NSToIntRound(nextTab - mOffsetFromBlockOriginForTabs))); mOffsetFromBlockOriginForTabs = nextTab; } @@ -4356,7 +4356,7 @@ void nsTextFrame::PropertyProvider::CalcTabWidths(Range aRange, } } -nscoord nsTextFrame::PropertyProvider::GetHyphenWidth() const { +gfxFloat nsTextFrame::PropertyProvider::GetHyphenWidth() const { if (mHyphenWidth < 0) { const auto& hyphenateChar = mTextStyle->mHyphenateCharacter; if (hyphenateChar.IsAuto()) { @@ -6570,8 +6570,7 @@ static void AddHyphenToMetrics(nsTextFrame* aTextFrame, bool aIsRightToLeft, void nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams, const StyleSimpleShadow& aShadowDetails, - const gfxRect& aBoundingBox, - uint32_t aBlurFlags) { + gfxRect& aBoundingBox, uint32_t aBlurFlags) { AUTO_PROFILER_LABEL("nsTextFrame::PaintOneShadow", GRAPHICS); nsPoint shadowOffset(aShadowDetails.horizontal.ToAppUnits(), @@ -7375,8 +7374,8 @@ void nsTextFrame::PaintShadows(Span<const StyleSimpleShadow> aShadows, aParams.context->GetDrawTarget()); } // Add bounds of text decorations - nsRect decorationRect(0, -shadowMetrics.mAscent, shadowMetrics.mAdvanceWidth, - shadowMetrics.mAscent + shadowMetrics.mDescent); + gfxRect decorationRect(0, -shadowMetrics.mAscent, shadowMetrics.mAdvanceWidth, + shadowMetrics.mAscent + shadowMetrics.mDescent); shadowMetrics.mBoundingBox.UnionRect(shadowMetrics.mBoundingBox, decorationRect); @@ -7400,12 +7399,7 @@ void nsTextFrame::PaintShadows(Span<const StyleSimpleShadow> aShadows, } for (const auto& shadow : Reversed(aShadows)) { - PaintOneShadow( - aParams, shadow, - gfxRect(shadowMetrics.mBoundingBox.x, shadowMetrics.mBoundingBox.y, - shadowMetrics.mBoundingBox.width, - shadowMetrics.mBoundingBox.height), - blurFlags); + PaintOneShadow(aParams, shadow, shadowMetrics.mBoundingBox, blurFlags); } } @@ -9553,7 +9547,7 @@ void nsTextFrame::AddInlineMinISizeForFlow(gfxContext* aRenderingContext, aData->ForceBreak(); } else if (i < flowEndInTextRun && hyphenating && gfxTextRun::IsOptionalHyphenBreak(hyphBuffer[i - start])) { - aData->OptionallyBreak(provider.GetHyphenWidth()); + aData->OptionallyBreak(NSToCoordRound(provider.GetHyphenWidth())); } else { aData->OptionallyBreak(); } @@ -9880,6 +9874,15 @@ nsIFrame::SizeComputationResult nsTextFrame::ComputeSize( AspectRatioUsage::None}; } +static nsRect RoundOut(const gfxRect& aRect) { + nsRect r; + r.x = NSToCoordFloor(aRect.X()); + r.y = NSToCoordFloor(aRect.Y()); + r.width = NSToCoordCeil(aRect.XMost()) - r.x; + r.height = NSToCoordCeil(aRect.YMost()) - r.y; + return r; +} + nsRect nsTextFrame::ComputeTightBounds(DrawTarget* aDrawTarget) const { if (Style()->HasTextDecorationLines() || HasAnyStateBits(TEXT_HYPHEN_BREAK)) { // This is conservative, but OK. @@ -9905,7 +9908,7 @@ nsRect nsTextFrame::ComputeTightBounds(DrawTarget* aDrawTarget) const { } // mAscent should be the same as metrics.mAscent, but it's what we use to // paint so that's the one we'll use. - nsRect boundingBox = metrics.mBoundingBox; + nsRect boundingBox = RoundOut(metrics.mBoundingBox); boundingBox += nsPoint(0, mAscent); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. @@ -9930,8 +9933,8 @@ nsresult nsTextFrame::GetPrefWidthTightBounds(gfxContext* aContext, nscoord* aX, ComputeTransformedRange(provider), gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS, aContext->GetDrawTarget(), &provider); // Round it like nsTextFrame::ComputeTightBounds() to ensure consistency. - *aX = metrics.mBoundingBox.x; - *aXMost = metrics.mBoundingBox.XMost(); + *aX = NSToCoordFloor(metrics.mBoundingBox.x); + *aXMost = NSToCoordCeil(metrics.mBoundingBox.XMost()); return NS_OK; } @@ -10684,15 +10687,18 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, // first-letter frames should use the tight bounding box metrics for // ascent/descent for good drop-cap effects if (HasAnyStateBits(TEXT_FIRST_LETTER)) { - textMetrics.mAscent = std::max(0, -textMetrics.mBoundingBox.Y()); - textMetrics.mDescent = std::max(0, textMetrics.mBoundingBox.YMost()); + textMetrics.mAscent = + std::max(gfxFloat(0.0), -textMetrics.mBoundingBox.Y()); + textMetrics.mDescent = + std::max(gfxFloat(0.0), textMetrics.mBoundingBox.YMost()); } // Setup metrics for caller // Disallow negative widths WritingMode wm = GetWritingMode(); LogicalSize finalSize(wm); - finalSize.ISize(wm) = std::max(0, textMetrics.mAdvanceWidth); + finalSize.ISize(wm) = + NSToCoordCeilClamped(std::max(gfxFloat(0.0), textMetrics.mAdvanceWidth)); nscoord fontBaseline; // Note(dshin): Baseline should tecnhically be halfway through the em box for @@ -10703,8 +10709,8 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, finalSize.BSize(wm) = 0; fontBaseline = 0; } else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) { - fontBaseline = textMetrics.mAscent; - const auto size = fontBaseline + textMetrics.mDescent; + fontBaseline = NSToCoordCeil(textMetrics.mAscent); + const auto size = fontBaseline + NSToCoordCeil(textMetrics.mDescent); // Use actual text metrics for floating first letter frame. aMetrics.SetBlockStartAscent(wm.IsAlphabeticalBaseline() ? fontBaseline : size / 2); @@ -10718,9 +10724,10 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, wm.IsLineInverted() ? fm->MaxDescent() : fm->MaxAscent(); nscoord fontDescent = wm.IsLineInverted() ? fm->MaxAscent() : fm->MaxDescent(); - fontBaseline = std::max(textMetrics.mAscent, fontAscent); + fontBaseline = std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent); const auto size = - fontBaseline + std::max(textMetrics.mDescent, fontDescent); + fontBaseline + + std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent); aMetrics.SetBlockStartAscent(wm.IsAlphabeticalBaseline() ? fontBaseline : size / 2); finalSize.BSize(wm) = size; @@ -10816,7 +10823,7 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, mAscent = fontBaseline; // Handle text that runs outside its normal bounds. - nsRect boundingBox = textMetrics.mBoundingBox; + nsRect boundingBox = RoundOut(textMetrics.mBoundingBox); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. std::swap(boundingBox.x, boundingBox.y); @@ -11074,7 +11081,7 @@ OverflowAreas nsTextFrame::RecomputeOverflow(nsIFrame* aBlockFrame, if (GetWritingMode().IsLineInverted()) { textMetrics.mBoundingBox.y = -textMetrics.mBoundingBox.YMost(); } - nsRect boundingBox = textMetrics.mBoundingBox; + nsRect boundingBox = RoundOut(textMetrics.mBoundingBox); boundingBox += nsPoint(0, mAscent); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. diff --git a/layout/generic/nsTextFrame.h b/layout/generic/nsTextFrame.h @@ -161,7 +161,7 @@ class nsTextFrame : public nsIFrame { void InitializeForMeasure(); bool GetSpacing(Range aRange, Spacing* aSpacing) const final; - nscoord GetHyphenWidth() const final; + gfxFloat GetHyphenWidth() const final; void GetHyphenationBreaks(Range aRange, HyphenType* aBreakBefore) const final; mozilla::StyleHyphens GetHyphensOption() const final { @@ -259,10 +259,10 @@ class nsTextFrame : public nsIFrame { int32_t mLength; // space for each whitespace char - const nscoord mWordSpacing; + const gfxFloat mWordSpacing; // space for each letter - const nscoord mLetterSpacing; + const gfxFloat mLetterSpacing; // If TextAutospace exists, inter-script spacing applies. Maybe<mozilla::TextAutospace> mTextAutospace; @@ -270,8 +270,8 @@ class nsTextFrame : public nsIFrame { // min advance for <tab> char mutable gfxFloat mMinTabAdvance; - mutable nscoord mHyphenWidth; - mutable nscoord mOffsetFromBlockOriginForTabs; + mutable gfxFloat mHyphenWidth; + mutable gfxFloat mOffsetFromBlockOriginForTabs; // The values in mJustificationSpacings corresponds to unskipped // characters start from mJustificationArrayStart. @@ -937,7 +937,7 @@ class nsTextFrame : public nsIFrame { void PaintOneShadow(const PaintShadowParams& aParams, const mozilla::StyleSimpleShadow& aShadowDetails, - const gfxRect& aBoundingBox, uint32_t aBlurFlags); + gfxRect& aBoundingBox, uint32_t aBlurFlags); void PaintShadows(mozilla::Span<const mozilla::StyleSimpleShadow>, const PaintShadowParams& aParams); diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp @@ -885,11 +885,11 @@ static nsBoundingMetrics MeasureTextRun(DrawTarget* aDrawTarget, aTextRun->MeasureText(gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS, aDrawTarget); nsBoundingMetrics bm; - bm.leftBearing = metrics.mBoundingBox.X(); - bm.rightBearing = metrics.mBoundingBox.XMost(); - bm.ascent = -metrics.mBoundingBox.Y(); - bm.descent = metrics.mBoundingBox.YMost(); - bm.width = metrics.mAdvanceWidth; + bm.leftBearing = NSToCoordFloor(metrics.mBoundingBox.X()); + bm.rightBearing = NSToCoordCeil(metrics.mBoundingBox.XMost()); + bm.ascent = NSToCoordCeil(-metrics.mBoundingBox.Y()); + bm.descent = NSToCoordCeil(metrics.mBoundingBox.YMost()); + bm.width = NSToCoordRound(metrics.mAdvanceWidth); return bm; } diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp @@ -850,18 +850,19 @@ SVGBBox TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext, gfxTextRun::Metrics metrics = textRun->MeasureText( range, gfxFont::LOOSE_INK_EXTENTS, nullptr, &provider); // Make sure it includes the font-box. - nsRect fontBox(0, -metrics.mAscent, metrics.mAdvanceWidth, - metrics.mAscent + metrics.mDescent); + 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 overflow due to decorations. - nscoord baseline = metrics.mBoundingBox.y + metrics.mAscent; - nscoord x, width; + nscoord baseline = + NSToCoordRoundWithClamp(metrics.mBoundingBox.y + metrics.mAscent); + gfxFloat x, width; if (aFlags & eNoHorizontalOverflow) { - x = 0; + x = 0.0; width = textRun->GetAdvanceWidth(range, &provider); - if (width < 0) { + if (width < 0.0) { x = width; width = -width; } @@ -869,7 +870,9 @@ SVGBBox TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext, x = metrics.mBoundingBox.x; width = metrics.mBoundingBox.width; } - nsRect fillInAppUnits(x, baseline, width, metrics.mBoundingBox.height); + nsRect fillInAppUnits(NSToCoordRoundWithClamp(x), baseline, + NSToCoordRoundWithClamp(width), + NSToCoordRoundWithClamp(metrics.mBoundingBox.height)); fillInAppUnits.Inflate(inkOverflow); if (textRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. diff --git a/testing/web-platform/meta/css/css-values/ch-unit-012.html.ini b/testing/web-platform/meta/css/css-values/ch-unit-012.html.ini @@ -0,0 +1,3 @@ +[ch-unit-012.html] + expected: + if (os == "android") and swgl: FAIL diff --git a/testing/web-platform/meta/css/css-writing-modes/text-combine-upright-gen-con-001.html.ini b/testing/web-platform/meta/css/css-writing-modes/text-combine-upright-gen-con-001.html.ini @@ -2,6 +2,5 @@ fuzzy: if os == "linux": maxDifference=0-255;totalPixels=0-60 if os == "android": maxDifference=0-92;totalPixels=0-93 - if os == "win": maxDifference=0-70;totalPixels=0-67 expected: PASS diff --git a/testing/web-platform/mozilla/meta/mathml/tables/dir-6a.html.ini b/testing/web-platform/mozilla/meta/mathml/tables/dir-6a.html.ini @@ -1,4 +1,3 @@ [dir-6a.html] fuzzy: if (os == "mac"): maxDifference=0-135;totalPixels=0-56 - if (os == "win"): maxDifference=0-92;totalPixels=0-41