зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset c1f9baaa7b63 (bug 1406510) because it was already landed on inbound while autoland was closed.
--HG-- extra : rebase_source : 23c62698a1f1d70a689545acba41208ab51ffcd8
This commit is contained in:
Родитель
4397201c90
Коммит
0af7d9de10
|
@ -637,10 +637,6 @@ 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,10 +208,6 @@ public:
|
|||
|
||||
~DisplayListBuilder();
|
||||
|
||||
void Save();
|
||||
void Restore();
|
||||
void ClearSave();
|
||||
|
||||
void Finalize(wr::LayoutSize& aOutContentSize,
|
||||
wr::BuiltDisplayList& aOutDisplayList);
|
||||
|
||||
|
|
|
@ -1097,21 +1097,6 @@ 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,10 +910,6 @@ 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,
|
||||
|
@ -1179,14 +1175,6 @@ 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,6 +17,59 @@ 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.
|
||||
//
|
||||
|
@ -43,54 +96,42 @@ using namespace gfx;
|
|||
// This is also likely to be a bit buggy (missing or misinterpreted info)
|
||||
// while we further develop the design.
|
||||
//
|
||||
// TextDrawTarget doesn't yet support all features. See mHasUnsupportedFeatures
|
||||
// for details.
|
||||
// This does not currently support SVG text effects.
|
||||
class TextDrawTarget : public DrawTarget
|
||||
{
|
||||
public:
|
||||
explicit TextDrawTarget(wr::DisplayListBuilder& aBuilder,
|
||||
const layers::StackingContextHelper& aSc,
|
||||
layers::WebRenderLayerManager* aManager,
|
||||
nsDisplayItem* aItem,
|
||||
nsRect& aBounds)
|
||||
: mBuilder(aBuilder), mSc(aSc), mManager(aManager)
|
||||
// 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)
|
||||
{
|
||||
|
||||
// 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();
|
||||
SetSelectionIndex(0);
|
||||
}
|
||||
|
||||
// Prevent this from being copied
|
||||
TextDrawTarget(const TextDrawTarget& src) = delete;
|
||||
TextDrawTarget& operator=(const TextDrawTarget&) = delete;
|
||||
|
||||
~TextDrawTarget()
|
||||
{
|
||||
if (mHasUnsupportedFeatures) {
|
||||
mBuilder.Restore();
|
||||
} else {
|
||||
mBuilder.ClearSave();
|
||||
}
|
||||
}
|
||||
|
||||
// Change the phase of text we're drawing.
|
||||
void StartDrawing(Phase aPhase) { mCurrentlyDrawing = aPhase; }
|
||||
void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
|
||||
bool HasUnsupportedFeatures() { return mHasUnsupportedFeatures; }
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
mCurrentPart = &mParts[i];
|
||||
}
|
||||
|
||||
// This overload just stores the glyphs/font/color.
|
||||
void
|
||||
|
@ -100,61 +141,63 @@ public:
|
|||
const DrawOptions& aOptions,
|
||||
const GlyphRenderingOptions* aRenderingOptions) override
|
||||
{
|
||||
// FIXME(?): Deal with AA on the DrawOptions, and the GlyphRenderingOptions
|
||||
|
||||
// Make sure we're only given boring color patterns
|
||||
// FIXME: figure out which of these asserts are real
|
||||
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
|
||||
// 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);
|
||||
if (!aFont->CanSerialize()) {
|
||||
FoundUnsupportedFeature();
|
||||
return;
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
// 170 is the maximum size gfxFont is expected to hand us
|
||||
AutoTArray<wr::GlyphInstance, 170> glyphs;
|
||||
glyphs.SetLength(aBuffer.mNumGlyphs);
|
||||
// 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);
|
||||
|
||||
for (size_t i = 0; i < aBuffer.mNumGlyphs; i++) {
|
||||
wr::GlyphInstance& targetGlyph = glyphs[i];
|
||||
wr::GlyphInstance& targetGlyph = glyphs[oldLength + 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)
|
||||
{
|
||||
mBuilder.PushShadow(mBoundsRect, mClipRect, mBackfaceVisible, aShadow);
|
||||
mShadowCount++;
|
||||
AppendShadow(const wr::Shadow& aShadow) {
|
||||
mCurrentPart->shadows.AppendElement(aShadow);
|
||||
}
|
||||
|
||||
void
|
||||
TerminateShadows()
|
||||
SetSelectionRect(const LayoutDeviceRect& aRect, const Color& aColor)
|
||||
{
|
||||
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);
|
||||
SelectionFragment frag;
|
||||
frag.rect = wr::ToLayoutRect(aRect);
|
||||
frag.color = wr::ToColorF(aColor);
|
||||
mCurrentPart->selection = Some(frag);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -165,7 +208,19 @@ public:
|
|||
const Color& aColor,
|
||||
const uint8_t aStyle)
|
||||
{
|
||||
wr::Line decoration;
|
||||
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");
|
||||
}
|
||||
|
||||
// This function is basically designed to slide into the decoration drawing
|
||||
// code of nsCSSRendering with minimum disruption, to minimize the
|
||||
|
@ -177,27 +232,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:
|
||||
|
@ -205,33 +260,119 @@ 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:
|
||||
// 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;
|
||||
// The part of the text we're currently drawing (glyphs, underlines, etc.)
|
||||
Phase mCurrentlyDrawing;
|
||||
|
||||
// Number of shadows currently pushed, so we can pop them later.
|
||||
size_t mShadowCount = 0;
|
||||
// Which chunk of mParts is actively being populated
|
||||
SelectedTextRunFragment* mCurrentPart;
|
||||
|
||||
// Things used to push to webrender
|
||||
wr::DisplayListBuilder& mBuilder;
|
||||
// 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)
|
||||
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,12 +306,13 @@ nsDisplayTextOverflowMarker::CreateWebRenderCommands(mozilla::wr::DisplayListBui
|
|||
}
|
||||
|
||||
// Run the rendering algorithm to capture the glyphs and shadows
|
||||
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, this, bounds);
|
||||
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aSc);
|
||||
RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
|
||||
// TextOverflowMarker only draws glyphs
|
||||
textDrawer->StartDrawing(TextDrawTarget::Phase::eGlyphs);
|
||||
Paint(aDisplayListBuilder, captureCtx);
|
||||
textDrawer->TerminateShadows();
|
||||
|
||||
return !textDrawer->HasUnsupportedFeatures();
|
||||
return textDrawer->CreateWebRenderCommands(aBuilder, aSc, aManager, this, bounds);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5135,13 +5135,13 @@ nsDisplayText::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder
|
|||
return true;
|
||||
}
|
||||
|
||||
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aBuilder, aSc, aManager, this, mBounds);
|
||||
RefPtr<TextDrawTarget> textDrawer = new TextDrawTarget(aSc);
|
||||
RefPtr<gfxContext> captureCtx = gfxContext::CreateOrNull(textDrawer);
|
||||
|
||||
// TODO: Paint() checks mDisableSubpixelAA, we should too.
|
||||
RenderToContext(captureCtx, aDisplayListBuilder, true);
|
||||
|
||||
return !textDrawer->HasUnsupportedFeatures();
|
||||
return textDrawer->CreateWebRenderCommands(aBuilder, aSc, aManager, this, mBounds);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5951,6 +5951,14 @@ 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:
|
||||
|
@ -6269,24 +6277,6 @@ 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.
|
||||
|
@ -6322,6 +6312,25 @@ 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));
|
||||
|
||||
|
@ -6425,8 +6434,13 @@ 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);
|
||||
|
@ -6448,7 +6462,7 @@ nsTextFrame::PaintTextWithSelectionColors(
|
|||
LayoutDeviceRect::FromAppUnits(bgRect, appUnitsPerDevPixel);
|
||||
|
||||
if (textDrawer) {
|
||||
textDrawer->AppendSelectionRect(selectionRect, ToDeviceColor(background));
|
||||
textDrawer->SetSelectionRect(selectionRect, ToDeviceColor(background));
|
||||
} else {
|
||||
PaintSelectionBackground(
|
||||
*aParams.context->GetDrawTarget(), background, aParams.dirtyRect,
|
||||
|
@ -6456,6 +6470,7 @@ nsTextFrame::PaintTextWithSelectionColors(
|
|||
}
|
||||
}
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
++selectionIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6482,8 +6497,14 @@ 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);
|
||||
|
@ -6522,6 +6543,7 @@ nsTextFrame::PaintTextWithSelectionColors(
|
|||
DrawText(range, textBaselinePt, params);
|
||||
advance += hyphenWidth;
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
++selectionIndex;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -6597,8 +6619,14 @@ 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) {
|
||||
|
@ -6618,6 +6646,7 @@ nsTextFrame::PaintTextSelectionDecorations(
|
|||
verticalRun, kDecoration);
|
||||
}
|
||||
iterator.UpdateWithAdvance(advance);
|
||||
++selectionIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7141,6 +7170,11 @@ 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) {
|
||||
|
@ -7268,7 +7302,13 @@ 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,
|
||||
|
@ -7276,6 +7316,9 @@ 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);
|
||||
|
@ -7294,11 +7337,17 @@ 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,
|
||||
|
@ -7324,10 +7373,6 @@ nsTextFrame::DrawText(Range aRange, const gfxPoint& aTextBaselinePt,
|
|||
} else {
|
||||
DrawTextRun(aRange, aTextBaselinePt, aParams);
|
||||
}
|
||||
|
||||
if (auto* textDrawer = aParams.context->GetTextDrawer()) {
|
||||
textDrawer->TerminateShadows();
|
||||
}
|
||||
}
|
||||
|
||||
int16_t
|
||||
|
|
Загрузка…
Ссылка в новой задаче