Bug 1251995 part 2 - Add gfxTextRun::Range to replace parameter pairs like (offset, length) and (start, end). r=jfkthame

Although this makes some places more complicated, code should generally
be simpler and clearer. It could slightly improve performance on x64 for
functions with more than four parameters, since it makes more data be
passed via registers rather than the stack.

MozReview-Commit-ID: D0GM2Jyrr6W

--HG--
extra : source : bd88a2e478e23edf1845f724a32fef908c8cc007
This commit is contained in:
Xidorn Quan 2016-03-08 15:56:18 +08:00
parent ab357753a9
commit b3ea3fa801
17 changed files with 546 additions and 572 deletions

View File

@ -658,10 +658,9 @@ ContentEventHandler::AppendFontRanges(FontRangeArray& aFontRanges,
} }
} }
uint32_t skipStart = iter.ConvertOriginalToSkipped(frameXPStart); gfxTextRun::Range skipRange(iter.ConvertOriginalToSkipped(frameXPStart),
uint32_t skipEnd = iter.ConvertOriginalToSkipped(frameXPEnd); iter.ConvertOriginalToSkipped(frameXPEnd));
gfxTextRun::GlyphRunIterator runIter( gfxTextRun::GlyphRunIterator runIter(textRun, skipRange);
textRun, skipStart, skipEnd - skipStart);
int32_t lastXPEndOffset = frameXPStart; int32_t lastXPEndOffset = frameXPStart;
while (runIter.NextRun()) { while (runIter.NextRun()) {
gfxFont* font = runIter.GetGlyphRun()->mFont.get(); gfxFont* font = runIter.GetGlyphRun()->mFont.get();

View File

@ -81,7 +81,7 @@ private:
class StubPropertyProvider : public gfxTextRun::PropertyProvider { class StubPropertyProvider : public gfxTextRun::PropertyProvider {
public: public:
virtual void GetHyphenationBreaks(uint32_t aStart, uint32_t aLength, virtual void GetHyphenationBreaks(gfxTextRun::Range aRange,
bool* aBreakBefore) { bool* aBreakBefore) {
NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText"); NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
} }
@ -101,8 +101,7 @@ public:
NS_ERROR("This shouldn't be called because we never enable hyphens"); NS_ERROR("This shouldn't be called because we never enable hyphens");
return 60; return 60;
} }
virtual void GetSpacing(uint32_t aStart, uint32_t aLength, virtual void GetSpacing(gfxTextRun::Range aRange, Spacing* aSpacing) {
Spacing* aSpacing) {
NS_ERROR("This shouldn't be called because we never enable spacing"); NS_ERROR("This shouldn't be called because we never enable spacing");
} }
}; };
@ -325,8 +324,11 @@ nsFontMetrics::GetWidth(const char* aString, uint32_t aLength,
StubPropertyProvider provider; StubPropertyProvider provider;
AutoTextRun textRun(this, aDrawTarget, aString, aLength); AutoTextRun textRun(this, aDrawTarget, aString, aLength);
return textRun.get() ? if (textRun.get()) {
NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider)) : 0; return NSToCoordRound(
textRun->GetAdvanceWidth(Range(0, aLength), &provider));
}
return 0;
} }
nscoord nscoord
@ -341,8 +343,11 @@ nsFontMetrics::GetWidth(const char16_t* aString, uint32_t aLength,
StubPropertyProvider provider; StubPropertyProvider provider;
AutoTextRun textRun(this, aDrawTarget, aString, aLength); AutoTextRun textRun(this, aDrawTarget, aString, aLength);
return textRun.get() ? if (textRun.get()) {
NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider)) : 0; return NSToCoordRound(
textRun->GetAdvanceWidth(Range(0, aLength), &provider));
}
return 0;
} }
// Draw a string using this font handle on the surface passed in. // Draw a string using this font handle on the surface passed in.
@ -360,15 +365,16 @@ nsFontMetrics::DrawString(const char *aString, uint32_t aLength,
return; return;
} }
gfxPoint pt(aX, aY); gfxPoint pt(aX, aY);
Range range(0, aLength);
if (mTextRunRTL) { if (mTextRunRTL) {
if (mVertical) { if (mVertical) {
pt.y += textRun->GetAdvanceWidth(0, aLength, &provider); pt.y += textRun->GetAdvanceWidth(range, &provider);
} else { } else {
pt.x += textRun->GetAdvanceWidth(0, aLength, &provider); pt.x += textRun->GetAdvanceWidth(range, &provider);
} }
} }
textRun->Draw(aContext->ThebesContext(), pt, DrawMode::GLYPH_FILL, 0, aLength, textRun->Draw(aContext->ThebesContext(), pt, DrawMode::GLYPH_FILL,
&provider, nullptr, nullptr); range, &provider, nullptr, nullptr);
} }
void void
@ -386,15 +392,16 @@ nsFontMetrics::DrawString(const char16_t* aString, uint32_t aLength,
return; return;
} }
gfxPoint pt(aX, aY); gfxPoint pt(aX, aY);
Range range(0, aLength);
if (mTextRunRTL) { if (mTextRunRTL) {
if (mVertical) { if (mVertical) {
pt.y += textRun->GetAdvanceWidth(0, aLength, &provider); pt.y += textRun->GetAdvanceWidth(range, &provider);
} else { } else {
pt.x += textRun->GetAdvanceWidth(0, aLength, &provider); pt.x += textRun->GetAdvanceWidth(range, &provider);
} }
} }
textRun->Draw(aContext->ThebesContext(), pt, DrawMode::GLYPH_FILL, 0, aLength, textRun->Draw(aContext->ThebesContext(), pt, DrawMode::GLYPH_FILL,
&provider, nullptr, nullptr); range, &provider, nullptr, nullptr);
} }
static nsBoundingMetrics static nsBoundingMetrics
@ -409,8 +416,8 @@ GetTextBoundingMetrics(nsFontMetrics* aMetrics, const char16_t* aString,
AutoTextRun textRun(aMetrics, aDrawTarget, aString, aLength); AutoTextRun textRun(aMetrics, aDrawTarget, aString, aLength);
nsBoundingMetrics m; nsBoundingMetrics m;
if (textRun.get()) { if (textRun.get()) {
gfxTextRun::Metrics theMetrics = gfxTextRun::Metrics theMetrics = textRun->MeasureText(
textRun->MeasureText(0, aLength, aType, aDrawTarget, &provider); gfxTextRun::Range(0, aLength), aType, aDrawTarget, &provider);
m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X()); m.leftBearing = NSToCoordFloor( theMetrics.mBoundingBox.X());
m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost()); m.rightBearing = NSToCoordCeil( theMetrics.mBoundingBox.XMost());

View File

@ -46,6 +46,7 @@ struct nsBoundingMetrics;
class nsFontMetrics final class nsFontMetrics final
{ {
public: public:
typedef gfxTextRun::Range Range;
typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::DrawTarget DrawTarget;
nsFontMetrics(); nsFontMetrics();

View File

@ -1943,7 +1943,7 @@ gfxFont::DrawEmphasisMarks(gfxTextRun* aShapedText, gfxPoint* aPt,
const EmphasisMarkDrawParams& aParams) const EmphasisMarkDrawParams& aParams)
{ {
gfxFloat& inlineCoord = aParams.isVertical ? aPt->y : aPt->x; gfxFloat& inlineCoord = aParams.isVertical ? aPt->y : aPt->x;
uint32_t markLength = aParams.mark->GetLength(); gfxTextRun::Range markRange(aParams.mark);
gfxFloat clusterStart = -std::numeric_limits<gfxFloat>::infinity(); gfxFloat clusterStart = -std::numeric_limits<gfxFloat>::infinity();
bool shouldDrawEmphasisMark = false; bool shouldDrawEmphasisMark = false;
@ -1966,7 +1966,7 @@ gfxFont::DrawEmphasisMarks(gfxTextRun* aShapedText, gfxPoint* aPt,
gfxFloat delta = (clusterAdvance + aParams.advance) / 2; gfxFloat delta = (clusterAdvance + aParams.advance) / 2;
inlineCoord -= delta; inlineCoord -= delta;
aParams.mark->Draw(aParams.context, *aPt, DrawMode::GLYPH_FILL, aParams.mark->Draw(aParams.context, *aPt, DrawMode::GLYPH_FILL,
0, markLength, nullptr, nullptr, nullptr); markRange, nullptr, nullptr, nullptr);
inlineCoord += delta; inlineCoord += delta;
shouldDrawEmphasisMark = false; shouldDrawEmphasisMark = false;
} }
@ -3187,7 +3187,8 @@ gfxFont::InitFakeSmallCapsRun(DrawTarget *aDrawTarget,
MergeCharactersInTextRun(mergedRun, tempRun, MergeCharactersInTextRun(mergedRun, tempRun,
charsToMergeArray.Elements(), charsToMergeArray.Elements(),
deletedCharsArray.Elements()); deletedCharsArray.Elements());
aTextRun->CopyGlyphDataFrom(mergedRun, 0, runLength, gfxTextRun::Range runRange(0, runLength);
aTextRun->CopyGlyphDataFrom(mergedRun, runRange,
aOffset + runStart); aOffset + runStart);
} }
} else { } else {

View File

@ -210,15 +210,14 @@ gfxTextRun::ReleaseFontGroup()
} }
bool bool
gfxTextRun::SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, gfxTextRun::SetPotentialLineBreaks(Range aRange, uint8_t *aBreakBefore)
uint8_t *aBreakBefore)
{ {
NS_ASSERTION(aStart + aLength <= GetLength(), "Overflow"); NS_ASSERTION(aRange.end <= GetLength(), "Overflow");
uint32_t changed = 0; uint32_t changed = 0;
uint32_t i; uint32_t i;
CompressedGlyph *charGlyphs = mCharacterGlyphs + aStart; CompressedGlyph *charGlyphs = mCharacterGlyphs + aRange.start;
for (i = 0; i < aLength; ++i) { for (i = 0; i < aRange.Length(); ++i) {
uint8_t canBreak = aBreakBefore[i]; uint8_t canBreak = aBreakBefore[i];
if (canBreak && !charGlyphs[i].IsClusterStart()) { if (canBreak && !charGlyphs[i].IsClusterStart()) {
// This can happen ... there is no guarantee that our linebreaking rules // This can happen ... there is no guarantee that our linebreaking rules
@ -231,39 +230,39 @@ gfxTextRun::SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength,
} }
gfxTextRun::LigatureData gfxTextRun::LigatureData
gfxTextRun::ComputeLigatureData(uint32_t aPartStart, uint32_t aPartEnd, gfxTextRun::ComputeLigatureData(Range aPartRange, PropertyProvider *aProvider)
PropertyProvider *aProvider)
{ {
NS_ASSERTION(aPartStart < aPartEnd, "Computing ligature data for empty range"); NS_ASSERTION(aPartRange.start < aPartRange.end,
NS_ASSERTION(aPartEnd <= GetLength(), "Character length overflow"); "Computing ligature data for empty range");
NS_ASSERTION(aPartRange.end <= GetLength(), "Character length overflow");
LigatureData result; LigatureData result;
CompressedGlyph *charGlyphs = mCharacterGlyphs; CompressedGlyph *charGlyphs = mCharacterGlyphs;
uint32_t i; uint32_t i;
for (i = aPartStart; !charGlyphs[i].IsLigatureGroupStart(); --i) { for (i = aPartRange.start; !charGlyphs[i].IsLigatureGroupStart(); --i) {
NS_ASSERTION(i > 0, "Ligature at the start of the run??"); NS_ASSERTION(i > 0, "Ligature at the start of the run??");
} }
result.mLigatureStart = i; result.mRange.start = i;
for (i = aPartStart + 1; i < GetLength() && !charGlyphs[i].IsLigatureGroupStart(); ++i) { for (i = aPartRange.start + 1;
i < GetLength() && !charGlyphs[i].IsLigatureGroupStart(); ++i) {
} }
result.mLigatureEnd = i; result.mRange.end = i;
int32_t ligatureWidth = int32_t ligatureWidth = GetAdvanceForGlyphs(result.mRange);
GetAdvanceForGlyphs(result.mLigatureStart, result.mLigatureEnd);
// Count the number of started clusters we have seen // Count the number of started clusters we have seen
uint32_t totalClusterCount = 0; uint32_t totalClusterCount = 0;
uint32_t partClusterIndex = 0; uint32_t partClusterIndex = 0;
uint32_t partClusterCount = 0; uint32_t partClusterCount = 0;
for (i = result.mLigatureStart; i < result.mLigatureEnd; ++i) { for (i = result.mRange.start; i < result.mRange.end; ++i) {
// Treat the first character of the ligature as the start of a // Treat the first character of the ligature as the start of a
// cluster for our purposes of allocating ligature width to its // cluster for our purposes of allocating ligature width to its
// characters. // characters.
if (i == result.mLigatureStart || charGlyphs[i].IsClusterStart()) { if (i == result.mRange.start || charGlyphs[i].IsClusterStart()) {
++totalClusterCount; ++totalClusterCount;
if (i < aPartStart) { if (i < aPartRange.start) {
++partClusterIndex; ++partClusterIndex;
} else if (i < aPartEnd) { } else if (i < aPartRange.end) {
++partClusterCount; ++partClusterCount;
} }
} }
@ -275,7 +274,7 @@ gfxTextRun::ComputeLigatureData(uint32_t aPartStart, uint32_t aPartEnd,
// Any rounding errors are apportioned to the final part of the ligature, // Any rounding errors are apportioned to the final part of the ligature,
// so that measuring all parts of a ligature and summing them is equal to // so that measuring all parts of a ligature and summing them is equal to
// the ligature width. // the ligature width.
if (aPartEnd == result.mLigatureEnd) { if (aPartRange.end == result.mRange.end) {
gfxFloat allParts = totalClusterCount * (ligatureWidth / totalClusterCount); gfxFloat allParts = totalClusterCount * (ligatureWidth / totalClusterCount);
result.mPartWidth += ligatureWidth - allParts; result.mPartWidth += ligatureWidth - allParts;
} }
@ -296,12 +295,14 @@ gfxTextRun::ComputeLigatureData(uint32_t aPartStart, uint32_t aPartEnd,
if (aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING)) { if (aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING)) {
gfxFont::Spacing spacing; gfxFont::Spacing spacing;
if (aPartStart == result.mLigatureStart) { if (aPartRange.start == result.mRange.start) {
aProvider->GetSpacing(aPartStart, 1, &spacing); aProvider->GetSpacing(
Range(aPartRange.start, aPartRange.start + 1), &spacing);
result.mPartWidth += spacing.mBefore; result.mPartWidth += spacing.mBefore;
} }
if (aPartEnd == result.mLigatureEnd) { if (aPartRange.end == result.mRange.end) {
aProvider->GetSpacing(aPartEnd - 1, 1, &spacing); aProvider->GetSpacing(
Range(aPartRange.end - 1, aPartRange.end), &spacing);
result.mPartWidth += spacing.mAfter; result.mPartWidth += spacing.mAfter;
} }
} }
@ -310,34 +311,34 @@ gfxTextRun::ComputeLigatureData(uint32_t aPartStart, uint32_t aPartEnd,
} }
gfxFloat gfxFloat
gfxTextRun::ComputePartialLigatureWidth(uint32_t aPartStart, uint32_t aPartEnd, gfxTextRun::ComputePartialLigatureWidth(Range aPartRange,
PropertyProvider *aProvider) PropertyProvider *aProvider)
{ {
if (aPartStart >= aPartEnd) if (aPartRange.start >= aPartRange.end)
return 0; return 0;
LigatureData data = ComputeLigatureData(aPartStart, aPartEnd, aProvider); LigatureData data = ComputeLigatureData(aPartRange, aProvider);
return data.mPartWidth; return data.mPartWidth;
} }
int32_t int32_t
gfxTextRun::GetAdvanceForGlyphs(uint32_t aStart, uint32_t aEnd) gfxTextRun::GetAdvanceForGlyphs(Range aRange)
{ {
int32_t advance = 0; int32_t advance = 0;
for (auto i = aStart; i < aEnd; ++i) { for (auto i = aRange.start; i < aRange.end; ++i) {
advance += GetAdvanceForGlyph(i); advance += GetAdvanceForGlyph(i);
} }
return advance; return advance;
} }
static void static void
GetAdjustedSpacing(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd, GetAdjustedSpacing(gfxTextRun *aTextRun, gfxTextRun::Range aRange,
gfxTextRun::PropertyProvider *aProvider, gfxTextRun::PropertyProvider *aProvider,
gfxTextRun::PropertyProvider::Spacing *aSpacing) gfxTextRun::PropertyProvider::Spacing *aSpacing)
{ {
if (aStart >= aEnd) if (aRange.start >= aRange.end)
return; return;
aProvider->GetSpacing(aStart, aEnd - aStart, aSpacing); aProvider->GetSpacing(aRange, aSpacing);
#ifdef DEBUG #ifdef DEBUG
// Check to see if we have spacing inside ligatures // Check to see if we have spacing inside ligatures
@ -345,11 +346,13 @@ GetAdjustedSpacing(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
const gfxTextRun::CompressedGlyph *charGlyphs = aTextRun->GetCharacterGlyphs(); const gfxTextRun::CompressedGlyph *charGlyphs = aTextRun->GetCharacterGlyphs();
uint32_t i; uint32_t i;
for (i = aStart; i < aEnd; ++i) { for (i = aRange.start; i < aRange.end; ++i) {
if (!charGlyphs[i].IsLigatureGroupStart()) { if (!charGlyphs[i].IsLigatureGroupStart()) {
NS_ASSERTION(i == aStart || aSpacing[i - aStart].mBefore == 0, NS_ASSERTION(i == aRange.start ||
aSpacing[i - aRange.start].mBefore == 0,
"Before-spacing inside a ligature!"); "Before-spacing inside a ligature!");
NS_ASSERTION(i - 1 <= aStart || aSpacing[i - 1 - aStart].mAfter == 0, NS_ASSERTION(i - 1 <= aRange.start ||
aSpacing[i - 1 - aRange.start].mAfter == 0,
"After-spacing inside a ligature!"); "After-spacing inside a ligature!");
} }
} }
@ -357,51 +360,53 @@ GetAdjustedSpacing(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd,
} }
bool bool
gfxTextRun::GetAdjustedSpacingArray(uint32_t aStart, uint32_t aEnd, gfxTextRun::GetAdjustedSpacingArray(Range aRange, PropertyProvider *aProvider,
PropertyProvider *aProvider, Range aSpacingRange,
uint32_t aSpacingStart, uint32_t aSpacingEnd,
nsTArray<PropertyProvider::Spacing> *aSpacing) nsTArray<PropertyProvider::Spacing> *aSpacing)
{ {
if (!aProvider || !(mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING)) if (!aProvider || !(mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING))
return false; return false;
if (!aSpacing->AppendElements(aEnd - aStart)) if (!aSpacing->AppendElements(aRange.Length()))
return false; return false;
memset(aSpacing->Elements(), 0, sizeof(gfxFont::Spacing)*(aSpacingStart - aStart)); auto spacingOffset = aSpacingRange.start - aRange.start;
GetAdjustedSpacing(this, aSpacingStart, aSpacingEnd, aProvider, memset(aSpacing->Elements(), 0, sizeof(gfxFont::Spacing) * spacingOffset);
aSpacing->Elements() + aSpacingStart - aStart); GetAdjustedSpacing(this, aSpacingRange, aProvider,
memset(aSpacing->Elements() + aSpacingEnd - aStart, 0, sizeof(gfxFont::Spacing)*(aEnd - aSpacingEnd)); aSpacing->Elements() + spacingOffset);
memset(aSpacing->Elements() + aSpacingRange.end - aRange.start, 0,
sizeof(gfxFont::Spacing) * (aRange.end - aSpacingRange.end));
return true; return true;
} }
void void
gfxTextRun::ShrinkToLigatureBoundaries(uint32_t *aStart, uint32_t *aEnd) gfxTextRun::ShrinkToLigatureBoundaries(Range* aRange)
{ {
if (*aStart >= *aEnd) if (aRange->start >= aRange->end)
return; return;
CompressedGlyph *charGlyphs = mCharacterGlyphs; CompressedGlyph *charGlyphs = mCharacterGlyphs;
while (*aStart < *aEnd && !charGlyphs[*aStart].IsLigatureGroupStart()) { while (aRange->start < aRange->end &&
++(*aStart); !charGlyphs[aRange->start].IsLigatureGroupStart()) {
++aRange->start;
} }
if (*aEnd < GetLength()) { if (aRange->end < GetLength()) {
while (*aEnd > *aStart && !charGlyphs[*aEnd].IsLigatureGroupStart()) { while (aRange->end > aRange->start &&
--(*aEnd); !charGlyphs[aRange->end].IsLigatureGroupStart()) {
--aRange->end;
} }
} }
} }
void void
gfxTextRun::DrawGlyphs(gfxFont *aFont, uint32_t aStart, uint32_t aEnd, gfxTextRun::DrawGlyphs(gfxFont *aFont, Range aRange, gfxPoint *aPt,
gfxPoint *aPt, PropertyProvider *aProvider, PropertyProvider *aProvider, Range aSpacingRange,
uint32_t aSpacingStart, uint32_t aSpacingEnd,
TextRunDrawParams& aParams, uint16_t aOrientation) TextRunDrawParams& aParams, uint16_t aOrientation)
{ {
AutoTArray<PropertyProvider::Spacing,200> spacingBuffer; AutoTArray<PropertyProvider::Spacing,200> spacingBuffer;
bool haveSpacing = GetAdjustedSpacingArray(aStart, aEnd, aProvider, bool haveSpacing = GetAdjustedSpacingArray(aRange, aProvider,
aSpacingStart, aSpacingEnd, &spacingBuffer); aSpacingRange, &spacingBuffer);
aParams.spacing = haveSpacing ? spacingBuffer.Elements() : nullptr; aParams.spacing = haveSpacing ? spacingBuffer.Elements() : nullptr;
aFont->Draw(this, aStart, aEnd, aPt, aParams, aOrientation); aFont->Draw(this, aRange.start, aRange.end, aPt, aParams, aOrientation);
} }
static void static void
@ -429,16 +434,16 @@ ClipPartialLigature(const gfxTextRun* aTextRun,
} }
void void
gfxTextRun::DrawPartialLigature(gfxFont *aFont, uint32_t aStart, uint32_t aEnd, gfxTextRun::DrawPartialLigature(gfxFont *aFont, Range aRange,
gfxPoint *aPt, PropertyProvider *aProvider, gfxPoint *aPt, PropertyProvider *aProvider,
TextRunDrawParams& aParams, uint16_t aOrientation) TextRunDrawParams& aParams, uint16_t aOrientation)
{ {
if (aStart >= aEnd) { if (aRange.start >= aRange.end) {
return; return;
} }
// Draw partial ligature. We hack this by clipping the ligature. // Draw partial ligature. We hack this by clipping the ligature.
LigatureData data = ComputeLigatureData(aStart, aEnd, aProvider); LigatureData data = ComputeLigatureData(aRange, aProvider);
gfxRect clipExtents = aParams.context->GetClipExtents(); gfxRect clipExtents = aParams.context->GetClipExtents();
gfxFloat start, end; gfxFloat start, end;
if (aParams.isVerticalRun) { if (aParams.isVerticalRun) {
@ -473,8 +478,8 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, uint32_t aStart, uint32_t aEnd,
pt = gfxPoint(aPt->x - aParams.direction * data.mPartAdvance, aPt->y); pt = gfxPoint(aPt->x - aParams.direction * data.mPartAdvance, aPt->y);
} }
DrawGlyphs(aFont, data.mLigatureStart, data.mLigatureEnd, &pt, DrawGlyphs(aFont, data.mRange, &pt,
aProvider, aStart, aEnd, aParams, aOrientation); aProvider, aRange, aParams, aOrientation);
aParams.context->Restore(); aParams.context->Restore();
if (aParams.isVerticalRun) { if (aParams.isVerticalRun) {
@ -489,9 +494,9 @@ gfxTextRun::DrawPartialLigature(gfxFont *aFont, uint32_t aStart, uint32_t aEnd,
// check whether the text run needs to be explicitly composited in order to // check whether the text run needs to be explicitly composited in order to
// support opacity. // support opacity.
static bool static bool
HasSyntheticBoldOrColor(gfxTextRun *aRun, uint32_t aStart, uint32_t aLength) HasSyntheticBoldOrColor(gfxTextRun *aRun, gfxTextRun::Range aRange)
{ {
gfxTextRun::GlyphRunIterator iter(aRun, aStart, aLength); gfxTextRun::GlyphRunIterator iter(aRun, aRange);
while (iter.NextRun()) { while (iter.NextRun()) {
gfxFont *font = iter.GetGlyphRun()->mFont; gfxFont *font = iter.GetGlyphRun()->mFont;
if (font) { if (font) {
@ -560,12 +565,12 @@ struct BufferAlphaColor {
void void
gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode, gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
uint32_t aStart, uint32_t aLength, Range aRange,
PropertyProvider *aProvider, gfxFloat *aAdvanceWidth, PropertyProvider *aProvider, gfxFloat *aAdvanceWidth,
gfxTextContextPaint *aContextPaint, gfxTextContextPaint *aContextPaint,
gfxTextRunDrawCallbacks *aCallbacks) gfxTextRunDrawCallbacks *aCallbacks)
{ {
NS_ASSERTION(aStart + aLength <= GetLength(), "Substring out of range"); NS_ASSERTION(aRange.end <= GetLength(), "Substring out of range");
NS_ASSERTION(aDrawMode == DrawMode::GLYPH_PATH || NS_ASSERTION(aDrawMode == DrawMode::GLYPH_PATH ||
!(int(aDrawMode) & int(DrawMode::GLYPH_PATH)), !(int(aDrawMode) & int(DrawMode::GLYPH_PATH)),
"GLYPH_PATH cannot be used with GLYPH_FILL, GLYPH_STROKE or GLYPH_STROKE_UNDERNEATH"); "GLYPH_PATH cannot be used with GLYPH_FILL, GLYPH_STROKE or GLYPH_STROKE_UNDERNEATH");
@ -586,7 +591,7 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
// We don't need to draw anything; // We don't need to draw anything;
// but if the caller wants advance width, we need to compute it here // but if the caller wants advance width, we need to compute it here
if (aAdvanceWidth) { if (aAdvanceWidth) {
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength, gfxTextRun::Metrics metrics = MeasureText(aRange,
gfxFont::LOOSE_INK_EXTENTS, gfxFont::LOOSE_INK_EXTENTS,
aContext->GetDrawTarget(), aContext->GetDrawTarget(),
aProvider); aProvider);
@ -605,10 +610,10 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
if (aDrawMode == DrawMode::GLYPH_FILL && if (aDrawMode == DrawMode::GLYPH_FILL &&
HasNonOpaqueNonTransparentColor(aContext, currentColor) && HasNonOpaqueNonTransparentColor(aContext, currentColor) &&
HasSyntheticBoldOrColor(this, aStart, aLength)) { HasSyntheticBoldOrColor(this, aRange)) {
needToRestore = true; needToRestore = true;
// measure text, use the bounding box // measure text, use the bounding box
gfxTextRun::Metrics metrics = MeasureText(aStart, aLength, gfxTextRun::Metrics metrics = MeasureText(aRange,
gfxFont::LOOSE_INK_EXTENTS, gfxFont::LOOSE_INK_EXTENTS,
aContext->GetDrawTarget(), aContext->GetDrawTarget(),
aProvider); aProvider);
@ -632,34 +637,33 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
params.dt = aContext->GetDrawTarget(); params.dt = aContext->GetDrawTarget();
params.fontSmoothingBGColor = aContext->GetFontSmoothingBackgroundColor(); params.fontSmoothingBGColor = aContext->GetFontSmoothingBackgroundColor();
GlyphRunIterator iter(this, aStart, aLength); GlyphRunIterator iter(this, aRange);
gfxFloat advance = 0.0; gfxFloat advance = 0.0;
while (iter.NextRun()) { while (iter.NextRun()) {
gfxFont *font = iter.GetGlyphRun()->mFont; gfxFont *font = iter.GetGlyphRun()->mFont;
uint32_t start = iter.GetStringStart(); uint32_t start = iter.GetStringStart();
uint32_t end = iter.GetStringEnd(); uint32_t end = iter.GetStringEnd();
uint32_t ligatureRunStart = start; Range ligatureRange(start, end);
uint32_t ligatureRunEnd = end; ShrinkToLigatureBoundaries(&ligatureRange);
ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
bool drawPartial = aDrawMode == DrawMode::GLYPH_FILL || bool drawPartial = aDrawMode == DrawMode::GLYPH_FILL ||
(aDrawMode == DrawMode::GLYPH_PATH && aCallbacks); (aDrawMode == DrawMode::GLYPH_PATH && aCallbacks);
gfxPoint origPt = aPt; gfxPoint origPt = aPt;
if (drawPartial) { if (drawPartial) {
DrawPartialLigature(font, start, ligatureRunStart, &aPt, DrawPartialLigature(font, Range(start, ligatureRange.start),
aProvider, params, &aPt, aProvider, params,
iter.GetGlyphRun()->mOrientation); iter.GetGlyphRun()->mOrientation);
} }
DrawGlyphs(font, ligatureRunStart, ligatureRunEnd, &aPt, DrawGlyphs(font, ligatureRange, &aPt,
aProvider, ligatureRunStart, ligatureRunEnd, params, aProvider, ligatureRange, params,
iter.GetGlyphRun()->mOrientation); iter.GetGlyphRun()->mOrientation);
if (drawPartial) { if (drawPartial) {
DrawPartialLigature(font, ligatureRunEnd, end, &aPt, DrawPartialLigature(font, Range(ligatureRange.end, end),
aProvider, params, &aPt, aProvider, params,
iter.GetGlyphRun()->mOrientation); iter.GetGlyphRun()->mOrientation);
} }
@ -684,10 +688,9 @@ gfxTextRun::Draw(gfxContext *aContext, gfxPoint aPt, DrawMode aDrawMode,
void void
gfxTextRun::DrawEmphasisMarks(gfxContext *aContext, gfxTextRun* aMark, gfxTextRun::DrawEmphasisMarks(gfxContext *aContext, gfxTextRun* aMark,
gfxFloat aMarkAdvance, gfxPoint aPt, gfxFloat aMarkAdvance, gfxPoint aPt,
uint32_t aStart, uint32_t aLength, Range aRange, PropertyProvider* aProvider)
PropertyProvider* aProvider)
{ {
MOZ_ASSERT(aStart + aLength <= GetLength()); MOZ_ASSERT(aRange.end <= GetLength());
EmphasisMarkDrawParams params; EmphasisMarkDrawParams params;
params.context = aContext; params.context = aContext;
@ -699,69 +702,65 @@ gfxTextRun::DrawEmphasisMarks(gfxContext *aContext, gfxTextRun* aMark,
gfxFloat& inlineCoord = params.isVertical ? aPt.y : aPt.x; gfxFloat& inlineCoord = params.isVertical ? aPt.y : aPt.x;
gfxFloat direction = params.direction; gfxFloat direction = params.direction;
GlyphRunIterator iter(this, aStart, aLength); GlyphRunIterator iter(this, aRange);
while (iter.NextRun()) { while (iter.NextRun()) {
gfxFont* font = iter.GetGlyphRun()->mFont; gfxFont* font = iter.GetGlyphRun()->mFont;
uint32_t start = iter.GetStringStart(); uint32_t start = iter.GetStringStart();
uint32_t end = iter.GetStringEnd(); uint32_t end = iter.GetStringEnd();
uint32_t ligatureRunStart = start; Range ligatureRange(start, end);
uint32_t ligatureRunEnd = end; ShrinkToLigatureBoundaries(&ligatureRange);
ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
inlineCoord += direction * inlineCoord += direction * ComputePartialLigatureWidth(
ComputePartialLigatureWidth(start, ligatureRunStart, aProvider); Range(start, ligatureRange.start), aProvider);
AutoTArray<PropertyProvider::Spacing, 200> spacingBuffer; AutoTArray<PropertyProvider::Spacing, 200> spacingBuffer;
bool haveSpacing = GetAdjustedSpacingArray( bool haveSpacing = GetAdjustedSpacingArray(
ligatureRunStart, ligatureRunEnd, aProvider, ligatureRange, aProvider, ligatureRange, &spacingBuffer);
ligatureRunStart, ligatureRunEnd, &spacingBuffer);
params.spacing = haveSpacing ? spacingBuffer.Elements() : nullptr; params.spacing = haveSpacing ? spacingBuffer.Elements() : nullptr;
font->DrawEmphasisMarks(this, &aPt, ligatureRunStart, font->DrawEmphasisMarks(this, &aPt, ligatureRange.start,
ligatureRunEnd - ligatureRunStart, params); ligatureRange.Length(), params);
inlineCoord += direction * inlineCoord += direction * ComputePartialLigatureWidth(
ComputePartialLigatureWidth(ligatureRunEnd, end, aProvider); Range(ligatureRange.end, end), aProvider);
} }
} }
void void
gfxTextRun::AccumulateMetricsForRun(gfxFont *aFont, gfxTextRun::AccumulateMetricsForRun(gfxFont *aFont, Range aRange,
uint32_t aStart, uint32_t aEnd,
gfxFont::BoundingBoxType aBoundingBoxType, gfxFont::BoundingBoxType aBoundingBoxType,
DrawTarget* aRefDrawTarget, DrawTarget* aRefDrawTarget,
PropertyProvider *aProvider, PropertyProvider *aProvider,
uint32_t aSpacingStart, uint32_t aSpacingEnd, Range aSpacingRange,
uint16_t aOrientation, uint16_t aOrientation,
Metrics *aMetrics) Metrics *aMetrics)
{ {
AutoTArray<PropertyProvider::Spacing,200> spacingBuffer; AutoTArray<PropertyProvider::Spacing,200> spacingBuffer;
bool haveSpacing = GetAdjustedSpacingArray(aStart, aEnd, aProvider, bool haveSpacing = GetAdjustedSpacingArray(aRange, aProvider,
aSpacingStart, aSpacingEnd, &spacingBuffer); aSpacingRange, &spacingBuffer);
Metrics metrics = aFont->Measure(this, aStart, aEnd, aBoundingBoxType, Metrics metrics = aFont->Measure(this, aRange.start, aRange.end,
aRefDrawTarget, aBoundingBoxType, aRefDrawTarget,
haveSpacing ? spacingBuffer.Elements() : nullptr, haveSpacing ? spacingBuffer.Elements() : nullptr,
aOrientation); aOrientation);
aMetrics->CombineWith(metrics, IsRightToLeft()); aMetrics->CombineWith(metrics, IsRightToLeft());
} }
void void
gfxTextRun::AccumulatePartialLigatureMetrics(gfxFont *aFont, gfxTextRun::AccumulatePartialLigatureMetrics(gfxFont *aFont, Range aRange,
uint32_t aStart, uint32_t aEnd,
gfxFont::BoundingBoxType aBoundingBoxType, DrawTarget* aRefDrawTarget, gfxFont::BoundingBoxType aBoundingBoxType, DrawTarget* aRefDrawTarget,
PropertyProvider *aProvider, uint16_t aOrientation, Metrics *aMetrics) PropertyProvider *aProvider, uint16_t aOrientation, Metrics *aMetrics)
{ {
if (aStart >= aEnd) if (aRange.start >= aRange.end)
return; return;
// Measure partial ligature. We hack this by clipping the metrics in the // Measure partial ligature. We hack this by clipping the metrics in the
// same way we clip the drawing. // same way we clip the drawing.
LigatureData data = ComputeLigatureData(aStart, aEnd, aProvider); LigatureData data = ComputeLigatureData(aRange, aProvider);
// First measure the complete ligature // First measure the complete ligature
Metrics metrics; Metrics metrics;
AccumulateMetricsForRun(aFont, data.mLigatureStart, data.mLigatureEnd, AccumulateMetricsForRun(aFont, data.mRange,
aBoundingBoxType, aRefDrawTarget, aBoundingBoxType, aRefDrawTarget,
aProvider, aStart, aEnd, aOrientation, &metrics); aProvider, aRange, aOrientation, &metrics);
// Clip the bounding box to the ligature part // Clip the bounding box to the ligature part
gfxFloat bboxLeft = metrics.mBoundingBox.X(); gfxFloat bboxLeft = metrics.mBoundingBox.X();
@ -783,24 +782,24 @@ gfxTextRun::AccumulatePartialLigatureMetrics(gfxFont *aFont,
} }
gfxTextRun::Metrics gfxTextRun::Metrics
gfxTextRun::MeasureText(uint32_t aStart, uint32_t aLength, gfxTextRun::MeasureText(Range aRange,
gfxFont::BoundingBoxType aBoundingBoxType, gfxFont::BoundingBoxType aBoundingBoxType,
DrawTarget* aRefDrawTarget, DrawTarget* aRefDrawTarget,
PropertyProvider *aProvider) PropertyProvider *aProvider)
{ {
NS_ASSERTION(aStart + aLength <= GetLength(), "Substring out of range"); NS_ASSERTION(aRange.end <= GetLength(), "Substring out of range");
Metrics accumulatedMetrics; Metrics accumulatedMetrics;
GlyphRunIterator iter(this, aStart, aLength); GlyphRunIterator iter(this, aRange);
while (iter.NextRun()) { while (iter.NextRun()) {
gfxFont *font = iter.GetGlyphRun()->mFont; gfxFont *font = iter.GetGlyphRun()->mFont;
uint32_t start = iter.GetStringStart(); uint32_t start = iter.GetStringStart();
uint32_t end = iter.GetStringEnd(); uint32_t end = iter.GetStringEnd();
uint32_t ligatureRunStart = start; Range ligatureRange(start, end);
uint32_t ligatureRunEnd = end; ShrinkToLigatureBoundaries(&ligatureRange);
ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
AccumulatePartialLigatureMetrics(font, start, ligatureRunStart, AccumulatePartialLigatureMetrics(
font, Range(start, ligatureRange.start),
aBoundingBoxType, aRefDrawTarget, aProvider, aBoundingBoxType, aRefDrawTarget, aProvider,
iter.GetGlyphRun()->mOrientation, &accumulatedMetrics); iter.GetGlyphRun()->mOrientation, &accumulatedMetrics);
@ -810,11 +809,12 @@ gfxTextRun::MeasureText(uint32_t aStart, uint32_t aLength,
// by getting some ascent/descent from the font and using our stored // by getting some ascent/descent from the font and using our stored
// advance widths. // advance widths.
AccumulateMetricsForRun(font, AccumulateMetricsForRun(font,
ligatureRunStart, ligatureRunEnd, aBoundingBoxType, ligatureRange, aBoundingBoxType,
aRefDrawTarget, aProvider, ligatureRunStart, ligatureRunEnd, aRefDrawTarget, aProvider, ligatureRange,
iter.GetGlyphRun()->mOrientation, &accumulatedMetrics); iter.GetGlyphRun()->mOrientation, &accumulatedMetrics);
AccumulatePartialLigatureMetrics(font, ligatureRunEnd, end, AccumulatePartialLigatureMetrics(
font, Range(ligatureRange.end, end),
aBoundingBoxType, aRefDrawTarget, aProvider, aBoundingBoxType, aRefDrawTarget, aProvider,
iter.GetGlyphRun()->mOrientation, &accumulatedMetrics); iter.GetGlyphRun()->mOrientation, &accumulatedMetrics);
} }
@ -842,13 +842,12 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
NS_ASSERTION(aStart + aMaxLength <= GetLength(), "Substring out of range"); NS_ASSERTION(aStart + aMaxLength <= GetLength(), "Substring out of range");
uint32_t bufferStart = aStart; Range bufferRange(aStart, aStart +
uint32_t bufferLength = std::min<uint32_t>(aMaxLength, MEASUREMENT_BUFFER_SIZE); std::min<uint32_t>(aMaxLength, MEASUREMENT_BUFFER_SIZE));
PropertyProvider::Spacing spacingBuffer[MEASUREMENT_BUFFER_SIZE]; PropertyProvider::Spacing spacingBuffer[MEASUREMENT_BUFFER_SIZE];
bool haveSpacing = aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING) != 0; bool haveSpacing = aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING) != 0;
if (haveSpacing) { if (haveSpacing) {
GetAdjustedSpacing(this, bufferStart, bufferStart + bufferLength, aProvider, GetAdjustedSpacing(this, bufferRange, aProvider, spacingBuffer);
spacingBuffer);
} }
bool hyphenBuffer[MEASUREMENT_BUFFER_SIZE]; bool hyphenBuffer[MEASUREMENT_BUFFER_SIZE];
bool haveHyphenation = aProvider && bool haveHyphenation = aProvider &&
@ -856,8 +855,7 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
(aProvider->GetHyphensOption() == NS_STYLE_HYPHENS_MANUAL && (aProvider->GetHyphensOption() == NS_STYLE_HYPHENS_MANUAL &&
(mFlags & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0)); (mFlags & gfxTextRunFactory::TEXT_ENABLE_HYPHEN_BREAKS) != 0));
if (haveHyphenation) { if (haveHyphenation) {
aProvider->GetHyphenationBreaks(bufferStart, bufferLength, aProvider->GetHyphenationBreaks(bufferRange, hyphenBuffer);
hyphenBuffer);
} }
gfxFloat width = 0; gfxFloat width = 0;
@ -873,23 +871,21 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
uint32_t end = aStart + aMaxLength; uint32_t end = aStart + aMaxLength;
bool lastBreakUsedHyphenation = false; bool lastBreakUsedHyphenation = false;
uint32_t ligatureRunStart = aStart; Range ligatureRange(aStart, end);
uint32_t ligatureRunEnd = end; ShrinkToLigatureBoundaries(&ligatureRange);
ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
uint32_t i; uint32_t i;
for (i = aStart; i < end; ++i) { for (i = aStart; i < end; ++i) {
if (i >= bufferStart + bufferLength) { if (i >= bufferRange.end) {
// Fetch more spacing and hyphenation data // Fetch more spacing and hyphenation data
bufferStart = i; bufferRange.start = i;
bufferLength = std::min(aStart + aMaxLength, i + MEASUREMENT_BUFFER_SIZE) - i; bufferRange.end = std::min(aStart + aMaxLength,
i + MEASUREMENT_BUFFER_SIZE);
if (haveSpacing) { if (haveSpacing) {
GetAdjustedSpacing(this, bufferStart, bufferStart + bufferLength, aProvider, GetAdjustedSpacing(this, bufferRange, aProvider, spacingBuffer);
spacingBuffer);
} }
if (haveHyphenation) { if (haveHyphenation) {
aProvider->GetHyphenationBreaks(bufferStart, bufferLength, aProvider->GetHyphenationBreaks(bufferRange, hyphenBuffer);
hyphenBuffer);
} }
} }
@ -900,8 +896,8 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
if (aSuppressBreak != eSuppressAllBreaks && if (aSuppressBreak != eSuppressAllBreaks &&
(aSuppressBreak != eSuppressInitialBreak || i > aStart)) { (aSuppressBreak != eSuppressInitialBreak || i > aStart)) {
bool atNaturalBreak = mCharacterGlyphs[i].CanBreakBefore() == 1; bool atNaturalBreak = mCharacterGlyphs[i].CanBreakBefore() == 1;
bool atHyphenationBreak = bool atHyphenationBreak = !atNaturalBreak &&
!atNaturalBreak && haveHyphenation && hyphenBuffer[i - bufferStart]; haveHyphenation && hyphenBuffer[i - bufferRange.start];
bool atBreak = atNaturalBreak || atHyphenationBreak; bool atBreak = atNaturalBreak || atHyphenationBreak;
bool wordWrapping = bool wordWrapping =
aCanWordWrap && mCharacterGlyphs[i].IsClusterStart() && aCanWordWrap && mCharacterGlyphs[i].IsClusterStart() &&
@ -934,14 +930,16 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
} }
gfxFloat charAdvance; gfxFloat charAdvance;
if (i >= ligatureRunStart && i < ligatureRunEnd) { if (i >= ligatureRange.start && i < ligatureRange.end) {
charAdvance = GetAdvanceForGlyphs(i, i + 1); charAdvance = GetAdvanceForGlyphs(Range(i, i + 1));
if (haveSpacing) { if (haveSpacing) {
PropertyProvider::Spacing *space = &spacingBuffer[i - bufferStart]; PropertyProvider::Spacing *space =
&spacingBuffer[i - bufferRange.start];
charAdvance += space->mBefore + space->mAfter; charAdvance += space->mBefore + space->mAfter;
} }
} else { } else {
charAdvance = ComputePartialLigatureWidth(i, i + 1, aProvider); charAdvance =
ComputePartialLigatureWidth(Range(i, i + 1), aProvider);
} }
advance += charAdvance; advance += charAdvance;
@ -978,13 +976,13 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
} }
if (aMetrics) { if (aMetrics) {
*aMetrics = MeasureText(aStart, charsFit, aBoundingBoxType, auto fitEnd = aStart + charsFit;
*aMetrics = MeasureText(Range(aStart, fitEnd), aBoundingBoxType,
aRefDrawTarget, aProvider); aRefDrawTarget, aProvider);
if (trimmableChars) { if (trimmableChars) {
Metrics trimMetrics = Metrics trimMetrics =
MeasureText(aStart + charsFit - trimmableChars, MeasureText(Range(fitEnd - trimmableChars, fitEnd),
trimmableChars, aBoundingBoxType, aBoundingBoxType, aRefDrawTarget, aProvider);
aRefDrawTarget, aProvider);
aMetrics->mAdvanceWidth -= trimMetrics.mAdvanceWidth; aMetrics->mAdvanceWidth -= trimMetrics.mAdvanceWidth;
} }
} }
@ -1006,18 +1004,19 @@ gfxTextRun::BreakAndMeasureText(uint32_t aStart, uint32_t aMaxLength,
} }
gfxFloat gfxFloat
gfxTextRun::GetAdvanceWidth(uint32_t aStart, uint32_t aLength, gfxTextRun::GetAdvanceWidth(Range aRange, PropertyProvider *aProvider,
PropertyProvider *aProvider,
PropertyProvider::Spacing* aSpacing) PropertyProvider::Spacing* aSpacing)
{ {
NS_ASSERTION(aStart + aLength <= GetLength(), "Substring out of range"); NS_ASSERTION(aRange.end <= GetLength(), "Substring out of range");
uint32_t ligatureRunStart = aStart; Range ligatureRange = aRange;
uint32_t ligatureRunEnd = aStart + aLength; ShrinkToLigatureBoundaries(&ligatureRange);
ShrinkToLigatureBoundaries(&ligatureRunStart, &ligatureRunEnd);
gfxFloat result = ComputePartialLigatureWidth(aStart, ligatureRunStart, aProvider) + gfxFloat result =
ComputePartialLigatureWidth(ligatureRunEnd, aStart + aLength, aProvider); ComputePartialLigatureWidth(Range(aRange.start, ligatureRange.start),
aProvider) +
ComputePartialLigatureWidth(Range(ligatureRange.end, aRange.end),
aProvider);
if (aSpacing) { if (aSpacing) {
aSpacing->mBefore = aSpacing->mAfter = 0; aSpacing->mBefore = aSpacing->mAfter = 0;
@ -1028,10 +1027,10 @@ gfxTextRun::GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
if (aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING)) { if (aProvider && (mFlags & gfxTextRunFactory::TEXT_ENABLE_SPACING)) {
uint32_t i; uint32_t i;
AutoTArray<PropertyProvider::Spacing,200> spacingBuffer; AutoTArray<PropertyProvider::Spacing,200> spacingBuffer;
if (spacingBuffer.AppendElements(aLength)) { if (spacingBuffer.AppendElements(aRange.Length())) {
GetAdjustedSpacing(this, ligatureRunStart, ligatureRunEnd, aProvider, GetAdjustedSpacing(this, ligatureRange, aProvider,
spacingBuffer.Elements()); spacingBuffer.Elements());
for (i = 0; i < ligatureRunEnd - ligatureRunStart; ++i) { for (i = 0; i < ligatureRange.Length(); ++i) {
PropertyProvider::Spacing *space = &spacingBuffer[i]; PropertyProvider::Spacing *space = &spacingBuffer[i];
result += space->mBefore + space->mAfter; result += space->mBefore + space->mAfter;
} }
@ -1042,11 +1041,11 @@ gfxTextRun::GetAdvanceWidth(uint32_t aStart, uint32_t aLength,
} }
} }
return result + GetAdvanceForGlyphs(ligatureRunStart, ligatureRunEnd); return result + GetAdvanceForGlyphs(ligatureRange);
} }
bool bool
gfxTextRun::SetLineBreaks(uint32_t aStart, uint32_t aLength, gfxTextRun::SetLineBreaks(Range aRange,
bool aLineBreakBefore, bool aLineBreakAfter, bool aLineBreakBefore, bool aLineBreakAfter,
gfxFloat *aAdvanceWidthDelta) gfxFloat *aAdvanceWidthDelta)
{ {
@ -1244,12 +1243,11 @@ gfxTextRun::CopyGlyphDataFrom(gfxShapedWord *aShapedWord, uint32_t aOffset)
} }
void void
gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart, gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, Range aRange, uint32_t aDest)
uint32_t aLength, uint32_t aDest)
{ {
NS_ASSERTION(aStart + aLength <= aSource->GetLength(), NS_ASSERTION(aRange.end <= aSource->GetLength(),
"Source substring out of range"); "Source substring out of range");
NS_ASSERTION(aDest + aLength <= GetLength(), NS_ASSERTION(aDest + aRange.Length() <= GetLength(),
"Destination substring out of range"); "Destination substring out of range");
if (aSource->mSkipDrawing) { if (aSource->mSkipDrawing) {
@ -1257,9 +1255,9 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
} }
// Copy base glyph data, and DetailedGlyph data where present // Copy base glyph data, and DetailedGlyph data where present
const CompressedGlyph *srcGlyphs = aSource->mCharacterGlyphs + aStart; const CompressedGlyph *srcGlyphs = aSource->mCharacterGlyphs + aRange.start;
CompressedGlyph *dstGlyphs = mCharacterGlyphs + aDest; CompressedGlyph *dstGlyphs = mCharacterGlyphs + aDest;
for (uint32_t i = 0; i < aLength; ++i) { for (uint32_t i = 0; i < aRange.Length(); ++i) {
CompressedGlyph g = srcGlyphs[i]; CompressedGlyph g = srcGlyphs[i];
g.SetCanBreakBefore(!g.IsClusterStart() ? g.SetCanBreakBefore(!g.IsClusterStart() ?
CompressedGlyph::FLAG_BREAK_TYPE_NONE : CompressedGlyph::FLAG_BREAK_TYPE_NONE :
@ -1269,7 +1267,8 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
if (count > 0) { if (count > 0) {
DetailedGlyph *dst = AllocateDetailedGlyphs(i + aDest, count); DetailedGlyph *dst = AllocateDetailedGlyphs(i + aDest, count);
if (dst) { if (dst) {
DetailedGlyph *src = aSource->GetDetailedGlyphs(i + aStart); DetailedGlyph *src =
aSource->GetDetailedGlyphs(i + aRange.start);
if (src) { if (src) {
::memcpy(dst, src, count * sizeof(DetailedGlyph)); ::memcpy(dst, src, count * sizeof(DetailedGlyph));
} else { } else {
@ -1284,7 +1283,7 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
} }
// Copy glyph runs // Copy glyph runs
GlyphRunIterator iter(aSource, aStart, aLength); GlyphRunIterator iter(aSource, aRange);
#ifdef DEBUG #ifdef DEBUG
GlyphRun *prevRun = nullptr; GlyphRun *prevRun = nullptr;
#endif #endif
@ -1315,7 +1314,7 @@ gfxTextRun::CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart,
"Ended font run in the middle of a cluster"); "Ended font run in the middle of a cluster");
nsresult rv = AddGlyphRun(font, iter.GetGlyphRun()->mMatchType, nsresult rv = AddGlyphRun(font, iter.GetGlyphRun()->mMatchType,
start - aStart + aDest, false, start - aRange.start + aDest, false,
iter.GetGlyphRun()->mOrientation); iter.GetGlyphRun()->mOrientation);
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return; return;
@ -1495,11 +1494,11 @@ gfxTextRun::ClusterIterator::NextCluster()
return false; return false;
} }
uint32_t gfxTextRun::Range
gfxTextRun::ClusterIterator::ClusterLength() const gfxTextRun::ClusterIterator::ClusterRange() const
{ {
if (mCurrentChar == uint32_t(-1)) { if (mCurrentChar == uint32_t(-1)) {
return 0; return Range(0, 0);
} }
uint32_t i = mCurrentChar, uint32_t i = mCurrentChar,
@ -1510,7 +1509,7 @@ gfxTextRun::ClusterIterator::ClusterLength() const
} }
} }
return i - mCurrentChar; return Range(mCurrentChar, i);
} }
gfxFloat gfxFloat
@ -1520,7 +1519,7 @@ gfxTextRun::ClusterIterator::ClusterAdvance(PropertyProvider *aProvider) const
return 0; return 0;
} }
return mTextRun->GetAdvanceWidth(mCurrentChar, ClusterLength(), aProvider); return mTextRun->GetAdvanceWidth(ClusterRange(), aProvider);
} }
size_t size_t

View File

@ -134,10 +134,23 @@ public:
return mCharacterGlyphs[aPos].CharMayHaveEmphasisMark(); return mCharacterGlyphs[aPos].CharMayHaveEmphasisMark();
} }
// All uint32_t aStart, uint32_t aLength ranges below are restricted to // All offsets are in terms of the string passed into MakeTextRun.
// grapheme cluster boundaries! All offsets are in terms of the string
// passed into MakeTextRun. // Describe range [start, end) of a text run. The range is
// restricted to grapheme cluster boundaries.
struct Range
{
uint32_t start;
uint32_t end;
uint32_t Length() const { return end - start; }
Range() : start(0), end(0) {}
Range(uint32_t aStart, uint32_t aEnd)
: start(aStart), end(aEnd) {}
explicit Range(gfxTextRun* aTextRun)
: start(0), end(aTextRun->GetLength()) {}
};
// All coordinates are in layout/app units // All coordinates are in layout/app units
/** /**
@ -152,8 +165,7 @@ public:
* @return true if this changed the linebreaks, false if the new line * @return true if this changed the linebreaks, false if the new line
* breaks are the same as the old * breaks are the same as the old
*/ */
virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, virtual bool SetPotentialLineBreaks(Range aRange, uint8_t *aBreakBefore);
uint8_t *aBreakBefore);
/** /**
* Layout provides PropertyProvider objects. These allow detection of * Layout provides PropertyProvider objects. These allow detection of
@ -169,8 +181,7 @@ public:
public: public:
// Detect hyphenation break opportunities in the given range; breaks // Detect hyphenation break opportunities in the given range; breaks
// not at cluster boundaries will be ignored. // not at cluster boundaries will be ignored.
virtual void GetHyphenationBreaks(uint32_t aStart, uint32_t aLength, virtual void GetHyphenationBreaks(Range aRange, bool *aBreakBefore) = 0;
bool *aBreakBefore) = 0;
// Returns the provider's hyphenation setting, so callers can decide // Returns the provider's hyphenation setting, so callers can decide
// whether it is necessary to call GetHyphenationBreaks. // whether it is necessary to call GetHyphenationBreaks.
@ -189,8 +200,7 @@ public:
* CLUSTER_START, then character i-1 must have zero after-spacing and * CLUSTER_START, then character i-1 must have zero after-spacing and
* character i must have zero before-spacing. * character i must have zero before-spacing.
*/ */
virtual void GetSpacing(uint32_t aStart, uint32_t aLength, virtual void GetSpacing(Range aRange, Spacing *aSpacing) = 0;
Spacing *aSpacing) = 0;
// Returns a gfxContext that can be used to measure the hyphen glyph. // Returns a gfxContext that can be used to measure the hyphen glyph.
// Only called if the hyphen width is requested. // Only called if the hyphen width is requested.
@ -213,7 +223,7 @@ public:
return mCurrentChar; return mCurrentChar;
} }
uint32_t ClusterLength() const; Range ClusterRange() const;
gfxFloat ClusterAdvance(PropertyProvider *aProvider) const; gfxFloat ClusterAdvance(PropertyProvider *aProvider) const;
@ -230,22 +240,21 @@ public:
* is returned here. * is returned here.
* *
* Drawing should respect advance widths in the sense that for LTR runs, * Drawing should respect advance widths in the sense that for LTR runs,
* Draw(ctx, pt, offset1, length1, dirty, &provider, &advance) followed by * Draw(ctx, pt, Range(start, middle), dirty, &provider, &advance) followed by
* Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1 + length1, length2, * Draw(ctx, gfxPoint(pt.x + advance, pt.y), Range(middle, end),
* dirty, &provider, nullptr) should have the same effect as * dirty, &provider, nullptr) should have the same effect as
* Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nullptr). * Draw(ctx, pt, Range(start, end), dirty, &provider, nullptr).
* For RTL runs the rule is: * For RTL runs the rule is:
* Draw(ctx, pt, offset1 + length1, length2, dirty, &provider, &advance) followed by * Draw(ctx, pt, Range(middle, end), dirty, &provider, &advance) followed by
* Draw(ctx, gfxPoint(pt.x + advance, pt.y), offset1, length1, * Draw(ctx, gfxPoint(pt.x + advance, pt.y), Range(start, middle),
* dirty, &provider, nullptr) should have the same effect as * dirty, &provider, nullptr) should have the same effect as
* Draw(ctx, pt, offset1, length1+length2, dirty, &provider, nullptr). * Draw(ctx, pt, Range(start, end), dirty, &provider, nullptr).
* *
* Glyphs should be drawn in logical content order, which can be significant * Glyphs should be drawn in logical content order, which can be significant
* if they overlap (perhaps due to negative spacing). * if they overlap (perhaps due to negative spacing).
*/ */
void Draw(gfxContext *aContext, gfxPoint aPt, void Draw(gfxContext *aContext, gfxPoint aPt,
DrawMode aDrawMode, DrawMode aDrawMode, Range aRange,
uint32_t aStart, uint32_t aLength,
PropertyProvider *aProvider, PropertyProvider *aProvider,
gfxFloat *aAdvanceWidth, gfxTextContextPaint *aContextPaint, gfxFloat *aAdvanceWidth, gfxTextContextPaint *aContextPaint,
gfxTextRunDrawCallbacks *aCallbacks = nullptr); gfxTextRunDrawCallbacks *aCallbacks = nullptr);
@ -257,15 +266,14 @@ public:
*/ */
void DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark, void DrawEmphasisMarks(gfxContext* aContext, gfxTextRun* aMark,
gfxFloat aMarkAdvance, gfxPoint aPt, gfxFloat aMarkAdvance, gfxPoint aPt,
uint32_t aStart, uint32_t aLength, Range aRange, PropertyProvider* aProvider);
PropertyProvider* aProvider);
/** /**
* Computes the ReflowMetrics for a substring. * Computes the ReflowMetrics for a substring.
* Uses GetSpacing from aBreakProvider. * Uses GetSpacing from aBreakProvider.
* @param aBoundingBoxType which kind of bounding box (loose/tight) * @param aBoundingBoxType which kind of bounding box (loose/tight)
*/ */
Metrics MeasureText(uint32_t aStart, uint32_t aLength, Metrics MeasureText(Range aRange,
gfxFont::BoundingBoxType aBoundingBoxType, gfxFont::BoundingBoxType aBoundingBoxType,
DrawTarget* aDrawTargetForTightBoundingBox, DrawTarget* aDrawTargetForTightBoundingBox,
PropertyProvider* aProvider); PropertyProvider* aProvider);
@ -273,7 +281,7 @@ public:
Metrics MeasureText(gfxFont::BoundingBoxType aBoundingBoxType, Metrics MeasureText(gfxFont::BoundingBoxType aBoundingBoxType,
DrawTarget* aDrawTargetForTightBoundingBox, DrawTarget* aDrawTargetForTightBoundingBox,
PropertyProvider* aProvider = nullptr) { PropertyProvider* aProvider = nullptr) {
return MeasureText(0, GetLength(), aBoundingBoxType, return MeasureText(Range(this), aBoundingBoxType,
aDrawTargetForTightBoundingBox, aProvider); aDrawTargetForTightBoundingBox, aProvider);
} }
@ -284,17 +292,16 @@ public:
* the substring would be returned in it. NOTE: the spacing is * the substring would be returned in it. NOTE: the spacing is
* included in the advance width. * included in the advance width.
*/ */
gfxFloat GetAdvanceWidth(uint32_t aStart, uint32_t aLength, gfxFloat GetAdvanceWidth(Range aRange, PropertyProvider *aProvider,
PropertyProvider *aProvider,
PropertyProvider::Spacing* aSpacing = nullptr); PropertyProvider::Spacing* aSpacing = nullptr);
gfxFloat GetAdvanceWidth() { gfxFloat GetAdvanceWidth() {
return GetAdvanceWidth(0, GetLength(), nullptr); return GetAdvanceWidth(Range(this), nullptr);
} }
/** /**
* Clear all stored line breaks for the given range (both before and after), * Clear all stored line breaks for the given range (both before and after),
* and then set the line-break state before aStart to aBreakBefore and * and then set the line-break state before aRange.start to aBreakBefore and
* after the last cluster to aBreakAfter. * after the last cluster to aBreakAfter.
* *
* We require that before and after line breaks be consistent. For clusters * We require that before and after line breaks be consistent. For clusters
@ -319,9 +326,9 @@ public:
* @param aAdvanceWidthDelta if non-null, returns the change in advance * @param aAdvanceWidthDelta if non-null, returns the change in advance
* width of the given range. * width of the given range.
*/ */
virtual bool SetLineBreaks(uint32_t aStart, uint32_t aLength, virtual bool SetLineBreaks(Range aRange,
bool aLineBreakBefore, bool aLineBreakAfter, bool aLineBreakBefore, bool aLineBreakAfter,
gfxFloat* aAdvanceWidthDelta); gfxFloat* aAdvanceWidthDelta);
enum SuppressBreak { enum SuppressBreak {
eNoSuppressBreak, eNoSuppressBreak,
@ -434,9 +441,11 @@ public:
class GlyphRunIterator { class GlyphRunIterator {
public: public:
GlyphRunIterator(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aLength) GlyphRunIterator(gfxTextRun *aTextRun, Range aRange)
: mTextRun(aTextRun), mStartOffset(aStart), mEndOffset(aStart + aLength) { : mTextRun(aTextRun)
mNextIndex = mTextRun->FindFirstGlyphRunContaining(aStart); , mStartOffset(aRange.start)
, mEndOffset(aRange.end) {
mNextIndex = mTextRun->FindFirstGlyphRunContaining(aRange.start);
} }
bool NextRun(); bool NextRun();
GlyphRun *GetGlyphRun() { return mGlyphRun; } GlyphRun *GetGlyphRun() { return mGlyphRun; }
@ -557,8 +566,7 @@ public:
// Copy glyph data for a range of characters from aSource to this // Copy glyph data for a range of characters from aSource to this
// textrun. // textrun.
void CopyGlyphDataFrom(gfxTextRun *aSource, uint32_t aStart, void CopyGlyphDataFrom(gfxTextRun *aSource, Range aRange, uint32_t aDest);
uint32_t aLength, uint32_t aDest);
nsExpirationState *GetExpirationState() { return &mExpirationState; } nsExpirationState *GetExpirationState() { return &mExpirationState; }
@ -571,9 +579,8 @@ public:
void ReleaseFontGroup(); void ReleaseFontGroup();
struct LigatureData { struct LigatureData {
// textrun offsets of the start and end of the containing ligature // textrun range of the containing ligature
uint32_t mLigatureStart; Range mRange;
uint32_t mLigatureEnd;
// appunits advance to the start of the ligature part within the ligature; // appunits advance to the start of the ligature part within the ligature;
// never includes any spacing // never includes any spacing
gfxFloat mPartAdvance; gfxFloat mPartAdvance;
@ -669,16 +676,15 @@ private:
// **** general helpers **** // **** general helpers ****
// Get the total advance for a range of glyphs. // Get the total advance for a range of glyphs.
int32_t GetAdvanceForGlyphs(uint32_t aStart, uint32_t aEnd); int32_t GetAdvanceForGlyphs(Range aRange);
// Spacing for characters outside the range aSpacingStart/aSpacingEnd // Spacing for characters outside the range aSpacingStart/aSpacingEnd
// is assumed to be zero; such characters are not passed to aProvider. // is assumed to be zero; such characters are not passed to aProvider.
// This is useful to protect aProvider from being passed character indices // This is useful to protect aProvider from being passed character indices
// it is not currently able to handle. // it is not currently able to handle.
bool GetAdjustedSpacingArray(uint32_t aStart, uint32_t aEnd, bool GetAdjustedSpacingArray(Range aRange, PropertyProvider *aProvider,
PropertyProvider *aProvider, Range aSpacingRange,
uint32_t aSpacingStart, uint32_t aSpacingEnd, nsTArray<PropertyProvider::Spacing> *aSpacing);
nsTArray<PropertyProvider::Spacing> *aSpacing);
CompressedGlyph& EnsureComplexGlyph(uint32_t aIndex) CompressedGlyph& EnsureComplexGlyph(uint32_t aIndex)
{ {
@ -691,20 +697,20 @@ private:
// to handle requests that begin or end inside a ligature) // to handle requests that begin or end inside a ligature)
// if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero // if aProvider is null then mBeforeSpacing and mAfterSpacing are set to zero
LigatureData ComputeLigatureData(uint32_t aPartStart, uint32_t aPartEnd, LigatureData ComputeLigatureData(Range aPartRange,
PropertyProvider *aProvider); PropertyProvider *aProvider);
gfxFloat ComputePartialLigatureWidth(uint32_t aPartStart, uint32_t aPartEnd, gfxFloat ComputePartialLigatureWidth(Range aPartRange,
PropertyProvider *aProvider); PropertyProvider *aProvider);
void DrawPartialLigature(gfxFont *aFont, uint32_t aStart, uint32_t aEnd, void DrawPartialLigature(gfxFont *aFont, Range aRange,
gfxPoint *aPt, PropertyProvider *aProvider, gfxPoint *aPt, PropertyProvider *aProvider,
TextRunDrawParams& aParams, uint16_t aOrientation); TextRunDrawParams& aParams, uint16_t aOrientation);
// Advance aStart to the start of the nearest ligature; back up aEnd // Advance aRange.start to the start of the nearest ligature, back
// to the nearest ligature end; may result in *aStart == *aEnd // up aRange.end to the nearest ligature end; may result in
void ShrinkToLigatureBoundaries(uint32_t *aStart, uint32_t *aEnd); // aRange->start == aRange->end.
void ShrinkToLigatureBoundaries(Range* aRange);
// result in appunits // result in appunits
gfxFloat GetPartialLigatureWidth(uint32_t aStart, uint32_t aEnd, PropertyProvider *aProvider); gfxFloat GetPartialLigatureWidth(Range aRange, PropertyProvider *aProvider);
void AccumulatePartialLigatureMetrics(gfxFont *aFont, void AccumulatePartialLigatureMetrics(gfxFont *aFont, Range aRange,
uint32_t aStart, uint32_t aEnd,
gfxFont::BoundingBoxType aBoundingBoxType, gfxFont::BoundingBoxType aBoundingBoxType,
DrawTarget* aRefDrawTarget, DrawTarget* aRefDrawTarget,
PropertyProvider *aProvider, PropertyProvider *aProvider,
@ -712,18 +718,17 @@ private:
Metrics *aMetrics); Metrics *aMetrics);
// **** measurement helper **** // **** measurement helper ****
void AccumulateMetricsForRun(gfxFont *aFont, uint32_t aStart, uint32_t aEnd, void AccumulateMetricsForRun(gfxFont *aFont, Range aRange,
gfxFont::BoundingBoxType aBoundingBoxType, gfxFont::BoundingBoxType aBoundingBoxType,
DrawTarget* aRefDrawTarget, DrawTarget* aRefDrawTarget,
PropertyProvider *aProvider, PropertyProvider *aProvider,
uint32_t aSpacingStart, uint32_t aSpacingEnd, Range aSpacingRange,
uint16_t aOrientation, uint16_t aOrientation,
Metrics *aMetrics); Metrics *aMetrics);
// **** drawing helper **** // **** drawing helper ****
void DrawGlyphs(gfxFont *aFont, uint32_t aStart, uint32_t aEnd, void DrawGlyphs(gfxFont *aFont, Range aRange, gfxPoint *aPt,
gfxPoint *aPt, PropertyProvider *aProvider, PropertyProvider *aProvider, Range aSpacingRange,
uint32_t aSpacingStart, uint32_t aSpacingEnd,
TextRunDrawParams& aParams, uint16_t aOrientation); TextRunDrawParams& aParams, uint16_t aOrientation);
// XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*, // XXX this should be changed to a GlyphRun plus a maybe-null GlyphRun*,

View File

@ -773,12 +773,15 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
} }
if (!child) if (!child)
return; return;
typedef gfxTextRun::Range Range;
// Copy potential linebreaks into child so they're preserved // Copy potential linebreaks into child so they're preserved
// (and also child will be shaped appropriately) // (and also child will be shaped appropriately)
NS_ASSERTION(convertedString.Length() == canBreakBeforeArray.Length(), NS_ASSERTION(convertedString.Length() == canBreakBeforeArray.Length(),
"Dropped characters or break-before values somewhere!"); "Dropped characters or break-before values somewhere!");
child->SetPotentialLineBreaks(0, canBreakBeforeArray.Length(), Range range(0, uint32_t(canBreakBeforeArray.Length()));
canBreakBeforeArray.Elements()); child->SetPotentialLineBreaks(range, canBreakBeforeArray.Elements());
if (transformedChild) { if (transformedChild) {
transformedChild->FinishSettingProperties(aRefDrawTarget, aMFR); transformedChild->FinishSettingProperties(aRefDrawTarget, aMFR);
} }
@ -796,6 +799,6 @@ MathMLTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
// We can't steal the data because the child may be cached and stealing // We can't steal the data because the child may be cached and stealing
// the data would break the cache. // the data would break the cache.
aTextRun->ResetGlyphRuns(); aTextRun->ResetGlyphRuns();
aTextRun->CopyGlyphDataFrom(child, 0, child->GetLength(), 0); aTextRun->CopyGlyphDataFrom(child, Range(child), 0);
} }
} }

View File

@ -253,7 +253,7 @@ nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
"Ellipsis textruns should always be LTR!"); "Ellipsis textruns should always be LTR!");
gfxPoint gfxPt(pt.x, pt.y); gfxPoint gfxPt(pt.x, pt.y);
textRun->Draw(aCtx->ThebesContext(), gfxPt, DrawMode::GLYPH_FILL, textRun->Draw(aCtx->ThebesContext(), gfxPt, DrawMode::GLYPH_FILL,
0, textRun->GetLength(), nullptr, nullptr, nullptr); gfxTextRun::Range(textRun), nullptr, nullptr, nullptr);
} }
} else { } else {
RefPtr<nsFontMetrics> fm; RefPtr<nsFontMetrics> fm;

File diff suppressed because it is too large Load Diff

View File

@ -45,6 +45,7 @@ class nsTextFrame : public nsTextFrameBase {
typedef mozilla::gfx::Point Point; typedef mozilla::gfx::Point Point;
typedef mozilla::gfx::Rect Rect; typedef mozilla::gfx::Rect Rect;
typedef mozilla::gfx::Size Size; typedef mozilla::gfx::Size Size;
typedef gfxTextRun::Range Range;
public: public:
NS_DECL_QUERYFRAME_TARGET(nsTextFrame) NS_DECL_QUERYFRAME_TARGET(nsTextFrame)
@ -406,8 +407,7 @@ public:
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
const gfxRect& aDirtyRect, const gfxRect& aDirtyRect,
PropertyProvider& aProvider, PropertyProvider& aProvider,
uint32_t aContentOffset, Range aRange,
uint32_t aContentLength,
nsTextPaintStyle& aTextPaintStyle, nsTextPaintStyle& aTextPaintStyle,
const nsCharClipDisplayItem::ClipEdges& aClipEdges, const nsCharClipDisplayItem::ClipEdges& aClipEdges,
gfxTextContextPaint* aContextPaint, gfxTextContextPaint* aContextPaint,
@ -422,8 +422,7 @@ public:
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
const gfxRect& aDirtyRect, const gfxRect& aDirtyRect,
PropertyProvider& aProvider, PropertyProvider& aProvider,
uint32_t aContentOffset, Range aContentRange,
uint32_t aContentLength,
nsTextPaintStyle& aTextPaintStyle, nsTextPaintStyle& aTextPaintStyle,
SelectionDetails* aDetails, SelectionDetails* aDetails,
SelectionType* aAllTypes, SelectionType* aAllTypes,
@ -435,8 +434,7 @@ public:
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
const gfxRect& aDirtyRect, const gfxRect& aDirtyRect,
PropertyProvider& aProvider, PropertyProvider& aProvider,
uint32_t aContentOffset, Range aContentRange,
uint32_t aContentLength,
nsTextPaintStyle& aTextPaintStyle, nsTextPaintStyle& aTextPaintStyle,
SelectionDetails* aDetails, SelectionDetails* aDetails,
SelectionType aSelectionType, SelectionType aSelectionType,
@ -445,7 +443,7 @@ public:
void DrawEmphasisMarks(gfxContext* aContext, void DrawEmphasisMarks(gfxContext* aContext,
mozilla::WritingMode aWM, mozilla::WritingMode aWM,
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
uint32_t aOffset, uint32_t aLength, Range aRange,
const nscolor* aDecorationOverrideColor, const nscolor* aDecorationOverrideColor,
PropertyProvider& aProvider); PropertyProvider& aProvider);
@ -598,8 +596,7 @@ protected:
nsRect UpdateTextEmphasis(mozilla::WritingMode aWM, nsRect UpdateTextEmphasis(mozilla::WritingMode aWM,
PropertyProvider& aProvider); PropertyProvider& aProvider);
void PaintOneShadow(uint32_t aOffset, void PaintOneShadow(Range aRange,
uint32_t aLength,
nsCSSShadowItem* aShadowDetails, nsCSSShadowItem* aShadowDetails,
PropertyProvider* aProvider, PropertyProvider* aProvider,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
@ -613,7 +610,7 @@ protected:
uint32_t aBlurFlags); uint32_t aBlurFlags);
void PaintShadows(nsCSSShadowArray* aShadow, void PaintShadows(nsCSSShadowArray* aShadow,
uint32_t aOffset, uint32_t aLength, Range aRange,
const nsRect& aDirtyRect, const nsRect& aDirtyRect,
const gfxPoint& aFramePt, const gfxPoint& aFramePt,
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
@ -699,8 +696,7 @@ protected:
void DrawTextRun(gfxContext* const aCtx, void DrawTextRun(gfxContext* const aCtx,
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
uint32_t aOffset, Range aRange,
uint32_t aLength,
PropertyProvider& aProvider, PropertyProvider& aProvider,
nscolor aTextColor, nscolor aTextColor,
gfxFloat& aAdvanceWidth, gfxFloat& aAdvanceWidth,
@ -712,8 +708,7 @@ protected:
const gfxRect& aDirtyRect, const gfxRect& aDirtyRect,
const gfxPoint& aFramePt, const gfxPoint& aFramePt,
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
uint32_t aOffset, Range aRange,
uint32_t aLength,
PropertyProvider& aProvider, PropertyProvider& aProvider,
const nsTextPaintStyle& aTextStyle, const nsTextPaintStyle& aTextStyle,
nscolor aTextColor, nscolor aTextColor,
@ -729,8 +724,7 @@ protected:
const gfxRect& aDirtyRect, const gfxRect& aDirtyRect,
const gfxPoint& aFramePt, const gfxPoint& aFramePt,
const gfxPoint& aTextBaselinePt, const gfxPoint& aTextBaselinePt,
uint32_t aOffset, Range aRange,
uint32_t aLength,
PropertyProvider& aProvider, PropertyProvider& aProvider,
const nsTextPaintStyle& aTextStyle, const nsTextPaintStyle& aTextStyle,
nscolor aTextColor, nscolor aTextColor,

View File

@ -69,11 +69,11 @@ nsTransformedTextRun::SetCapitalization(uint32_t aStart, uint32_t aLength,
} }
bool bool
nsTransformedTextRun::SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, nsTransformedTextRun::SetPotentialLineBreaks(Range aRange,
uint8_t* aBreakBefore) uint8_t* aBreakBefore)
{ {
bool changed = bool changed =
gfxTextRun::SetPotentialLineBreaks(aStart, aLength, aBreakBefore); gfxTextRun::SetPotentialLineBreaks(aRange, aBreakBefore);
if (changed) { if (changed) {
mNeedsRebuild = true; mNeedsRebuild = true;
} }
@ -131,7 +131,7 @@ MergeCharactersInTextRun(gfxTextRun* aDest, gfxTextRun* aSrc,
{ {
aDest->ResetGlyphRuns(); aDest->ResetGlyphRuns();
gfxTextRun::GlyphRunIterator iter(aSrc, 0, aSrc->GetLength()); gfxTextRun::GlyphRunIterator iter(aSrc, gfxTextRun::Range(aSrc));
uint32_t offset = 0; uint32_t offset = 0;
AutoTArray<gfxTextRun::DetailedGlyph,2> glyphs; AutoTArray<gfxTextRun::DetailedGlyph,2> glyphs;
while (iter.NextRun()) { while (iter.NextRun()) {
@ -646,8 +646,8 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
// (and also child will be shaped appropriately) // (and also child will be shaped appropriately)
NS_ASSERTION(convertedString.Length() == canBreakBeforeArray.Length(), NS_ASSERTION(convertedString.Length() == canBreakBeforeArray.Length(),
"Dropped characters or break-before values somewhere!"); "Dropped characters or break-before values somewhere!");
child->SetPotentialLineBreaks(0, canBreakBeforeArray.Length(), gfxTextRun::Range range(0, uint32_t(canBreakBeforeArray.Length()));
canBreakBeforeArray.Elements()); child->SetPotentialLineBreaks(range, canBreakBeforeArray.Elements());
if (transformedChild) { if (transformedChild) {
transformedChild->FinishSettingProperties(aRefDrawTarget, aMFR); transformedChild->FinishSettingProperties(aRefDrawTarget, aMFR);
} }
@ -666,6 +666,6 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
// We can't steal the data because the child may be cached and stealing // We can't steal the data because the child may be cached and stealing
// the data would break the cache. // the data would break the cache.
aTextRun->ResetGlyphRuns(); aTextRun->ResetGlyphRuns();
aTextRun->CopyGlyphDataFrom(child, 0, child->GetLength(), 0); aTextRun->CopyGlyphDataFrom(child, gfxTextRun::Range(child), 0);
} }
} }

View File

@ -130,8 +130,7 @@ public:
void SetCapitalization(uint32_t aStart, uint32_t aLength, void SetCapitalization(uint32_t aStart, uint32_t aLength,
bool* aCapitalization); bool* aCapitalization);
virtual bool SetPotentialLineBreaks(uint32_t aStart, uint32_t aLength, virtual bool SetPotentialLineBreaks(Range aRange, uint8_t* aBreakBefore);
uint8_t* aBreakBefore);
/** /**
* Called after SetCapitalization and SetPotentialLineBreaks * Called after SetCapitalization and SetPotentialLineBreaks
* are done and before we request any data from the textrun. Also always * are done and before we request any data from the textrun. Also always

View File

@ -60,7 +60,8 @@ nsresult
nsFontFaceList::AddFontsFromTextRun(gfxTextRun* aTextRun, nsFontFaceList::AddFontsFromTextRun(gfxTextRun* aTextRun,
uint32_t aOffset, uint32_t aLength) uint32_t aOffset, uint32_t aLength)
{ {
gfxTextRun::GlyphRunIterator iter(aTextRun, aOffset, aLength); gfxTextRun::Range range(aOffset, aOffset + aLength);
gfxTextRun::GlyphRunIterator iter(aTextRun, range);
while (iter.NextRun()) { while (iter.NextRun()) {
gfxFontEntry *fe = iter.GetGlyphRun()->mFont->GetFontEntry(); gfxFontEntry *fe = iter.GetGlyphRun()->mFont->GetFontEntry();
// if we have already listed this face, just make sure the match type is // if we have already listed this face, just make sure the match type is

View File

@ -2147,7 +2147,7 @@ nsMathMLChar::PaintForeground(nsPresContext* aPresContext,
// XXXfredw verify if mGlyphs[0] is non-null to workaround bug 973322. // XXXfredw verify if mGlyphs[0] is non-null to workaround bug 973322.
if (mGlyphs[0]) { if (mGlyphs[0]) {
mGlyphs[0]->Draw(thebesContext, gfxPoint(0.0, mUnscaledAscent), mGlyphs[0]->Draw(thebesContext, gfxPoint(0.0, mUnscaledAscent),
DrawMode::GLYPH_FILL, 0, mGlyphs[0]->GetLength(), DrawMode::GLYPH_FILL, Range(mGlyphs[0]),
nullptr, nullptr, nullptr); nullptr, nullptr, nullptr);
} }
break; break;
@ -2304,7 +2304,7 @@ nsMathMLChar::PaintVertically(nsPresContext* aPresContext,
if (!clipRect.IsEmpty()) { if (!clipRect.IsEmpty()) {
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect); AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
mGlyphs[i]->Draw(aThebesContext, gfxPoint(dx, dy), mGlyphs[i]->Draw(aThebesContext, gfxPoint(dx, dy),
DrawMode::GLYPH_FILL, 0, mGlyphs[i]->GetLength(), DrawMode::GLYPH_FILL, Range(mGlyphs[i]),
nullptr, nullptr, nullptr); nullptr, nullptr, nullptr);
} }
} }
@ -2372,7 +2372,7 @@ nsMathMLChar::PaintVertically(nsPresContext* aPresContext,
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect); AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
dy += bm.ascent; dy += bm.ascent;
mGlyphs[3]->Draw(aThebesContext, gfxPoint(dx, dy), mGlyphs[3]->Draw(aThebesContext, gfxPoint(dx, dy),
DrawMode::GLYPH_FILL, 0, mGlyphs[3]->GetLength(), DrawMode::GLYPH_FILL, Range(mGlyphs[3]),
nullptr, nullptr, nullptr); nullptr, nullptr, nullptr);
dy += bm.descent; dy += bm.descent;
} }
@ -2476,7 +2476,7 @@ nsMathMLChar::PaintHorizontally(nsPresContext* aPresContext,
if (!clipRect.IsEmpty()) { if (!clipRect.IsEmpty()) {
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect); AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
mGlyphs[i]->Draw(aThebesContext, gfxPoint(dx, dy), mGlyphs[i]->Draw(aThebesContext, gfxPoint(dx, dy),
DrawMode::GLYPH_FILL, 0, mGlyphs[i]->GetLength(), DrawMode::GLYPH_FILL, Range(mGlyphs[i]),
nullptr, nullptr, nullptr); nullptr, nullptr, nullptr);
} }
} }
@ -2542,7 +2542,7 @@ nsMathMLChar::PaintHorizontally(nsPresContext* aPresContext,
AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect); AutoPushClipRect clip(aThebesContext, oneDevPixel, clipRect);
dx -= bm.leftBearing; dx -= bm.leftBearing;
mGlyphs[3]->Draw(aThebesContext, gfxPoint(dx, dy), mGlyphs[3]->Draw(aThebesContext, gfxPoint(dx, dy),
DrawMode::GLYPH_FILL, 0, mGlyphs[3]->GetLength(), DrawMode::GLYPH_FILL, Range(mGlyphs[3]),
nullptr, nullptr, nullptr); nullptr, nullptr, nullptr);
dx += bm.rightBearing; dx += bm.rightBearing;
} }

View File

@ -13,7 +13,7 @@
#include "nsRect.h" #include "nsRect.h"
#include "nsString.h" #include "nsString.h"
#include "nsBoundingMetrics.h" #include "nsBoundingMetrics.h"
#include "gfxFont.h" #include "gfxTextRun.h"
class nsGlyphTable; class nsGlyphTable;
class nsIFrame; class nsIFrame;
@ -85,6 +85,7 @@ struct nsGlyphCode {
class nsMathMLChar class nsMathMLChar
{ {
public: public:
typedef gfxTextRun::Range Range;
typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::DrawTarget DrawTarget;
// constructor and destructor // constructor and destructor

View File

@ -60,34 +60,16 @@ using namespace mozilla::gfx;
* in original char indexes to skipped char indexes. * in original char indexes to skipped char indexes.
* *
* @param aIterator The gfxSkipCharsIterator to use for the conversion. * @param aIterator The gfxSkipCharsIterator to use for the conversion.
* @param aOriginalOffset The original offset (input). * @param aOriginalOffset The original offset.
* @param aOriginalLength The original length (input). * @param aOriginalLength The original length.
* @param aSkippedOffset The skipped offset (output).
* @param aSkippedLength The skipped length (output).
*/ */
static void static gfxTextRun::Range
ConvertOriginalToSkipped(gfxSkipCharsIterator& aIterator, ConvertOriginalToSkipped(gfxSkipCharsIterator& aIterator,
uint32_t aOriginalOffset, uint32_t aOriginalLength, uint32_t aOriginalOffset, uint32_t aOriginalLength)
uint32_t& aSkippedOffset, uint32_t& aSkippedLength)
{ {
aSkippedOffset = aIterator.ConvertOriginalToSkipped(aOriginalOffset); uint32_t start = aIterator.ConvertOriginalToSkipped(aOriginalOffset);
aIterator.AdvanceOriginal(aOriginalLength); aIterator.AdvanceOriginal(aOriginalLength);
aSkippedLength = aIterator.GetSkippedOffset() - aSkippedOffset; return gfxTextRun::Range(start, aIterator.GetSkippedOffset());
}
/**
* Using the specified gfxSkipCharsIterator, converts an offset and length
* in original char indexes to skipped char indexes in place.
*
* @param aIterator The gfxSkipCharsIterator to use for the conversion.
* @param aOriginalOffset The offset to convert from original to skipped.
* @param aOriginalLength The length to convert from original to skipped.
*/
static void
ConvertOriginalToSkipped(gfxSkipCharsIterator& aIterator,
uint32_t& aOffset, uint32_t& aLength)
{
ConvertOriginalToSkipped(aIterator, aOffset, aLength, aOffset, aLength);
} }
/** /**
@ -157,15 +139,11 @@ GetAscentAndDescentInAppUnits(nsTextFrame* aFrame,
gfxSkipCharsIterator it = aFrame->EnsureTextRun(nsTextFrame::eInflated); gfxSkipCharsIterator it = aFrame->EnsureTextRun(nsTextFrame::eInflated);
gfxTextRun* textRun = aFrame->GetTextRun(nsTextFrame::eInflated); gfxTextRun* textRun = aFrame->GetTextRun(nsTextFrame::eInflated);
uint32_t offset, length; gfxTextRun::Range range = ConvertOriginalToSkipped(
ConvertOriginalToSkipped(it, it, aFrame->GetContentOffset(), aFrame->GetContentLength());
aFrame->GetContentOffset(),
aFrame->GetContentLength(),
offset, length);
gfxTextRun::Metrics metrics = gfxTextRun::Metrics metrics =
textRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS, nullptr, textRun->MeasureText(range, gfxFont::LOOSE_INK_EXTENTS, nullptr, nullptr);
nullptr);
aAscent = metrics.mAscent; aAscent = metrics.mAscent;
aDescent = metrics.mDescent; aDescent = metrics.mDescent;
@ -385,7 +363,7 @@ GetBaselinePosition(nsTextFrame* aFrame,
} }
/** /**
* For a given text run, returns the number of skipped characters that comprise * For a given text run, returns the range of skipped characters that comprise
* the ligature group and/or cluster that includes the character represented * the ligature group and/or cluster that includes the character represented
* by the specified gfxSkipCharsIterator. * by the specified gfxSkipCharsIterator.
* *
@ -394,8 +372,8 @@ GetBaselinePosition(nsTextFrame* aFrame,
* @param aIterator The gfxSkipCharsIterator to use for the current position * @param aIterator The gfxSkipCharsIterator to use for the current position
* in the text run. * in the text run.
*/ */
static uint32_t static gfxTextRun::Range
ClusterLength(gfxTextRun* aTextRun, const gfxSkipCharsIterator& aIterator) ClusterRange(gfxTextRun* aTextRun, const gfxSkipCharsIterator& aIterator)
{ {
uint32_t start = aIterator.GetSkippedOffset(); uint32_t start = aIterator.GetSkippedOffset();
uint32_t end = start + 1; uint32_t end = start + 1;
@ -404,7 +382,7 @@ ClusterLength(gfxTextRun* aTextRun, const gfxSkipCharsIterator& aIterator)
!aTextRun->IsClusterStart(end))) { !aTextRun->IsClusterStart(end))) {
end++; end++;
} }
return end - start; return gfxTextRun::Range(start, end);
} }
/** /**
@ -481,6 +459,8 @@ namespace mozilla {
*/ */
struct TextRenderedRun struct TextRenderedRun
{ {
typedef gfxTextRun::Range Range;
/** /**
* Constructs a TextRenderedRun that is uninitialized except for mFrame * Constructs a TextRenderedRun that is uninitialized except for mFrame
* being null. * being null.
@ -938,17 +918,15 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
gfxTextRun* textRun = mFrame->GetTextRun(nsTextFrame::eInflated); gfxTextRun* textRun = mFrame->GetTextRun(nsTextFrame::eInflated);
// Get the content range for this rendered run. // Get the content range for this rendered run.
uint32_t offset, length; Range range = ConvertOriginalToSkipped(it, mTextFrameContentOffset,
ConvertOriginalToSkipped(it, mTextFrameContentOffset, mTextFrameContentLength, mTextFrameContentLength);
offset, length); if (range.Length() == 0) {
if (length == 0) {
return r; return r;
} }
// Measure that range. // Measure that range.
gfxTextRun::Metrics metrics = gfxTextRun::Metrics metrics =
textRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS, textRun->MeasureText(range, gfxFont::LOOSE_INK_EXTENTS, nullptr, nullptr);
nullptr, nullptr);
// Make sure it includes the font-box. // Make sure it includes the font-box.
gfxRect fontBox(0, -metrics.mAscent, gfxRect fontBox(0, -metrics.mAscent,
metrics.mAdvanceWidth, metrics.mAscent + metrics.mDescent); metrics.mAdvanceWidth, metrics.mAscent + metrics.mDescent);
@ -961,7 +939,7 @@ TextRenderedRun::GetRunUserSpaceRect(nsPresContext* aContext,
gfxFloat x, width; gfxFloat x, width;
if (aFlags & eNoHorizontalOverflow) { if (aFlags & eNoHorizontalOverflow) {
x = 0.0; x = 0.0;
width = textRun->GetAdvanceWidth(offset, length, nullptr); width = textRun->GetAdvanceWidth(range, nullptr);
} else { } else {
x = metrics.mBoundingBox.x; x = metrics.mBoundingBox.x;
width = metrics.mBoundingBox.width; width = metrics.mBoundingBox.width;
@ -1058,13 +1036,12 @@ TextRenderedRun::GetClipEdges(nscoord& aVisIStartEdge,
// Get the covered content offset/length for this rendered run in skipped // Get the covered content offset/length for this rendered run in skipped
// characters, since that is what GetAdvanceWidth expects. // characters, since that is what GetAdvanceWidth expects.
uint32_t runOffset, runLength, frameOffset, frameLength; Range runRange = ConvertOriginalToSkipped(it, mTextFrameContentOffset,
ConvertOriginalToSkipped(it, mTextFrameContentOffset, mTextFrameContentLength, mTextFrameContentLength);
runOffset, runLength);
// Get the offset/length of the whole nsTextFrame. // Get the offset/length of the whole nsTextFrame.
frameOffset = mFrame->GetContentOffset(); uint32_t frameOffset = mFrame->GetContentOffset();
frameLength = mFrame->GetContentLength(); uint32_t frameLength = mFrame->GetContentLength();
// Trim the whole-nsTextFrame offset/length to remove any leading/trailing // Trim the whole-nsTextFrame offset/length to remove any leading/trailing
// white space, as the nsTextFrame when painting does not include them when // white space, as the nsTextFrame when painting does not include them when
@ -1075,19 +1052,17 @@ TextRenderedRun::GetClipEdges(nscoord& aVisIStartEdge,
// Convert the trimmed whole-nsTextFrame offset/length into skipped // Convert the trimmed whole-nsTextFrame offset/length into skipped
// characters. // characters.
ConvertOriginalToSkipped(it, frameOffset, frameLength); Range frameRange = ConvertOriginalToSkipped(it, frameOffset, frameLength);
// Measure the advance width in the text run between the start of // Measure the advance width in the text run between the start of
// frame's content and the start of the rendered run's content, // frame's content and the start of the rendered run's content,
nscoord startEdge = nscoord startEdge = textRun->
textRun->GetAdvanceWidth(frameOffset, runOffset - frameOffset, nullptr); GetAdvanceWidth(Range(frameRange.start, runRange.start), nullptr);
// and between the end of the rendered run's content and the end // and between the end of the rendered run's content and the end
// of the frame's content. // of the frame's content.
nscoord endEdge = nscoord endEdge = textRun->
textRun->GetAdvanceWidth(runOffset + runLength, GetAdvanceWidth(Range(runRange.end, frameRange.end), nullptr);
frameOffset + frameLength - (runOffset + runLength),
nullptr);
if (textRun->IsRightToLeft()) { if (textRun->IsRightToLeft()) {
aVisIStartEdge = endEdge; aVisIStartEdge = endEdge;
@ -1104,11 +1079,10 @@ TextRenderedRun::GetAdvanceWidth() const
gfxSkipCharsIterator it = mFrame->EnsureTextRun(nsTextFrame::eInflated); gfxSkipCharsIterator it = mFrame->EnsureTextRun(nsTextFrame::eInflated);
gfxTextRun* textRun = mFrame->GetTextRun(nsTextFrame::eInflated); gfxTextRun* textRun = mFrame->GetTextRun(nsTextFrame::eInflated);
uint32_t offset, length; Range range = ConvertOriginalToSkipped(it, mTextFrameContentOffset,
ConvertOriginalToSkipped(it, mTextFrameContentOffset, mTextFrameContentLength, mTextFrameContentLength);
offset, length);
return textRun->GetAdvanceWidth(offset, length, nullptr); return textRun->GetAdvanceWidth(range, nullptr);
} }
int32_t int32_t
@ -1159,12 +1133,10 @@ TextRenderedRun::GetCharNumAtPosition(nsPresContext* aContext,
// Next check that the point lies horizontally within the left and right // Next check that the point lies horizontally within the left and right
// edges of the text. // edges of the text.
uint32_t offset, length; Range range = ConvertOriginalToSkipped(it, mTextFrameContentOffset,
ConvertOriginalToSkipped(it, mTextFrameContentOffset, mTextFrameContentLength, mTextFrameContentLength);
offset, length);
gfxFloat runAdvance = gfxFloat runAdvance =
aContext->AppUnitsToGfxUnits(textRun->GetAdvanceWidth(offset, length, aContext->AppUnitsToGfxUnits(textRun->GetAdvanceWidth(range, nullptr));
nullptr));
gfxFloat pos = writingMode.IsVertical() ? p.y : p.x; gfxFloat pos = writingMode.IsVertical() ? p.y : p.x;
if (pos < 0 || pos >= runAdvance) { if (pos < 0 || pos >= runAdvance) {
@ -1176,10 +1148,9 @@ TextRenderedRun::GetCharNumAtPosition(nsPresContext* aContext,
// support letter-spacing and word-spacing. // support letter-spacing and word-spacing.
bool rtl = textRun->IsRightToLeft(); bool rtl = textRun->IsRightToLeft();
for (int32_t i = mTextFrameContentLength - 1; i >= 0; i--) { for (int32_t i = mTextFrameContentLength - 1; i >= 0; i--) {
ConvertOriginalToSkipped(it, mTextFrameContentOffset, i, offset, length); range = ConvertOriginalToSkipped(it, mTextFrameContentOffset, i);
gfxFloat advance = gfxFloat advance =
aContext->AppUnitsToGfxUnits(textRun->GetAdvanceWidth(offset, length, aContext->AppUnitsToGfxUnits(textRun->GetAdvanceWidth(range, nullptr));
nullptr));
if ((rtl && pos < runAdvance - advance) || if ((rtl && pos < runAdvance - advance) ||
(!rtl && pos >= advance)) { (!rtl && pos >= advance)) {
return i; return i;
@ -2137,6 +2108,8 @@ TextRenderedRunIterator::First()
*/ */
class CharIterator class CharIterator
{ {
typedef gfxTextRun::Range Range;
public: public:
/** /**
* Values for the aFilter argument of the constructor, to indicate which * Values for the aFilter argument of the constructor, to indicate which
@ -2628,12 +2601,12 @@ CharIterator::GetGlyphAdvance(nsPresContext* aContext) const
GetOriginalGlyphOffsets(offset, length); GetOriginalGlyphOffsets(offset, length);
gfxSkipCharsIterator it = TextFrame()->EnsureTextRun(nsTextFrame::eInflated); gfxSkipCharsIterator it = TextFrame()->EnsureTextRun(nsTextFrame::eInflated);
ConvertOriginalToSkipped(it, offset, length); Range range = ConvertOriginalToSkipped(it, offset, length);
float cssPxPerDevPx = aContext-> float cssPxPerDevPx = aContext->
AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel()); AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
gfxFloat advance = mTextRun->GetAdvanceWidth(offset, length, nullptr); gfxFloat advance = mTextRun->GetAdvanceWidth(range, nullptr);
return aContext->AppUnitsToGfxUnits(advance) * return aContext->AppUnitsToGfxUnits(advance) *
mLengthAdjustScaleFactor * cssPxPerDevPx; mLengthAdjustScaleFactor * cssPxPerDevPx;
} }
@ -2644,8 +2617,9 @@ CharIterator::GetAdvance(nsPresContext* aContext) const
float cssPxPerDevPx = aContext-> float cssPxPerDevPx = aContext->
AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel()); AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
gfxFloat advance = uint32_t offset = mSkipCharsIterator.GetSkippedOffset();
mTextRun->GetAdvanceWidth(mSkipCharsIterator.GetSkippedOffset(), 1, nullptr); gfxFloat advance = mTextRun->
GetAdvanceWidth(Range(offset, offset + 1), nullptr);
return aContext->AppUnitsToGfxUnits(advance) * return aContext->AppUnitsToGfxUnits(advance) *
mLengthAdjustScaleFactor * cssPxPerDevPx; mLengthAdjustScaleFactor * cssPxPerDevPx;
} }
@ -2661,12 +2635,12 @@ CharIterator::GetGlyphPartialAdvance(uint32_t aPartLength,
length = aPartLength; length = aPartLength;
gfxSkipCharsIterator it = TextFrame()->EnsureTextRun(nsTextFrame::eInflated); gfxSkipCharsIterator it = TextFrame()->EnsureTextRun(nsTextFrame::eInflated);
ConvertOriginalToSkipped(it, offset, length); Range range = ConvertOriginalToSkipped(it, offset, length);
float cssPxPerDevPx = aContext-> float cssPxPerDevPx = aContext->
AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel()); AppUnitsToFloatCSSPixels(aContext->AppUnitsPerDevPixel());
gfxFloat advance = mTextRun->GetAdvanceWidth(offset, length, nullptr); gfxFloat advance = mTextRun->GetAdvanceWidth(range, nullptr);
return aContext->AppUnitsToGfxUnits(advance) * return aContext->AppUnitsToGfxUnits(advance) *
mLengthAdjustScaleFactor * cssPxPerDevPx; mLengthAdjustScaleFactor * cssPxPerDevPx;
} }
@ -4218,10 +4192,10 @@ SVGTextFrame::GetSubStringLength(nsIContent* aContent,
gfxSkipCharsIterator it = gfxSkipCharsIterator it =
run.mFrame->EnsureTextRun(nsTextFrame::eInflated); run.mFrame->EnsureTextRun(nsTextFrame::eInflated);
gfxTextRun* textRun = run.mFrame->GetTextRun(nsTextFrame::eInflated); gfxTextRun* textRun = run.mFrame->GetTextRun(nsTextFrame::eInflated);
ConvertOriginalToSkipped(it, offset, length); Range range = ConvertOriginalToSkipped(it, offset, length);
// Accumulate the advance. // Accumulate the advance.
textLength += textRun->GetAdvanceWidth(offset, length, nullptr); textLength += textRun->GetAdvanceWidth(range, nullptr);
} }
run = it.Next(); run = it.Next();
@ -4720,8 +4694,9 @@ SVGTextFrame::DetermineCharPositions(nsTArray<nsPoint>& aPositions)
!it.IsOriginalCharSkipped() && !it.IsOriginalCharSkipped() &&
(!textRun->IsLigatureGroupStart(it.GetSkippedOffset()) || (!textRun->IsLigatureGroupStart(it.GetSkippedOffset()) ||
!textRun->IsClusterStart(it.GetSkippedOffset()))) { !textRun->IsClusterStart(it.GetSkippedOffset()))) {
nscoord advance = textRun->GetAdvanceWidth(it.GetSkippedOffset(), 1, uint32_t offset = it.GetSkippedOffset();
nullptr); nscoord advance = textRun->
GetAdvanceWidth(Range(offset, offset + 1), nullptr);
(textRun->IsVertical() ? position.y : position.x) += (textRun->IsVertical() ? position.y : position.x) +=
textRun->IsRightToLeft() ? -advance : advance; textRun->IsRightToLeft() ? -advance : advance;
aPositions.AppendElement(lastPosition); aPositions.AppendElement(lastPosition);
@ -4735,9 +4710,8 @@ SVGTextFrame::DetermineCharPositions(nsTArray<nsPoint>& aPositions)
textRun->IsLigatureGroupStart(it.GetSkippedOffset()) && textRun->IsLigatureGroupStart(it.GetSkippedOffset()) &&
textRun->IsClusterStart(it.GetSkippedOffset())) { textRun->IsClusterStart(it.GetSkippedOffset())) {
// A real visible character. // A real visible character.
uint32_t length = ClusterLength(textRun, it); nscoord advance = textRun->
nscoord advance = textRun->GetAdvanceWidth(it.GetSkippedOffset(), GetAdvanceWidth(ClusterRange(textRun, it), nullptr);
length, nullptr);
(textRun->IsVertical() ? position.y : position.x) += (textRun->IsVertical() ? position.y : position.x) +=
textRun->IsRightToLeft() ? -advance : advance; textRun->IsRightToLeft() ? -advance : advance;
lastPosition = position; lastPosition = position;

View File

@ -12,6 +12,7 @@
#include "gfxMatrix.h" #include "gfxMatrix.h"
#include "gfxRect.h" #include "gfxRect.h"
#include "gfxSVGGlyphs.h" #include "gfxSVGGlyphs.h"
#include "gfxTextRun.h"
#include "nsIContent.h" // for GetContent #include "nsIContent.h" // for GetContent
#include "nsStubMutationObserver.h" #include "nsStubMutationObserver.h"
#include "nsSVGPaintServerFrame.h" #include "nsSVGPaintServerFrame.h"
@ -258,6 +259,7 @@ class SVGTextFrame final : public SVGTextFrameBase
friend class MutationObserver; friend class MutationObserver;
friend class nsDisplaySVGText; friend class nsDisplaySVGText;
typedef gfxTextRun::Range Range;
typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::DrawTarget DrawTarget;
typedef mozilla::gfx::Path Path; typedef mozilla::gfx::Path Path;
typedef mozilla::gfx::Point Point; typedef mozilla::gfx::Point Point;