Bug 1406510 - rewrite TextDrawTarget to push directly into display list. r=jrmuizel

MozReview-Commit-ID: 7rPGlYmmgeg
This commit is contained in:
Alexis Beingessner 2017-10-06 13:06:10 -04:00 коммит произвёл Jeff Muizelaar
Родитель 0e0b35e1aa
Коммит eeaa4695dc
7 изменённых файлов: 171 добавлений и 323 удалений

Просмотреть файл

@ -637,6 +637,10 @@ DisplayListBuilder::~DisplayListBuilder()
wr_state_delete(mWrState);
}
void DisplayListBuilder::Save() { wr_dp_save(mWrState); }
void DisplayListBuilder::Restore() { wr_dp_restore(mWrState); }
void DisplayListBuilder::ClearSave() { wr_dp_clear_save(mWrState); }
void
DisplayListBuilder::Finalize(wr::LayoutSize& aOutContentSize,
BuiltDisplayList& aOutDisplayList)

Просмотреть файл

@ -208,6 +208,10 @@ public:
~DisplayListBuilder();
void Save();
void Restore();
void ClearSave();
void Finalize(wr::LayoutSize& aOutContentSize,
wr::BuiltDisplayList& aOutDisplayList);

Просмотреть файл

@ -1097,6 +1097,21 @@ pub extern "C" fn wr_state_delete(state: *mut WrState) {
}
}
#[no_mangle]
pub extern "C" fn wr_dp_save(state: &mut WrState) {
state.frame_builder.dl_builder.save();
}
#[no_mangle]
pub extern "C" fn wr_dp_restore(state: &mut WrState) {
state.frame_builder.dl_builder.restore();
}
#[no_mangle]
pub extern "C" fn wr_dp_clear_save(state: &mut WrState) {
state.frame_builder.dl_builder.clear_save();
}
#[no_mangle]
pub extern "C" fn wr_dp_push_stacking_context(state: &mut WrState,
bounds: LayoutRect,

Просмотреть файл

@ -910,6 +910,10 @@ WR_INLINE
void wr_dec_ref_arc(const VecU8 *aArc)
WR_FUNC;
WR_INLINE
void wr_dp_clear_save(WrState *aState)
WR_FUNC;
WR_INLINE
uint64_t wr_dp_define_clip(WrState *aState,
LayoutRect aClipRect,
@ -1175,6 +1179,14 @@ void wr_dp_push_yuv_planar_image(WrState *aState,
ImageRendering aImageRendering)
WR_FUNC;
WR_INLINE
void wr_dp_restore(WrState *aState)
WR_FUNC;
WR_INLINE
void wr_dp_save(WrState *aState)
WR_FUNC;
extern bool wr_moz2d_render_cb(ByteSlice aBlob,
uint32_t aWidth,
uint32_t aHeight,

Просмотреть файл

@ -17,59 +17,6 @@ namespace layout {
using namespace gfx;
// This is used by all Advanced Layers users, so we use plain gfx types
struct TextRunFragment {
ScaledFont* font;
wr::ColorF color;
nsTArray<wr::GlyphInstance> glyphs;
};
// Only webrender handles this, so we use webrender types
struct SelectionFragment {
wr::ColorF color;
wr::LayoutRect rect;
};
// Selections are used in nsTextFrame to hack in sub-frame style changes.
// Most notably text-shadows can be changed by selections, and so we need to
// group all the glyphs and decorations attached to a shadow. We do this by
// having shadows apply to an entire SelectedTextRunFragment, and creating
// one for each "piece" of selection.
//
// For instance, this text:
//
// Hello [there] my name [is Mega]man
// ^ ^
// normal selection Ctrl+F highlight selection (yeah it's very overloaded)
//
// Would be broken up into 5 SelectedTextRunFragments
//
// ["Hello ", "there", " my name ", "is Mega", "man"]
//
// For almost all nsTextFrames, there will be only one SelectedTextRunFragment.
struct SelectedTextRunFragment {
Maybe<SelectionFragment> selection;
AutoTArray<wr::Shadow, 1> shadows;
AutoTArray<TextRunFragment, 1> text;
AutoTArray<wr::Line, 1> beforeDecorations;
AutoTArray<wr::Line, 1> afterDecorations;
};
}
}
// AutoTArray is bad
template<>
struct nsTArray_CopyChooser<mozilla::layout::SelectedTextRunFragment>
{
typedef nsTArray_CopyWithConstructors<mozilla::layout::SelectedTextRunFragment> Type;
};
namespace mozilla {
namespace layout {
using namespace gfx;
// This class is fake DrawTarget, used to intercept text draw calls, while
// also collecting up the other aspects of text natively.
//
@ -96,43 +43,55 @@ using namespace gfx;
// This is also likely to be a bit buggy (missing or misinterpreted info)
// while we further develop the design.
//
// This does not currently support SVG text effects.
// TextDrawTarget doesn't yet support all features. See mHasUnsupportedFeatures
// for details.
class TextDrawTarget : public DrawTarget
{
public:
// The different phases of drawing the text we're in
// Each should only happen once, and in the given order.
enum class Phase : uint8_t {
eSelection, eUnderline, eOverline, eGlyphs, eEmphasisMarks, eLineThrough
};
explicit TextDrawTarget(const layers::StackingContextHelper& aSc)
: mCurrentlyDrawing(Phase::eSelection),
mHasUnsupportedFeatures(false),
mSc(aSc)
explicit TextDrawTarget(wr::DisplayListBuilder& aBuilder,
const layers::StackingContextHelper& aSc,
layers::WebRenderLayerManager* aManager,
nsDisplayItem* aItem,
nsRect& aBounds)
: mBuilder(aBuilder), mSc(aSc), mManager(aManager)
{
SetSelectionIndex(0);
// Compute clip/bounds
auto appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect layoutBoundsRect = LayoutDeviceRect::FromAppUnits(
aBounds, appUnitsPerDevPixel);
LayoutDeviceRect layoutClipRect = layoutBoundsRect;
auto clip = aItem->GetClip();
if (clip.HasClip()) {
layoutClipRect = LayoutDeviceRect::FromAppUnits(
clip.GetClipRect(), appUnitsPerDevPixel);
}
mBoundsRect = aSc.ToRelativeLayoutRect(LayerRect::FromUnknownRect(layoutBoundsRect.ToUnknownRect()));
mClipRect = aSc.ToRelativeLayoutRect(LayerRect::FromUnknownRect(layoutClipRect.ToUnknownRect()));
mBackfaceVisible = !aItem->BackfaceIsHidden();
mBuilder.Save();
}
// Prevent this from being copied
TextDrawTarget(const TextDrawTarget& src) = delete;
TextDrawTarget& operator=(const TextDrawTarget&) = delete;
// Change the phase of text we're drawing.
void StartDrawing(Phase aPhase) { mCurrentlyDrawing = aPhase; }
void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
void SetSelectionIndex(size_t i) {
// i should only be accessed if i-1 has already been
MOZ_ASSERT(i <= mParts.Length());
if (mParts.Length() == i){
mParts.AppendElement();
~TextDrawTarget()
{
if (mHasUnsupportedFeatures) {
mBuilder.Restore();
} else {
mBuilder.ClearSave();
}
mCurrentPart = &mParts[i];
}
void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
bool HasUnsupportedFeatures() { return mHasUnsupportedFeatures; }
// This overload just stores the glyphs/font/color.
void
FillGlyphs(ScaledFont* aFont,
@ -141,63 +100,61 @@ public:
const DrawOptions& aOptions,
const GlyphRenderingOptions* aRenderingOptions) override
{
// FIXME: figure out which of these asserts are real
MOZ_RELEASE_ASSERT(aOptions.mCompositionOp == CompositionOp::OP_OVER);
MOZ_RELEASE_ASSERT(aOptions.mAlpha == 1.0f);
// Make sure we're only given color patterns
MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
const ColorPattern* colorPat = static_cast<const ColorPattern*>(&aPattern);
// Make sure the font exists
MOZ_RELEASE_ASSERT(aFont);
// FIXME(?): Deal with AA on the DrawOptions, and the GlyphRenderingOptions
if (mCurrentlyDrawing != Phase::eGlyphs &&
mCurrentlyDrawing != Phase::eEmphasisMarks) {
MOZ_CRASH("TextDrawTarget received glyphs in wrong phase");
// Make sure we're only given boring color patterns
MOZ_RELEASE_ASSERT(aOptions.mCompositionOp == CompositionOp::OP_OVER);
MOZ_RELEASE_ASSERT(aOptions.mAlpha == 1.0f);
MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
auto* colorPat = static_cast<const ColorPattern*>(&aPattern);
auto color = wr::ToColorF(colorPat->mColor);
// Make sure the font exists, and can be serialized
MOZ_RELEASE_ASSERT(aFont);
if (!aFont->CanSerialize()) {
FoundUnsupportedFeature();
return;
}
// We need to push a new TextRunFragment whenever the font/color changes
// (usually this implies some font fallback from mixing languages/emoji)
TextRunFragment* fragment;
if (mCurrentPart->text.IsEmpty() ||
mCurrentPart->text.LastElement().font != aFont ||
!(mCurrentPart->text.LastElement().color == wr::ToColorF(colorPat->mColor))) {
fragment = mCurrentPart->text.AppendElement();
fragment->font = aFont;
fragment->color = wr::ToColorF(colorPat->mColor);
} else {
fragment = &mCurrentPart->text.LastElement();
}
nsTArray<wr::GlyphInstance>& glyphs = fragment->glyphs;
size_t oldLength = glyphs.Length();
glyphs.SetLength(oldLength + aBuffer.mNumGlyphs);
// 170 is the maximum size gfxFont is expected to hand us
AutoTArray<wr::GlyphInstance, 170> glyphs;
glyphs.SetLength(aBuffer.mNumGlyphs);
for (size_t i = 0; i < aBuffer.mNumGlyphs; i++) {
wr::GlyphInstance& targetGlyph = glyphs[oldLength + i];
wr::GlyphInstance& targetGlyph = glyphs[i];
const gfx::Glyph& sourceGlyph = aBuffer.mGlyphs[i];
targetGlyph.index = sourceGlyph.mIndex;
targetGlyph.point = mSc.ToRelativeLayoutPoint(
LayerPoint::FromUnknownPoint(sourceGlyph.mPosition));
}
mManager->WrBridge()->PushGlyphs(mBuilder, glyphs, aFont,
color, mSc, mBoundsRect, mClipRect,
mBackfaceVisible);
}
void
AppendShadow(const wr::Shadow& aShadow) {
mCurrentPart->shadows.AppendElement(aShadow);
}
void
SetSelectionRect(const LayoutDeviceRect& aRect, const Color& aColor)
AppendShadow(const wr::Shadow& aShadow)
{
SelectionFragment frag;
frag.rect = wr::ToLayoutRect(aRect);
frag.color = wr::ToColorF(aColor);
mCurrentPart->selection = Some(frag);
mBuilder.PushShadow(mBoundsRect, mClipRect, mBackfaceVisible, aShadow);
mShadowCount++;
}
void
TerminateShadows()
{
for (size_t i = 0; i < mShadowCount; ++i) {
mBuilder.PopShadow();
}
mShadowCount = 0;
}
void
AppendSelectionRect(const LayoutDeviceRect& aRect, const Color& aColor)
{
auto rect = wr::ToLayoutRect(aRect);
auto color = wr::ToColorF(aColor);
mBuilder.PushRect(rect, mClipRect, mBackfaceVisible, color);
}
void
@ -208,19 +165,7 @@ public:
const Color& aColor,
const uint8_t aStyle)
{
wr::Line* decoration;
switch (mCurrentlyDrawing) {
case Phase::eUnderline:
case Phase::eOverline:
decoration = mCurrentPart->beforeDecorations.AppendElement();
break;
case Phase::eLineThrough:
decoration = mCurrentPart->afterDecorations.AppendElement();
break;
default:
MOZ_CRASH("TextDrawTarget received Decoration in wrong phase");
}
wr::Line decoration;
// This function is basically designed to slide into the decoration drawing
// code of nsCSSRendering with minimum disruption, to minimize the
@ -232,27 +177,27 @@ public:
//
// So we mangle the format here in a single centralized place, where neither
// webrender nor nsCSSRendering has to care about this mismatch.
decoration->baseline = (aVertical ? aStart.x : aStart.y) - aThickness / 2;
decoration->start = aVertical ? aStart.y : aStart.x;
decoration->end = aVertical ? aEnd.y : aEnd.x;
decoration->width = aThickness;
decoration->color = wr::ToColorF(aColor);
decoration->orientation = aVertical
decoration.baseline = (aVertical ? aStart.x : aStart.y) - aThickness / 2;
decoration.start = aVertical ? aStart.y : aStart.x;
decoration.end = aVertical ? aEnd.y : aEnd.x;
decoration.width = aThickness;
decoration.color = wr::ToColorF(aColor);
decoration.orientation = aVertical
? wr::LineOrientation::Vertical
: wr::LineOrientation::Horizontal;
switch (aStyle) {
case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
decoration->style = wr::LineStyle::Solid;
decoration.style = wr::LineStyle::Solid;
break;
case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED:
decoration->style = wr::LineStyle::Dotted;
decoration.style = wr::LineStyle::Dotted;
break;
case NS_STYLE_TEXT_DECORATION_STYLE_DASHED:
decoration->style = wr::LineStyle::Dashed;
decoration.style = wr::LineStyle::Dashed;
break;
case NS_STYLE_TEXT_DECORATION_STYLE_WAVY:
decoration->style = wr::LineStyle::Wavy;
decoration.style = wr::LineStyle::Wavy;
break;
// Double lines should be lowered to two solid lines
case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE:
@ -260,119 +205,33 @@ public:
MOZ_CRASH("TextDrawTarget received unsupported line style");
}
mBuilder.PushLine(mClipRect, mBackfaceVisible, decoration);
}
const nsTArray<SelectedTextRunFragment>& GetParts() { return mParts; }
bool
CanSerializeFonts()
{
if (mHasUnsupportedFeatures) {
return false;
}
for (const SelectedTextRunFragment& part : GetParts()) {
for (const TextRunFragment& frag : part.text) {
if (!frag.font->CanSerialize()) {
return false;
}
}
}
return true;
}
bool
CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder,
const layers::StackingContextHelper& aSc,
layers::WebRenderLayerManager* aManager,
nsDisplayItem* aItem,
nsRect& aBounds) {
if (!CanSerializeFonts()) {
return false;
}
// Drawing order: selections,
// shadows,
// underline, overline, [grouped in one array]
// text, emphasisText, [grouped in one array]
// lineThrough
// Compute clip/bounds
auto appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect layoutBoundsRect = LayoutDeviceRect::FromAppUnits(
aBounds, appUnitsPerDevPixel);
LayoutDeviceRect layoutClipRect = layoutBoundsRect;
auto clip = aItem->GetClip();
if (clip.HasClip()) {
layoutClipRect = LayoutDeviceRect::FromAppUnits(
clip.GetClipRect(), appUnitsPerDevPixel);
}
LayerRect boundsRect = LayerRect::FromUnknownRect(layoutBoundsRect.ToUnknownRect());
LayerRect clipRect = LayerRect::FromUnknownRect(layoutClipRect.ToUnknownRect());
bool backfaceVisible = !aItem->BackfaceIsHidden();
wr::LayoutRect wrBoundsRect = aSc.ToRelativeLayoutRect(boundsRect);
wr::LayoutRect wrClipRect = aSc.ToRelativeLayoutRect(clipRect);
// Create commands
for (auto& part : GetParts()) {
if (part.selection) {
auto selection = part.selection.value();
aBuilder.PushRect(selection.rect, wrClipRect, backfaceVisible, selection.color);
}
}
for (auto& part : GetParts()) {
// WR takes the shadows in CSS-order (reverse of rendering order),
// because the drawing of a shadow actually occurs when it's popped.
for (const wr::Shadow& shadow : part.shadows) {
aBuilder.PushShadow(wrBoundsRect, wrClipRect, backfaceVisible, shadow);
}
for (const wr::Line& decoration : part.beforeDecorations) {
aBuilder.PushLine(wrClipRect, backfaceVisible, decoration);
}
for (const mozilla::layout::TextRunFragment& text : part.text) {
aManager->WrBridge()->PushGlyphs(aBuilder, text.glyphs, text.font,
text.color, aSc, wrBoundsRect, wrClipRect,
backfaceVisible);
}
for (const wr::Line& decoration : part.afterDecorations) {
aBuilder.PushLine(wrClipRect, backfaceVisible, decoration);
}
for (size_t i = 0; i < part.shadows.Length(); ++i) {
aBuilder.PopShadow();
}
}
return true;
}
private:
// The part of the text we're currently drawing (glyphs, underlines, etc.)
Phase mCurrentlyDrawing;
// Whether anything unsupported was encountered. Currently:
//
// * Synthetic bold/italics
// * SVG fonts
// * Unserializable fonts
// * Tofu glyphs
// * Pratial ligatures
// * Text writing-mode
// * Text stroke
bool mHasUnsupportedFeatures = false;
// Which chunk of mParts is actively being populated
SelectedTextRunFragment* mCurrentPart;
// Number of shadows currently pushed, so we can pop them later.
size_t mShadowCount = 0;
// Chunks of the text, grouped by selection
AutoTArray<SelectedTextRunFragment, 1> mParts;
// Whether Tofu or SVG fonts were encountered
bool mHasUnsupportedFeatures;
// Needs to be saved so FillGlyphs can use this to offset glyphs to
// relative space. Shouldn't be used otherwise (may dangle if we move
// to retaining TextDrawTargets)
// Things used to push to webrender
wr::DisplayListBuilder& mBuilder;
const layers::StackingContextHelper& mSc;
layers::WebRenderLayerManager* mManager;
// Computed facts
wr::LayerRect mBoundsRect;
wr::LayerRect mClipRect;
bool mBackfaceVisible;
// The rest of this is dummy implementations of DrawTarget's API
public:

Просмотреть файл

@ -306,13 +306,12 @@ nsDisplayTextOverflowMarker::CreateWebRenderCommands(mozilla::wr::DisplayListBui
}
// Run the rendering algorithm to capture the glyphs and shadows
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aSc);
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, this, bounds);
RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
// TextOverflowMarker only draws glyphs
textDrawer->StartDrawing(TextDrawTarget::Phase::eGlyphs);
Paint(aDisplayListBuilder, captureCtx);
textDrawer->TerminateShadows();
return textDrawer->CreateWebRenderCommands(aBuilder, aSc, aManager, this, bounds);
return !textDrawer->HasUnsupportedFeatures();
}

Просмотреть файл

@ -5135,13 +5135,13 @@ nsDisplayText::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder
return true;
}
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aSc);
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, this, mBounds);
RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
// TODO: Paint() checks mDisableSubpixelAA, we should too.
RenderToContext(captureCtx, aDisplayListBuilder, true);
return textDrawer->CreateWebRenderCommands(aBuilder, aSc, aManager, this, mBounds);
return !textDrawer->HasUnsupportedFeatures();
}
void
@ -5951,14 +5951,6 @@ nsTextFrame::DrawSelectionDecorations(gfxContext* aContext,
float relativeSize;
auto* textDrawer = aContext->GetTextDrawer();
// Since this happens after text, all we *should* be allowed to do is strikeThrough.
// If this isn't true, we're at least bug-compatible with gecko!
if (textDrawer) {
textDrawer->StartDrawing(TextDrawTarget::Phase::eLineThrough);
}
switch (aSelectionType) {
case SelectionType::eIMERawClause:
case SelectionType::eIMESelectedRawClause:
@ -6277,6 +6269,24 @@ nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams,
gfxPoint shadowOffset(aShadowDetails->mXOffset, aShadowDetails->mYOffset);
nscoord blurRadius = std::max(aShadowDetails->mRadius, 0);
nscolor shadowColor = aShadowDetails->mHasColor ? aShadowDetails->mColor
: aParams.foregroundColor;
if (auto* textDrawer = aParams.context->GetTextDrawer()) {
wr::Shadow wrShadow;
wrShadow.offset = {
PresContext()->AppUnitsToFloatDevPixels(aShadowDetails->mXOffset),
PresContext()->AppUnitsToFloatDevPixels(aShadowDetails->mYOffset)
};
wrShadow.blur_radius = PresContext()->AppUnitsToFloatDevPixels(blurRadius);
wrShadow.color = wr::ToColorF(ToDeviceColor(shadowColor));
textDrawer->AppendShadow(wrShadow);
return;
}
// This rect is the box which is equivalent to where the shadow will be painted.
// The origin of aBoundingBox is the text baseline left, so we must translate it by
// that much in order to make the origin the top-left corner of the text bounding box.
@ -6312,25 +6322,6 @@ nsTextFrame::PaintOneShadow(const PaintShadowParams& aParams,
if (!shadowContext)
return;
nscolor shadowColor = aShadowDetails->mHasColor ? aShadowDetails->mColor
: aParams.foregroundColor;
auto* textDrawer = aParams.context->GetTextDrawer();
if (textDrawer) {
wr::Shadow wrShadow;
wrShadow.offset = {
PresContext()->AppUnitsToFloatDevPixels(aShadowDetails->mXOffset),
PresContext()->AppUnitsToFloatDevPixels(aShadowDetails->mYOffset)
};
wrShadow.blur_radius = PresContext()->AppUnitsToFloatDevPixels(aShadowDetails->mRadius);
wrShadow.color = wr::ToColorF(ToDeviceColor(shadowColor));
textDrawer->AppendShadow(wrShadow);
return;
}
aParams.context->Save();
aParams.context->SetColor(Color::FromABGR(shadowColor));
@ -6434,13 +6425,8 @@ nsTextFrame::PaintTextWithSelectionColors(
SelectionIterator iterator(prevailingSelections, contentRange,
*aParams.provider, mTextRun, startIOffset);
SelectionType selectionType;
size_t selectionIndex = 0;
while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
&selectionType, &rangeStyle)) {
if (textDrawer) {
textDrawer->SetSelectionIndex(selectionIndex);
}
nscolor foreground, background;
GetSelectionTextColors(selectionType, *aParams.textPaintStyle,
rangeStyle, &foreground, &background);
@ -6462,7 +6448,7 @@ nsTextFrame::PaintTextWithSelectionColors(
LayoutDeviceRect::FromAppUnits(bgRect, appUnitsPerDevPixel);
if (textDrawer) {
textDrawer->SetSelectionRect(selectionRect, ToDeviceColor(background));
textDrawer->AppendSelectionRect(selectionRect, ToDeviceColor(background));
} else {
PaintSelectionBackground(
*aParams.context->GetDrawTarget(), background, aParams.dirtyRect,
@ -6470,7 +6456,6 @@ nsTextFrame::PaintTextWithSelectionColors(
}
}
iterator.UpdateWithAdvance(advance);
++selectionIndex;
}
}
@ -6497,14 +6482,8 @@ nsTextFrame::PaintTextWithSelectionColors(
SelectionIterator iterator(prevailingSelections, contentRange,
*aParams.provider, mTextRun, startIOffset);
SelectionType selectionType;
size_t selectionIndex = 0;
while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
&selectionType, &rangeStyle)) {
if (textDrawer) {
textDrawer->SetSelectionIndex(selectionIndex);
}
nscolor foreground, background;
if (aParams.IsGenerateTextMask()) {
foreground = NS_RGBA(0, 0, 0, 255);
@ -6543,7 +6522,6 @@ nsTextFrame::PaintTextWithSelectionColors(
DrawText(range, textBaselinePt, params);
advance += hyphenWidth;
iterator.UpdateWithAdvance(advance);
++selectionIndex;
}
return true;
}
@ -6619,14 +6597,8 @@ nsTextFrame::PaintTextSelectionDecorations(
SelectionType nextSelectionType;
TextRangeStyle selectedStyle;
size_t selectionIndex = 0;
auto* textDrawer = aParams.context->GetTextDrawer();
while (iterator.GetNextSegment(&iOffset, &range, &hyphenWidth,
&nextSelectionType, &selectedStyle)) {
if (textDrawer) {
textDrawer->SetSelectionIndex(selectionIndex);
}
gfxFloat advance = hyphenWidth +
mTextRun->GetAdvanceWidth(range, aParams.provider);
if (nextSelectionType == aSelectionType) {
@ -6646,7 +6618,6 @@ nsTextFrame::PaintTextSelectionDecorations(
verticalRun, kDecoration);
}
iterator.UpdateWithAdvance(advance);
++selectionIndex;
}
}
@ -7170,11 +7141,6 @@ nsTextFrame::DrawTextRun(Range aRange, const gfxPoint& aTextBaselinePt,
{
MOZ_ASSERT(aParams.advanceWidth, "Must provide advanceWidth");
auto* textDrawer = aParams.context->GetTextDrawer();
if (textDrawer) {
textDrawer->StartDrawing(TextDrawTarget::Phase::eGlyphs);
}
::DrawTextRun(mTextRun, aTextBaselinePt, aRange, aParams);
if (aParams.drawSoftHyphen) {
@ -7302,13 +7268,7 @@ nsTextFrame::DrawTextRunAndDecorations(Range aRange,
PaintDecorationLine(params);
};
auto* textDrawer = aParams.context->GetTextDrawer();
// Underlines
if (textDrawer && aDecorations.mUnderlines.Length() > 0) {
textDrawer->StartDrawing(TextDrawTarget::Phase::eUnderline);
}
//
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
for (const LineDecoration& dec : Reversed(aDecorations.mUnderlines)) {
paintDecorationLine(dec, &Metrics::underlineSize,
@ -7316,9 +7276,6 @@ nsTextFrame::DrawTextRunAndDecorations(Range aRange,
}
// Overlines
if (textDrawer && aDecorations.mOverlines.Length() > 0) {
textDrawer->StartDrawing(TextDrawTarget::Phase::eOverline);
}
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_OVERLINE;
for (const LineDecoration& dec : Reversed(aDecorations.mOverlines)) {
paintDecorationLine(dec, &Metrics::underlineSize, &Metrics::maxAscent);
@ -7337,17 +7294,11 @@ nsTextFrame::DrawTextRunAndDecorations(Range aRange,
}
// Emphasis marks
if (textDrawer) {
textDrawer->StartDrawing(TextDrawTarget::Phase::eEmphasisMarks);
}
DrawEmphasisMarks(aParams.context, wm,
aTextBaselinePt, aParams.framePt, aRange,
aParams.decorationOverrideColor, aParams.provider);
// Line-throughs
if (textDrawer && aDecorations.mStrikes.Length() > 0) {
textDrawer->StartDrawing(TextDrawTarget::Phase::eLineThrough);
}
params.decoration = NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH;
for (const LineDecoration& dec : Reversed(aDecorations.mStrikes)) {
paintDecorationLine(dec, &Metrics::strikeoutSize,
@ -7373,6 +7324,10 @@ nsTextFrame::DrawText(Range aRange, const gfxPoint& aTextBaselinePt,
} else {
DrawTextRun(aRange, aTextBaselinePt, aParams);
}
if (auto* textDrawer = aParams.context->GetTextDrawer()) {
textDrawer->TerminateShadows();
}
}
int16_t