commit 0026ee1f90c892ec170835a64cadb03334ac158d parent 21c7a83374e1e4c22739822f2bccbcf9f7421914 Author: Narcis Beleuzu <nbeleuzu@mozilla.com> Date: Mon, 3 Nov 2025 12:22:33 +0200 Revert "Bug 1996403 - Revert changesets 08b700ae5349, 9a06ba9c63f8, and 713d9f3a5771 (bug 1994197 patches 2-4) to restore previous text-measurement behavior and performance. r=firefox-svg-reviewers,longsonr" for causing failure on 2d.text.drawing.style.letterSpacing.measure.html This reverts commit 02d6f73d213a5504af572857985064772cbd1ca9. Diffstat:
16 files changed, 200 insertions(+), 198 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.0 || mProcessor.mWordSpacing != 0.0; + return mProcessor.mLetterSpacing != 0 || mProcessor.mWordSpacing != 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!"); } - gfxFloat GetHyphenWidth() const { + nscoord GetHyphenWidth() const { MOZ_ASSERT_UNREACHABLE("no hyphenation in canvas2d text!"); - return 0.0; + return 0; } already_AddRefed<DrawTarget> GetDrawTarget() const { MOZ_ASSERT_UNREACHABLE("no hyphenation in canvas2d text!"); @@ -4736,11 +4736,13 @@ 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) { - textRunMetrics.mBoundingBox.Scale(1.0 / mAppUnitsPerDevPixel); - mBoundingBox = mBoundingBox.Union(textRunMetrics.mBoundingBox); + // The bounding box is tracked in device pixels. + gfxRect bbox = nsLayoutUtils::RectToGfxRect(textRunMetrics.mBoundingBox, + mAppUnitsPerDevPixel); + mBoundingBox = mBoundingBox.Union(bbox); } - return NSToCoordRound(textRunMetrics.mAdvanceWidth); + return textRunMetrics.mAdvanceWidth; } already_AddRefed<gfxPattern> GetGradientFor(Style aStyle) { @@ -4936,8 +4938,8 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final mozilla::gfx::PaletteCache& mPaletteCache; // spacing adjustments to be applied - gfx::Float mLetterSpacing = 0.0f; - gfx::Float mWordSpacing = 0.0f; + nscoord mLetterSpacing = 0; + nscoord mWordSpacing = 0; // to record any unsupported characters found in the text, // and notify front-end if it is interested @@ -5104,8 +5106,9 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText( if (state.letterSpacing != 0.0 || state.wordSpacing != 0.0) { processor.mLetterSpacing = - state.letterSpacing * processor.mAppUnitsPerDevPixel; - processor.mWordSpacing = state.wordSpacing * processor.mAppUnitsPerDevPixel; + NSToCoordRound(state.letterSpacing * processor.mAppUnitsPerDevPixel); + processor.mWordSpacing = + NSToCoordRound(state.wordSpacing * processor.mAppUnitsPerDevPixel); processor.mTextRunFlags |= gfx::ShapedTextFlags::TEXT_ENABLE_SPACING; if (state.letterSpacing != 0.0) { processor.mTextRunFlags |= @@ -5232,7 +5235,7 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText( // based on the text position and advance. if (!doCalculateBounds) { processor.mBoundingBox.width = totalWidth; - processor.mBoundingBox.MoveBy(gfxPoint(processor.mPt.x, processor.mPt.y)); + processor.mBoundingBox.MoveBy(processor.mPt.x, processor.mPt.y); } processor.mPt.x *= processor.mAppUnitsPerDevPixel; @@ -5285,7 +5288,8 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText( if (aOp == CanvasRenderingContext2D::TextDrawOperation::FILL && !doCalculateBounds) { - RedrawUser(boundingBox); + RedrawUser(gfxRect(boundingBox.x, boundingBox.y, boundingBox.width, + boundingBox.height)); } 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; } - gfxFloat GetHyphenWidth() const override { + nscoord GetHyphenWidth() const override { NS_ERROR("This shouldn't be called because we never enable hyphens"); return 0; } @@ -312,8 +312,7 @@ nscoord nsFontMetrics::GetWidth(const char* aString, uint32_t aLength, StubPropertyProvider provider; AutoTextRun textRun(this, aDrawTarget, aString, aLength); if (textRun.get()) { - return NSToCoordRound( - textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider)); + return textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider); } return 0; } @@ -329,8 +328,7 @@ nscoord nsFontMetrics::GetWidth(const char16_t* aString, uint32_t aLength, StubPropertyProvider provider; AutoTextRun textRun(this, aDrawTarget, aString, aLength); if (textRun.get()) { - return NSToCoordRound( - textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider)); + return textRun->GetAdvanceWidth(gfxTextRun::Range(0, aLength), &provider); } return 0; } @@ -401,11 +399,11 @@ static nsBoundingMetrics GetTextBoundingMetrics( gfxTextRun::Metrics theMetrics = textRun->MeasureText( gfxTextRun::Range(0, aLength), aType, aDrawTarget, &provider); - 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); + m.leftBearing = theMetrics.mBoundingBox.X(); + m.rightBearing = theMetrics.mBoundingBox.XMost(); + m.ascent = -theMetrics.mBoundingBox.Y(); + m.descent = theMetrics.mBoundingBox.YMost(); + m.width = theMetrics.mAdvanceWidth; } return m; } diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp @@ -31,6 +31,7 @@ #include "gfxUserFontSet.h" #include "nsCRT.h" #include "nsContentUtils.h" +#include "nsLayoutUtils.h" #include "nsSpecialCasingData.h" #include "nsTextRunTransformations.h" #include "nsUGenCategory.h" @@ -961,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 + gfxPoint(aOther.mAdvanceWidth, 0)) + mBoundingBox = (mBoundingBox + nsPoint(aOther.mAdvanceWidth, 0)) .Union(aOther.mBoundingBox); } else { mBoundingBox = - mBoundingBox.Union(aOther.mBoundingBox + gfxPoint(mAdvanceWidth, 0)); + mBoundingBox.Union(aOther.mBoundingBox + nsPoint(mAdvanceWidth, 0)); } - mAdvanceWidth += aOther.mAdvanceWidth; + mAdvanceWidth = NSCoordSaturatingAdd(mAdvanceWidth, aOther.mAdvanceWidth); } gfxFont::gfxFont(const RefPtr<UnscaledFont>& aUnscaledFont, @@ -2873,7 +2874,7 @@ bool gfxFont::HasColorGlyphFor(uint32_t aCh, uint32_t aNextCh) { return false; } -static void UnionRange(gfxFloat aX, gfxFloat* aDestMin, gfxFloat* aDestMax) { +static void UnionRange(nscoord aX, nscoord* aDestMin, nscoord* aDestMax) { *aDestMin = std::min(*aDestMin, aX); *aDestMax = std::max(*aDestMax, aX); } @@ -2894,7 +2895,7 @@ bool gfxFont::IsSpaceGlyphInvisible(DrawTarget* aRefDrawTarget, GetAdjustedSize() >= 1.0) { gfxGlyphExtents* extents = GetOrCreateGlyphExtents(aTextRun->GetAppUnitsPerDevUnit()); - gfxRect glyphExtents; + nsRect glyphExtents; flag = extents->GetTightGlyphExtentsAppUnits( this, aRefDrawTarget, GetSpaceGlyph(), &glyphExtents) && glyphExtents.IsEmpty() @@ -2910,7 +2911,7 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, DrawTarget* aRefDrawTarget, Spacing* aSpacing, gfxGlyphExtents* aExtents, bool aIsRTL, bool aNeedsGlyphExtents, RunMetrics& aMetrics, - gfxFloat* aAdvanceMin, gfxFloat* aAdvanceMax) { + nscoord* aAdvanceMin, nscoord* aAdvanceMax) { const gfxTextRun::CompressedGlyph* charGlyphs = aTextRun->GetCharacterGlyphs(); uint32_t spaceGlyph = GetSpaceGlyph(); @@ -2934,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) { - gfxRect glyphExtents; + nsRect glyphExtents; flag = aExtents->GetTightGlyphExtentsAppUnitsLocked( this, aRefDrawTarget, spaceGlyph, &glyphExtents) && glyphExtents.IsEmpty() @@ -2957,11 +2958,11 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart, UnionRange(x, aAdvanceMin, aAdvanceMax); UnionRange(x + extentsWidth, aAdvanceMin, aAdvanceMax); } else { - gfxRect glyphRect; + nsRect glyphRect; if (!aExtents->GetTightGlyphExtentsAppUnitsLocked( this, aRefDrawTarget, glyphIndex, &glyphRect)) { - glyphRect = gfxRect(0, aMetrics.mBoundingBox.Y(), advance, - aMetrics.mBoundingBox.Height()); + glyphRect = nsRect(0, aMetrics.mBoundingBox.Y(), advance, + aMetrics.mBoundingBox.Height()); } if (aIsRTL) { // In effect, swap left and right sidebearings of the glyph, for @@ -2984,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; - double advance = details->mAdvance; - gfxRect glyphRect; + nscoord advance = details->mAdvance; + nsRect glyphRect; if (glyphData->IsMissing() || !aExtents->GetTightGlyphExtentsAppUnitsLocked( this, aRefDrawTarget, glyphIndex, &glyphRect)) { // We might have failed to get glyph extents due to // OOM or something - glyphRect = gfxRect(0, -aMetrics.mAscent, advance, - aMetrics.mAscent + aMetrics.mDescent); + glyphRect = nsRect(0, -aMetrics.mAscent, advance, + aMetrics.mAscent + aMetrics.mDescent); } if (aIsRTL) { // Swap left/right sidebearings of the glyph, because we're doing @@ -3053,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) { - double advance = details->mAdvance; - gfxRect glyphRect(0, -aMetrics.mAscent, advance, - aMetrics.mAscent + aMetrics.mDescent); + nscoord advance = details->mAdvance; + nsRect glyphRect(0, -aMetrics.mAscent, advance, + aMetrics.mAscent + aMetrics.mDescent); if (aIsRTL) { // Swap left/right sidebearings of the glyph, because we're doing // mirrored measurement. @@ -3123,7 +3124,7 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun, : nsFontMetrics::eHorizontal; const gfxFont::Metrics& fontMetrics = GetMetrics(orientation); - gfxFloat baselineOffset = 0; + nscoord baselineOffset = 0; if (aTextRun->UseCenterBaseline() && orientation == nsFontMetrics::eHorizontal) { // For a horizontal font being used in vertical writing mode with @@ -3135,23 +3136,25 @@ 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 = - appUnitsPerDevUnit * (fontMetrics.emAscent - fontMetrics.emDescent) / 2; + NSToCoordRound(appUnitsPerDevUnit * + (fontMetrics.emAscent - fontMetrics.emDescent) / 2.0); } RunMetrics metrics; - metrics.mAscent = fontMetrics.maxAscent * appUnitsPerDevUnit; - metrics.mDescent = fontMetrics.maxDescent * appUnitsPerDevUnit; + metrics.mAscent = NSToCoordRound(fontMetrics.maxAscent * appUnitsPerDevUnit); + metrics.mDescent = + NSToCoordRound(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 = - gfxRect(0, -metrics.mAscent, 0, metrics.mAscent + metrics.mDescent); + nsRect(0, -metrics.mAscent, 0, metrics.mAscent + metrics.mDescent); return metrics; } - gfxFloat advanceMin = 0, advanceMax = 0; + nscoord advanceMin = 0, advanceMax = 0; bool isRTL = aTextRun->IsRightToLeft(); bool needsGlyphExtents = NeedsGlyphExtents(this, aTextRun); gfxGlyphExtents* extents = @@ -3176,8 +3179,8 @@ gfxFont::RunMetrics gfxFont::Measure(const gfxTextRun* aTextRun, metrics.mBoundingBox.SetEmpty(); } else if (aBoundingBoxType == LOOSE_INK_EXTENTS) { UnionRange(metrics.mAdvanceWidth, &advanceMin, &advanceMax); - gfxRect fontBox(advanceMin, -metrics.mAscent, advanceMax - advanceMin, - metrics.mAscent + metrics.mDescent); + nsRect fontBox(advanceMin, -metrics.mAscent, advanceMax - advanceMin, + metrics.mAscent + metrics.mDescent); metrics.mBoundingBox = metrics.mBoundingBox.Union(fontBox); } @@ -3208,9 +3211,10 @@ 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() + - extendLeftEdge + extendRightEdge); - metrics.mBoundingBox.MoveByX(-extendLeftEdge); + metrics.mBoundingBox.SetWidth( + metrics.mBoundingBox.Width() + + NSToCoordRound(extendLeftEdge + extendRightEdge)); + metrics.mBoundingBox.MoveByX(NSToCoordRound(-extendLeftEdge)); } if (baselineOffset != 0) { @@ -4110,16 +4114,27 @@ 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)) { - gfxFloat d2a = aExtents->GetAppUnitsPerDevUnit(); - aExtents->SetTightGlyphExtents( - aGlyphID, gfxRect(svgBounds.X() * d2a, svgBounds.Y() * d2a, - svgBounds.Width() * d2a, svgBounds.Height() * d2a)); + aExtents->SetTightGlyphExtents(aGlyphID, + ToAppRect(svgBounds, appUnitsPerDevUnit)); return; } @@ -4132,10 +4147,8 @@ void gfxFont::SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID, mFontEntry->mCOLR, shaper->GetHBFont(), aGlyphID, aDrawTarget, scaledFont, mFUnitsConvFactor); if (!r.IsEmpty()) { - gfxFloat d2a = aExtents->GetAppUnitsPerDevUnit(); - aExtents->SetTightGlyphExtents( - aGlyphID, gfxRect(r.X() * d2a, r.Y() * d2a, r.Width() * d2a, - r.Height() * d2a)); + aExtents->SetTightGlyphExtents(aGlyphID, + ToAppRect(r, appUnitsPerDevUnit)); return; } } @@ -4145,7 +4158,6 @@ 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 = @@ -4162,10 +4174,8 @@ void gfxFont::SetupGlyphExtents(DrawTarget* aDrawTarget, uint32_t aGlyphID, } #endif - gfxFloat d2a = appUnitsPerDevUnit; - aExtents->SetTightGlyphExtents( - aGlyphID, gfxRect(bounds.x * d2a, bounds.y * d2a, bounds.width * d2a, - bounds.height * d2a)); + aExtents->SetTightGlyphExtents(aGlyphID, + ToAppRect(bounds, appUnitsPerDevUnit)); } // Try to initialize font metrics by reading sfnt tables directly; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h @@ -1657,23 +1657,22 @@ class gfxFont { nscoord mBefore; nscoord mAfter; }; + /** - * Metrics for a particular string + * Metrics for a particular string. These are in appUnits. */ 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) - gfxFloat mAdvanceWidth; + nscoord mAdvanceWidth = 0; // For zero-width substrings, these must be zero! - gfxFloat mAscent; // always non-negative - gfxFloat mDescent; // always non-negative + nscoord mAscent = 0; // always non-negative + nscoord mDescent = 0; // always non-negative // Bounding box that is guaranteed to include everything drawn. // If a tight boundingBox was requested when these metrics were @@ -1681,7 +1680,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 - gfxRect mBoundingBox; + nsRect mBoundingBox; }; /** @@ -1957,7 +1956,7 @@ class gfxFont { DrawTarget* aRefDrawTarget, Spacing* aSpacing, gfxGlyphExtents* aExtents, bool aIsRTL, bool aNeedsGlyphExtents, RunMetrics& aMetrics, - gfxFloat* aAdvanceMin, gfxFloat* aAdvanceMax); + nscoord* aAdvanceMin, nscoord* 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, - gfxRect* aExtents) { + nsRect* 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 = gfxRect(entry->x, entry->y, entry->width, entry->height); + *aExtents = nsRect(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 gfxRect& aExtentsAppUnits) { + const nsRect& 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, gfxRect* aExtents) + uint32_t aGlyphID, nsRect* aExtents) MOZ_REQUIRES_SHARED(mLock); bool GetTightGlyphExtentsAppUnits(gfxFont* aFont, DrawTarget* aDrawTarget, - uint32_t aGlyphID, gfxRect* aExtents) { + uint32_t aGlyphID, nsRect* 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 gfxRect& aExtentsAppUnits); + void SetTightGlyphExtents(uint32_t aGlyphID, const nsRect& 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.0), y(0.0), width(0.0), height(0.0) {} + : nsUint32HashKey(aPtr), x(0), y(0), width(0), height(0) {} HashEntry(HashEntry&& aOther) : nsUint32HashKey(std::move(aOther)), x(aOther.x), @@ -111,7 +111,7 @@ class gfxGlyphExtents { width(aOther.width), height(aOther.height) {} - float x, y, width, height; + nscoord x, y, width, height; }; enum { diff --git a/gfx/thebes/gfxTextRun.cpp b/gfx/thebes/gfxTextRun.cpp @@ -281,7 +281,7 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( } result.mRange.end = i; - int32_t ligatureWidth = GetAdvanceForGlyphs(result.mRange); + nscoord ligatureWidth = GetAdvanceForGlyphs(result.mRange); // Count the number of started clusters we have seen uint32_t totalClusterCount = 0; uint32_t partClusterIndex = 0; @@ -307,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) { - gfxFloat allParts = totalClusterCount * (ligatureWidth / totalClusterCount); + nscoord allParts = totalClusterCount * (ligatureWidth / totalClusterCount); result.mPartWidth += ligatureWidth - allParts; } @@ -331,13 +331,15 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( if (aPartRange.start == result.mRange.start) { if (aProvider->GetSpacing(Range(aPartRange.start, aPartRange.start + 1), &spacing)) { - result.mPartWidth += spacing.mBefore; + result.mPartWidth = + NSCoordSaturatingAdd(result.mPartWidth, spacing.mBefore); } } if (aPartRange.end == result.mRange.end) { if (aProvider->GetSpacing(Range(aPartRange.end - 1, aPartRange.end), &spacing)) { - result.mPartWidth += spacing.mAfter; + result.mPartWidth = + NSCoordSaturatingAdd(result.mPartWidth, spacing.mAfter); } } } @@ -345,17 +347,19 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData( return result; } -gfxFloat gfxTextRun::ComputePartialLigatureWidth( +nscoord 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; } -int32_t gfxTextRun::GetAdvanceForGlyphs(Range aRange) const { - int32_t advance = 0; +nscoord gfxTextRun::GetAdvanceForGlyphs(Range aRange) const { + nscoord advance = 0; for (auto i = aRange.start; i < aRange.end; ++i) { - advance += GetAdvanceForGlyph(i); + advance = NSCoordSaturatingAdd(advance, GetAdvanceForGlyph(i)); } return advance; } @@ -548,12 +552,11 @@ struct MOZ_STACK_CLASS BufferAlphaColor { ~BufferAlphaColor() = default; - void PushSolidColor(const gfxRect& aBounds, const DeviceColor& aAlphaColor, + void PushSolidColor(const nsRect& aBounds, const DeviceColor& aAlphaColor, uint32_t appsPerDevUnit) { mContext->Save(); - mContext->SnappedClip(gfxRect( - aBounds.X() / appsPerDevUnit, aBounds.Y() / appsPerDevUnit, - aBounds.Width() / appsPerDevUnit, aBounds.Height() / appsPerDevUnit)); + mContext->SnappedClip( + nsLayoutUtils::RectToGfxRect(aBounds, appsPerDevUnit)); mContext->SetDeviceColor( DeviceColor(aAlphaColor.r, aAlphaColor.g, aAlphaColor.b)); mContext->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, aAlphaColor.a); @@ -672,9 +675,9 @@ void gfxTextRun::Draw(const Range aRange, const gfx::Point aPt, aParams.provider); if (IsRightToLeft()) { metrics.mBoundingBox.MoveBy( - gfxPoint(aPt.x - metrics.mAdvanceWidth, aPt.y)); + nsPoint(aPt.x - metrics.mAdvanceWidth, aPt.y)); } else { - metrics.mBoundingBox.MoveBy(gfxPoint(aPt.x, aPt.y)); + metrics.mBoundingBox.MoveBy(nsPoint(aPt.x, aPt.y)); } gotMetrics = true; } @@ -975,19 +978,19 @@ uint32_t gfxTextRun::BreakAndMeasureText( } } - gfxFloat width = 0; - gfxFloat advance = 0; + nscoord width = 0; + nscoord 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 - gfxFloat trimmableAdvance = 0; + nscoord trimmableAdvance = 0; int32_t lastBreak = -1; int32_t lastBreakTrimmableChars = -1; - gfxFloat lastBreakTrimmableAdvance = -1; + nscoord lastBreakTrimmableAdvance = -1; // Cache the last candidate break int32_t lastCandidateBreak = -1; int32_t lastCandidateBreakTrimmableChars = -1; - gfxFloat lastCandidateBreakTrimmableAdvance = -1; + nscoord lastCandidateBreakTrimmableAdvance = -1; bool lastCandidateBreakUsedHyphenation = false; gfxBreakPriority lastCandidateBreakPriority = gfxBreakPriority::eNoBreak; bool aborted = false; @@ -1099,7 +1102,7 @@ uint32_t gfxTextRun::BreakAndMeasureText( : gfxBreakPriority::eWordWrapBreak; } - width += advance; + width = NSCoordSaturatingAdd(width, advance); advance = 0; if (width - trimmableAdvance > aWidth) { // No more text fits. Abort @@ -1135,23 +1138,24 @@ uint32_t gfxTextRun::BreakAndMeasureText( continue; } - gfxFloat charAdvance; + nscoord charAdvance; if (i >= ligatureRange.start && i < ligatureRange.end) { charAdvance = GetAdvanceForGlyphs(Range(i, i + 1)); if (haveSpacing) { PropertyProvider::Spacing* space = &spacingBuffer[i - bufferRange.start]; - charAdvance += space->mBefore + space->mAfter; + charAdvance = + NSCoordSaturatingAdd(charAdvance, space->mBefore + space->mAfter); } } else { charAdvance = ComputePartialLigatureWidth(Range(i, i + 1), &aProvider); } - advance += charAdvance; + advance = NSCoordSaturatingAdd(advance, charAdvance); if (aOutTrimmableWhitespace) { if (mCharacterGlyphs[i].CharIsSpace()) { ++trimmableChars; - trimmableAdvance += charAdvance; + trimmableAdvance = NSCoordSaturatingAdd(trimmableAdvance, charAdvance); } else { trimmableAdvance = 0; trimmableChars = 0; @@ -1160,7 +1164,7 @@ uint32_t gfxTextRun::BreakAndMeasureText( } if (!aborted) { - width += advance; + width = NSCoordSaturatingAdd(width, advance); } // There are three possibilities: @@ -1210,20 +1214,20 @@ uint32_t gfxTextRun::BreakAndMeasureText( return charsFit; } -gfxFloat gfxTextRun::GetAdvanceWidth( - Range aRange, const PropertyProvider* aProvider, - PropertyProvider::Spacing* aSpacing) const { +nscoord 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); - gfxFloat result = + nscoord 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; @@ -1239,7 +1243,7 @@ gfxFloat gfxTextRun::GetAdvanceWidth( spacingBuffer.Elements())) { for (i = 0; i < ligatureRange.Length(); ++i) { PropertyProvider::Spacing* space = &spacingBuffer[i]; - result += space->mBefore + space->mAfter; + result = NSCoordSaturatingAdd(result, space->mBefore + space->mAfter); } if (aSpacing) { aSpacing->mBefore = spacingBuffer[0].mBefore; @@ -1249,33 +1253,34 @@ gfxFloat gfxTextRun::GetAdvanceWidth( } } - return result + GetAdvanceForGlyphs(ligatureRange); + return NSCoordSaturatingAdd(result, GetAdvanceForGlyphs(ligatureRange)); } -gfxFloat gfxTextRun::GetMinAdvanceWidth(Range aRange) { +nscoord gfxTextRun::GetMinAdvanceWidth(Range aRange) { MOZ_ASSERT(aRange.end <= GetLength(), "Substring out of range"); Range ligatureRange = aRange; bool adjusted = ShrinkToLigatureBoundaries(&ligatureRange); - gfxFloat result = + nscoord 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. - gfxFloat clusterAdvance = 0; + nscoord 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 += GetAdvanceForGlyph(i); + clusterAdvance = + NSCoordSaturatingAdd(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 gfxFloat GetHyphenWidth() const = 0; + virtual nscoord 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. */ - gfxFloat GetAdvanceWidth(Range aRange, const PropertyProvider* aProvider, - PropertyProvider::Spacing* aSpacing = nullptr) const; + nscoord GetAdvanceWidth(Range aRange, const PropertyProvider* aProvider, + PropertyProvider::Spacing* aSpacing = nullptr) const; - gfxFloat GetAdvanceWidth() const { + nscoord 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. */ - gfxFloat GetMinAdvanceWidth(Range aRange); + nscoord 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 - gfxFloat mPartAdvance; + nscoord 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 - gfxFloat mPartWidth; + nscoord mPartWidth; bool mClipBeforePart; bool mClipAfterPart; @@ -822,7 +822,7 @@ class gfxTextRun : public gfxShapedText { // **** general helpers **** // Get the total advance for a range of glyphs. - int32_t GetAdvanceForGlyphs(Range aRange) const; + nscoord 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; - gfxFloat ComputePartialLigatureWidth(Range aPartRange, - const PropertyProvider* aProvider) const; + nscoord ComputePartialLigatureWidth(Range aPartRange, + const PropertyProvider* aProvider) const; void DrawPartialLigature(gfxFont* aFont, Range aRange, mozilla::gfx::Point* aPt, const PropertyProvider* aProvider, @@ -856,9 +856,6 @@ 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 @@ -271,11 +271,11 @@ TextAutospace::BoundarySet TextAutospace::InitBoundarySet( } // namespace mozilla struct TabWidth { - TabWidth(uint32_t aOffset, uint32_t aWidth) - : mOffset(aOffset), mWidth(float(aWidth)) {} + TabWidth(uint32_t aOffset, nscoord aWidth) + : mOffset(aOffset), mWidth(aWidth) {} uint32_t mOffset; // DOM offset relative to the current frame's offset. - float mWidth; // extra space to be added at this position (in app units) + nscoord mWidth; // extra space to be added at this position (in app units) }; struct nsTextFrame::TabWidthStore { @@ -3463,7 +3463,7 @@ nsTextFrame::PropertyProvider::PropertyProvider( mLength(aLength), mWordSpacing(WordSpacing(aFrame, *aTextStyle)), mLetterSpacing(LetterSpacing(aFrame, *aTextStyle)), - mMinTabAdvance(-1.0), + mMinTabAdvance(-1), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(aOffsetFromBlockOriginForTabs), mJustificationArrayStart(0), @@ -3493,7 +3493,7 @@ nsTextFrame::PropertyProvider::PropertyProvider( mLength(aFrame->GetContentLength()), mWordSpacing(WordSpacing(aFrame, *mTextStyle)), mLetterSpacing(LetterSpacing(aFrame, *mTextStyle)), - mMinTabAdvance(-1.0), + mMinTabAdvance(-1), mHyphenWidth(-1), mOffsetFromBlockOriginForTabs(0), mJustificationArrayStart(0), @@ -3513,7 +3513,7 @@ already_AddRefed<DrawTarget> nsTextFrame::PropertyProvider::GetDrawTarget() } gfxFloat nsTextFrame::PropertyProvider::MinTabAdvance() const { - if (mMinTabAdvance < 0.0) { + if (mMinTabAdvance < 0) { mMinTabAdvance = GetMinTabAdvanceAppUnits(mTextRun); } return mMinTabAdvance; @@ -3862,7 +3862,7 @@ static gfxFloat ComputeTabWidthAppUnits(const nsIFrame* aFrame) { MOZ_ASSERT(tabSize.IsNumber()); gfxFloat spaces = tabSize.number._0; - MOZ_ASSERT(spaces >= 0); + MOZ_ASSERT(spaces >= 0.0); const nsIFrame* cb = aFrame->GetContainingBlock(0, aFrame->StyleDisplay()); const auto* styleText = cb->StyleText(); @@ -4265,12 +4265,13 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange, } // aX and the result are in whole appunits. -static gfxFloat AdvanceToNextTab(gfxFloat aX, gfxFloat aTabWidth, - gfxFloat aMinAdvance) { +static nscoord AdvanceToNextTab(nscoord 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 aTabWidth > 0.0 ? ceil(nextPos / aTabWidth) * aTabWidth : nextPos; + return NSToCoordRound(aTabWidth > 0 ? ceil(nextPos / aTabWidth) * aTabWidth + : nextPos); } void nsTextFrame::PropertyProvider::CalcTabWidths(Range aRange, @@ -4331,11 +4332,10 @@ void nsTextFrame::PropertyProvider::CalcTabWidths(Range aRange, mTabWidths = new TabWidthStore(mFrame->GetContentOffset()); mFrame->SetProperty(TabWidthProperty(), mTabWidths); } - double nextTab = AdvanceToNextTab(mOffsetFromBlockOriginForTabs, - aTabWidth, MinTabAdvance()); + nscoord nextTab = AdvanceToNextTab(mOffsetFromBlockOriginForTabs, + aTabWidth, MinTabAdvance()); mTabWidths->mWidths.AppendElement( - TabWidth(i - startOffset, - NSToIntRound(nextTab - mOffsetFromBlockOriginForTabs))); + TabWidth(i - startOffset, nextTab - mOffsetFromBlockOriginForTabs)); mOffsetFromBlockOriginForTabs = nextTab; } @@ -4355,7 +4355,7 @@ void nsTextFrame::PropertyProvider::CalcTabWidths(Range aRange, } } -gfxFloat nsTextFrame::PropertyProvider::GetHyphenWidth() const { +nscoord nsTextFrame::PropertyProvider::GetHyphenWidth() const { if (mHyphenWidth < 0) { const auto& hyphenateChar = mTextStyle->mHyphenateCharacter; if (hyphenateChar.IsAuto()) { @@ -6723,7 +6723,8 @@ static void AddHyphenToMetrics(nsTextFrame* aTextFrame, bool aIsRightToLeft, void nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams, const StyleSimpleShadow& aShadowDetails, - gfxRect& aBoundingBox, uint32_t aBlurFlags) { + const gfxRect& aBoundingBox, + uint32_t aBlurFlags) { AUTO_PROFILER_LABEL("nsTextFrame::PaintOneShadow", GRAPHICS); nsPoint shadowOffset(aShadowDetails.horizontal.ToAppUnits(), @@ -7529,8 +7530,8 @@ void nsTextFrame::PaintShadows(Span<const StyleSimpleShadow> aShadows, aParams.context->GetDrawTarget()); } // Add bounds of text decorations - gfxRect decorationRect(0, -shadowMetrics.mAscent, shadowMetrics.mAdvanceWidth, - shadowMetrics.mAscent + shadowMetrics.mDescent); + nsRect decorationRect(0, -shadowMetrics.mAscent, shadowMetrics.mAdvanceWidth, + shadowMetrics.mAscent + shadowMetrics.mDescent); shadowMetrics.mBoundingBox.UnionRect(shadowMetrics.mBoundingBox, decorationRect); @@ -7554,7 +7555,12 @@ void nsTextFrame::PaintShadows(Span<const StyleSimpleShadow> aShadows, } for (const auto& shadow : Reversed(aShadows)) { - PaintOneShadow(aParams, shadow, shadowMetrics.mBoundingBox, blurFlags); + PaintOneShadow( + aParams, shadow, + gfxRect(shadowMetrics.mBoundingBox.x, shadowMetrics.mBoundingBox.y, + shadowMetrics.mBoundingBox.width, + shadowMetrics.mBoundingBox.height), + blurFlags); } } @@ -9726,7 +9732,7 @@ void nsTextFrame::AddInlineMinISizeForFlow(gfxContext* aRenderingContext, aData->ForceBreak(); } else if (i < flowEndInTextRun && hyphenating && gfxTextRun::IsOptionalHyphenBreak(hyphBuffer[i - start])) { - aData->OptionallyBreak(NSToCoordRound(provider.GetHyphenWidth())); + aData->OptionallyBreak(provider.GetHyphenWidth()); } else { aData->OptionallyBreak(); } @@ -10053,15 +10059,6 @@ 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. @@ -10087,7 +10084,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 = RoundOut(metrics.mBoundingBox); + nsRect boundingBox = metrics.mBoundingBox; boundingBox += nsPoint(0, mAscent); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. @@ -10112,8 +10109,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 = NSToCoordFloor(metrics.mBoundingBox.x); - *aXMost = NSToCoordCeil(metrics.mBoundingBox.XMost()); + *aX = metrics.mBoundingBox.x; + *aXMost = metrics.mBoundingBox.XMost(); return NS_OK; } @@ -10866,18 +10863,15 @@ 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(gfxFloat(0.0), -textMetrics.mBoundingBox.Y()); - textMetrics.mDescent = - std::max(gfxFloat(0.0), textMetrics.mBoundingBox.YMost()); + textMetrics.mAscent = std::max(0, -textMetrics.mBoundingBox.Y()); + textMetrics.mDescent = std::max(0, textMetrics.mBoundingBox.YMost()); } // Setup metrics for caller // Disallow negative widths WritingMode wm = GetWritingMode(); LogicalSize finalSize(wm); - finalSize.ISize(wm) = - NSToCoordCeilClamped(std::max(gfxFloat(0.0), textMetrics.mAdvanceWidth)); + finalSize.ISize(wm) = std::max(0, textMetrics.mAdvanceWidth); nscoord fontBaseline; // Note(dshin): Baseline should tecnhically be halfway through the em box for @@ -10888,8 +10882,8 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, finalSize.BSize(wm) = 0; fontBaseline = 0; } else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) { - fontBaseline = NSToCoordCeil(textMetrics.mAscent); - const auto size = fontBaseline + NSToCoordCeil(textMetrics.mDescent); + fontBaseline = textMetrics.mAscent; + const auto size = fontBaseline + textMetrics.mDescent; // Use actual text metrics for floating first letter frame. aMetrics.SetBlockStartAscent(wm.IsAlphabeticalBaseline() ? fontBaseline : size / 2); @@ -10903,10 +10897,9 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, wm.IsLineInverted() ? fm->MaxDescent() : fm->MaxAscent(); nscoord fontDescent = wm.IsLineInverted() ? fm->MaxAscent() : fm->MaxDescent(); - fontBaseline = std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent); + fontBaseline = std::max(textMetrics.mAscent, fontAscent); const auto size = - fontBaseline + - std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent); + fontBaseline + std::max(textMetrics.mDescent, fontDescent); aMetrics.SetBlockStartAscent(wm.IsAlphabeticalBaseline() ? fontBaseline : size / 2); finalSize.BSize(wm) = size; @@ -11002,7 +10995,7 @@ void nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, mAscent = fontBaseline; // Handle text that runs outside its normal bounds. - nsRect boundingBox = RoundOut(textMetrics.mBoundingBox); + nsRect boundingBox = textMetrics.mBoundingBox; if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. std::swap(boundingBox.x, boundingBox.y); @@ -11260,7 +11253,7 @@ OverflowAreas nsTextFrame::RecomputeOverflow(nsIFrame* aBlockFrame, if (GetWritingMode().IsLineInverted()) { textMetrics.mBoundingBox.y = -textMetrics.mBoundingBox.YMost(); } - nsRect boundingBox = RoundOut(textMetrics.mBoundingBox); + nsRect boundingBox = 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; - gfxFloat GetHyphenWidth() const final; + nscoord GetHyphenWidth() const final; void GetHyphenationBreaks(Range aRange, HyphenType* aBreakBefore) const final; mozilla::StyleHyphens GetHyphensOption() const final { @@ -270,8 +270,8 @@ class nsTextFrame : public nsIFrame { // min advance for <tab> char mutable gfxFloat mMinTabAdvance; - mutable gfxFloat mHyphenWidth; - mutable gfxFloat mOffsetFromBlockOriginForTabs; + mutable nscoord mHyphenWidth; + mutable nscoord 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, - gfxRect& aBoundingBox, uint32_t aBlurFlags); + const 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 @@ -884,11 +884,11 @@ static nsBoundingMetrics MeasureTextRun(DrawTarget* aDrawTarget, aTextRun->MeasureText(gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS, aDrawTarget); nsBoundingMetrics bm; - 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); + bm.leftBearing = metrics.mBoundingBox.X(); + bm.rightBearing = metrics.mBoundingBox.XMost(); + bm.ascent = -metrics.mBoundingBox.Y(); + bm.descent = metrics.mBoundingBox.YMost(); + bm.width = metrics.mAdvanceWidth; return bm; } diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list @@ -2121,7 +2121,7 @@ skip-if(Android) test-pref(ui.textScaleFactor,50) test-pref(browser.display.os-z pref(widget.disable-dark-scrollbar,false) == 1777135.html 1777135-ref.html test-pref(widget.non-native-theme.use-theme-accent,false) == 1778834.html 1778834-ref.html # do not adjust the fuzz without looking, this test was written as fuzzy on purpose (because that was the only way to make a test work) -fuzzy(16-68,26939-44426) == 1780191-1.svg 1780191-1-ref.svg +fuzzy(16-47,26939-44425) == 1780191-1.svg 1780191-1-ref.svg pref(layout.css.prefers-color-scheme.content-override,0) == 1787127.html 1787127-ref.html pref(layout.css.prefers-color-scheme.content-override,1) == 1787127.html 1787127-ref.html pref(layout.css.prefers-color-scheme.content-override,2) == 1787127.html 1787127-ref.html diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp @@ -838,19 +838,18 @@ SVGBBox TextRenderedRun::GetRunUserSpaceRect(uint32_t aFlags) const { gfxTextRun::Metrics metrics = textRun->MeasureText( range, gfxFont::LOOSE_INK_EXTENTS, nullptr, &provider); // Make sure it includes the font-box. - gfxRect fontBox(0, -metrics.mAscent, metrics.mAdvanceWidth, - metrics.mAscent + metrics.mDescent); + nsRect 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 = - NSToCoordRoundWithClamp(metrics.mBoundingBox.y + metrics.mAscent); - gfxFloat x, width; + nscoord baseline = metrics.mBoundingBox.y + metrics.mAscent; + nscoord x, width; if (aFlags & eNoHorizontalOverflow) { - x = 0.0; + x = 0; width = textRun->GetAdvanceWidth(range, &provider); - if (width < 0.0) { + if (width < 0) { x = width; width = -width; } @@ -858,9 +857,7 @@ SVGBBox TextRenderedRun::GetRunUserSpaceRect(uint32_t aFlags) const { x = metrics.mBoundingBox.x; width = metrics.mBoundingBox.width; } - nsRect fillInAppUnits(NSToCoordRoundWithClamp(x), baseline, - NSToCoordRoundWithClamp(width), - NSToCoordRoundWithClamp(metrics.mBoundingBox.height)); + nsRect fillInAppUnits(x, baseline, width, 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 @@ -1,3 +0,0 @@ -[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,5 +2,6 @@ fuzzy: if os == "linux": maxDifference=0-255;totalPixels=0-60 if os == "android": maxDifference=0-92;totalPixels=0-93 + if os == "win": maxDifference=0-72;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,3 +1,4 @@ [dir-6a.html] fuzzy: if (os == "mac"): maxDifference=0-135;totalPixels=0-56 + if (os == "win"): maxDifference=0-92;totalPixels=0-41