commit afa632d8ef0c12f07ee3b36574e53f505ce256fe
parent f66df20fb0b399ca2b4b5e194f2cc62cdba4b9b6
Author: Serban Stanca <sstanca@mozilla.com>
Date: Thu, 16 Oct 2025 05:46:12 +0300
Revert "Bug 1994197, Bug 1994193 - patch 3 - Also use integer nscoords for textrun ascent/descent metrics and bounding box. r=firefox-svg-reviewers,longsonr" for causing assertion failures in nsTextFrame.cpp.
This reverts commit eb7cdb05c4bcd0835692824bbf9741f6857e668d.
This reverts commit d1e97328cdef956eb5ef2cbd74754655d51acfee.
This reverts commit f0290e617fba4d07670494febc4db4349196e5b5.
This reverts commit f4ed96250592feb6e435f09305a3f067c6442d61.
Diffstat:
14 files changed, 199 insertions(+), 224 deletions(-)
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -4635,7 +4635,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
explicit PropertyProvider(const CanvasBidiProcessor& aProcessor)
: mProcessor(aProcessor) {}
- bool GetSpacing(gfxTextRun::Range aRange,
+ void GetSpacing(gfxTextRun::Range aRange,
gfxFont::Spacing* aSpacing) const {
for (auto i = aRange.start; i < aRange.end; ++i) {
auto* charGlyphs = mProcessor.mTextRun->GetCharacterGlyphs();
@@ -4665,7 +4665,6 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
}
aSpacing++;
}
- return mProcessor.mLetterSpacing != 0 || mProcessor.mWordSpacing != 0;
}
mozilla::StyleHyphens GetHyphensOption() const {
@@ -4677,9 +4676,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 +4735,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 +4935,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 +5103,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 +5231,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 +5284,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;
}
@@ -101,9 +101,8 @@ class StubPropertyProvider final : public gfxTextRun::PropertyProvider {
NS_ERROR("This shouldn't be called because we never enable hyphens");
return 60;
}
- bool GetSpacing(gfxTextRun::Range aRange, Spacing* aSpacing) const override {
+ void GetSpacing(gfxTextRun::Range aRange, Spacing* aSpacing) const override {
NS_ERROR("This shouldn't be called because we never enable spacing");
- return false;
}
gfx::ShapedTextFlags GetShapedTextFlags() const override {
NS_ERROR("This shouldn't be called because we never enable hyphens");
@@ -401,11 +400,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,11 +962,11 @@ 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 += aOther.mAdvanceWidth;
}
@@ -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,19 +2911,19 @@ 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();
+ double x = 0;
+ if (aSpacing) {
+ x += aSpacing[0].mBefore;
+ }
uint32_t spaceGlyph = GetSpaceGlyph();
bool allGlyphsInvisible = true;
AutoReadLock lock(aExtents->mLock);
- double x = 0;
for (uint32_t i = aStart; i < aEnd; ++i) {
- if (aSpacing) {
- x += aSpacing->mBefore;
- }
const gfxTextRun::CompressedGlyph* glyphData = &charGlyphs[i];
if (glyphData->IsSimpleGlyph()) {
double advance = glyphData->GetSimpleAdvance();
@@ -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
@@ -3012,8 +3011,11 @@ bool gfxFont::MeasureGlyphs(const gfxTextRun* aTextRun, uint32_t aStart,
}
}
if (aSpacing) {
- x += aSpacing->mAfter;
- ++aSpacing;
+ double space = aSpacing[i - aStart].mAfter;
+ if (i + 1 < aEnd) {
+ space += aSpacing[i + 1 - aStart].mBefore;
+ }
+ x += space;
}
}
@@ -3055,9 +3057,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 +3127,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 +3139,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 +3180,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 +3212,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 +4114,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 +4136,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 +4149,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 +4166,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"
@@ -330,16 +329,14 @@ gfxTextRun::LigatureData gfxTextRun::ComputeLigatureData(
if (aProvider && (mFlags & gfx::ShapedTextFlags::TEXT_ENABLE_SPACING)) {
gfxFont::Spacing spacing;
if (aPartRange.start == result.mRange.start) {
- if (aProvider->GetSpacing(Range(aPartRange.start, aPartRange.start + 1),
- &spacing)) {
- result.mPartWidth += spacing.mBefore;
- }
+ aProvider->GetSpacing(Range(aPartRange.start, aPartRange.start + 1),
+ &spacing);
+ result.mPartWidth += spacing.mBefore;
}
if (aPartRange.end == result.mRange.end) {
- if (aProvider->GetSpacing(Range(aPartRange.end - 1, aPartRange.end),
- &spacing)) {
- result.mPartWidth += spacing.mAfter;
- }
+ aProvider->GetSpacing(Range(aPartRange.end - 1, aPartRange.end),
+ &spacing);
+ result.mPartWidth += spacing.mAfter;
}
}
@@ -361,16 +358,15 @@ int32_t gfxTextRun::GetAdvanceForGlyphs(Range aRange) const {
return advance;
}
-// Returns false if there is definitely no spacing to apply.
-static bool GetAdjustedSpacing(
+static void GetAdjustedSpacing(
const gfxTextRun* aTextRun, gfxTextRun::Range aRange,
const gfxTextRun::PropertyProvider& aProvider,
gfxTextRun::PropertyProvider::Spacing* aSpacing) {
if (aRange.start >= aRange.end) {
- return false;
+ return;
}
- bool result = aProvider.GetSpacing(aRange, aSpacing);
+ aProvider.GetSpacing(aRange, aSpacing);
#ifdef DEBUG
// Check to see if we have spacing inside ligatures
@@ -389,8 +385,6 @@ static bool GetAdjustedSpacing(
}
}
#endif
-
- return result;
}
bool gfxTextRun::GetAdjustedSpacingArray(
@@ -404,11 +398,8 @@ bool gfxTextRun::GetAdjustedSpacingArray(
}
auto spacingOffset = aSpacingRange.start - aRange.start;
memset(aSpacing->Elements(), 0, sizeof(gfxFont::Spacing) * spacingOffset);
- if (!GetAdjustedSpacing(this, aSpacingRange, *aProvider,
- aSpacing->Elements() + spacingOffset)) {
- aSpacing->Clear();
- return false;
- }
+ GetAdjustedSpacing(this, aSpacingRange, *aProvider,
+ aSpacing->Elements() + spacingOffset);
memset(aSpacing->Elements() + spacingOffset + aSpacingRange.Length(), 0,
sizeof(gfxFont::Spacing) * (aRange.end - aSpacingRange.end));
return true;
@@ -549,11 +540,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);
@@ -672,9 +664,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;
}
@@ -1235,16 +1227,15 @@ gfxFloat gfxTextRun::GetAdvanceWidth(
uint32_t i;
AutoTArray<PropertyProvider::Spacing, 200> spacingBuffer;
if (spacingBuffer.AppendElements(aRange.Length(), fallible)) {
- if (GetAdjustedSpacing(this, ligatureRange, *aProvider,
- spacingBuffer.Elements())) {
- for (i = 0; i < ligatureRange.Length(); ++i) {
- PropertyProvider::Spacing* space = &spacingBuffer[i];
- result += space->mBefore + space->mAfter;
- }
- if (aSpacing) {
- aSpacing->mBefore = spacingBuffer[0].mBefore;
- aSpacing->mAfter = spacingBuffer.LastElement().mAfter;
- }
+ GetAdjustedSpacing(this, ligatureRange, *aProvider,
+ spacingBuffer.Elements());
+ for (i = 0; i < ligatureRange.Length(); ++i) {
+ PropertyProvider::Spacing* space = &spacingBuffer[i];
+ result += space->mBefore + space->mAfter;
+ }
+ if (aSpacing) {
+ aSpacing->mBefore = spacingBuffer[0].mBefore;
+ aSpacing->mAfter = spacingBuffer.LastElement().mAfter;
}
}
}
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;
@@ -242,10 +242,8 @@ class gfxTextRun : public gfxShapedText {
* inside clusters. In other words, if character i is not
* CLUSTER_START, then character i-1 must have zero after-spacing and
* character i must have zero before-spacing.
- * Returns true if there is (or may be) any custom spacing; false if we
- * are sure that aSpacing contains only zero values.
*/
- virtual bool GetSpacing(Range aRange, Spacing* aSpacing) const = 0;
+ virtual void GetSpacing(Range aRange, Spacing* aSpacing) const = 0;
// Returns a gfxContext that can be used to measure the hyphen glyph.
// Only called if the hyphen width is requested.
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;
@@ -3815,11 +3815,10 @@ JustificationInfo nsTextFrame::PropertyProvider::ComputeJustification(
return info;
}
-// aStart, aLength in transformed string offsets.
-// Returns false if no non-standard spacing was required.
-bool nsTextFrame::PropertyProvider::GetSpacing(Range aRange,
+// aStart, aLength in transformed string offsets
+void nsTextFrame::PropertyProvider::GetSpacing(Range aRange,
Spacing* aSpacing) const {
- return GetSpacingInternal(
+ GetSpacingInternal(
aRange, aSpacing,
!(mTextRun->GetFlags2() & nsTextFrameUtils::Flags::HasTab));
}
@@ -3863,7 +3862,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 +3878,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));
@@ -4067,7 +4066,7 @@ static bool HasCJKGlyphRun(const gfxTextRun* aTextRun) {
return false;
}
-bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
+void nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
Spacing* aSpacing,
bool aIgnoreTabs) const {
MOZ_ASSERT(IsInBounds(mStart, mLength, aRange), "Range out of bounds");
@@ -4075,14 +4074,9 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
std::memset(aSpacing, 0, aRange.Length() * sizeof(*aSpacing));
if (mFrame->Style()->IsTextCombined()) {
- return false;
+ return;
}
- // Track whether any non-standard spacing is actually present in this range.
- // If letter-spacing is non-zero this will always be true, but for the
- /// word-spacing and text-autospace cases it will depend on the actual text.
- bool spacingPresent = mLetterSpacing;
-
// First, compute the word spacing, letter spacing, and text-autospace
// spacing.
if (mWordSpacing || mLetterSpacing || mTextAutospace) {
@@ -4091,24 +4085,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 +4164,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
@@ -4191,7 +4185,6 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
&iter);
uint32_t runOffset = iter.GetSkippedOffset() - aRange.start;
aSpacing[runOffset].mAfter += mWordSpacing;
- spacingPresent = true;
}
// Add text-autospace spacing only at cluster starts. Always check the
// character classes if the textrun includes CJK; otherwise, check only
@@ -4216,7 +4209,6 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
prevClass.valueOrFrom(findPrecedingClass), currClass)) {
aSpacing[runOffsetInSubstring + i].mBefore +=
mTextAutospace->InterScriptSpacing();
- spacingPresent = true;
}
// Even if we didn't actually need to check spacing rules here, we
// record the new prevClass. (Incidentally, this ensure that we'll
@@ -4238,7 +4230,6 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
mTabWidths->ApplySpacing(aSpacing,
aRange.start - mStart.GetSkippedOffset(),
aRange.Length());
- spacingPresent = true;
}
}
}
@@ -4259,20 +4250,16 @@ bool nsTextFrame::PropertyProvider::GetSpacingInternal(Range aRange,
aSpacing[offset].mBefore += spacing.mBefore;
aSpacing[offset].mAfter += spacing.mAfter;
}
- spacingPresent = true;
}
-
- return spacingPresent;
}
// 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 +4320,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 +4344,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()) {
@@ -6567,8 +6555,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(),
@@ -7372,8 +7359,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);
@@ -7397,12 +7384,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);
}
}
@@ -9550,7 +9532,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();
}
@@ -9877,6 +9859,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.
@@ -9902,7 +9893,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.
@@ -9927,8 +9918,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;
}
@@ -10681,15 +10672,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
@@ -10700,8 +10694,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);
@@ -10715,9 +10709,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;
@@ -10813,7 +10808,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);
@@ -11071,7 +11066,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
@@ -160,8 +160,8 @@ class nsTextFrame : public nsIFrame {
void InitializeForMeasure();
- bool GetSpacing(Range aRange, Spacing* aSpacing) const final;
- nscoord GetHyphenWidth() const final;
+ void GetSpacing(Range aRange, Spacing* aSpacing) const final;
+ gfxFloat GetHyphenWidth() const final;
void GetHyphenationBreaks(Range aRange,
HyphenType* aBreakBefore) const final;
mozilla::StyleHyphens GetHyphensOption() const final {
@@ -175,7 +175,7 @@ class nsTextFrame : public nsIFrame {
return mTextRun->GetAppUnitsPerDevUnit();
}
- bool GetSpacingInternal(Range aRange, Spacing* aSpacing,
+ void GetSpacingInternal(Range aRange, Spacing* aSpacing,
bool aIgnoreTabs) const;
/**
@@ -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-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