Bug 1692937 [wpt PR 27636] - new parameter --include-file for wptrunner, a=testonly
[gecko.git] / layout / generic / TextDrawTarget.h
blobfadd7049fb348e67accab78ef1aa44f7492ae960
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef TextDrawTarget_h
8 #define TextDrawTarget_h
10 #include "mozilla/gfx/2D.h"
11 #include "mozilla/layers/RenderRootStateManager.h"
12 #include "mozilla/layers/WebRenderLayerManager.h"
13 #include "mozilla/layers/WebRenderBridgeChild.h"
14 #include "mozilla/webrender/WebRenderAPI.h"
15 #include "mozilla/layers/StackingContextHelper.h"
16 #include "mozilla/layers/IpcResourceUpdateQueue.h"
18 namespace mozilla {
19 namespace layout {
21 using namespace gfx;
23 // This class is a fake DrawTarget, used to intercept text draw calls, while
24 // also collecting up the other aspects of text natively.
26 // When using advanced-layers in nsDisplayText's constructor, we construct this
27 // and run the full painting algorithm with this as the DrawTarget. This is
28 // done to avoid having to massively refactor gecko's text painting code (which
29 // has lots of components shared between other rendering algorithms).
31 // In some phases of the painting algorithm, we can grab the relevant values
32 // and feed them directly into TextDrawTarget. For instance, selections,
33 // decorations, and shadows are handled in this manner. In those cases we can
34 // also short-circuit the painting algorithm to save work.
36 // In other phases, the computed values are sufficiently buried in complex
37 // code that it's best for us to just intercept the final draw calls. This
38 // is how we handle computing the glyphs of the main text and text-emphasis
39 // (see our overloaded FillGlyphs implementation).
41 // To be clear: this is a big hack. With time we hope to refactor the codebase
42 // so that all the elements of text are handled directly by TextDrawTarget,
43 // which is to say everything is done like we do selections and shadows now.
44 // This design is a good step for doing this work incrementally.
46 // This is also likely to be a bit buggy (missing or misinterpreted info)
47 // while we further develop the design.
49 // TextDrawTarget doesn't yet support all features. See mHasUnsupportedFeatures
50 // for details.
51 class TextDrawTarget : public DrawTarget {
52 public:
53 explicit TextDrawTarget(wr::DisplayListBuilder& aBuilder,
54 wr::IpcResourceUpdateQueue& aResources,
55 const layers::StackingContextHelper& aSc,
56 layers::RenderRootStateManager* aManager,
57 nsDisplayItem* aItem, nsRect& aBounds,
58 bool aCallerDoesSaveRestore = false)
59 : mCallerDoesSaveRestore(aCallerDoesSaveRestore), mBuilder(aBuilder) {
60 Reinitialize(aResources, aSc, aManager, aItem, aBounds);
63 // Prevent this from being copied
64 TextDrawTarget(const TextDrawTarget& src) = delete;
65 TextDrawTarget& operator=(const TextDrawTarget&) = delete;
67 ~TextDrawTarget() { MOZ_ASSERT(mFinished); }
69 void Reinitialize(wr::IpcResourceUpdateQueue& aResources,
70 const layers::StackingContextHelper& aSc,
71 layers::RenderRootStateManager* aManager,
72 nsDisplayItem* aItem, nsRect& aBounds) {
73 mResources = &aResources;
74 mSc = &aSc;
75 mManager = aManager;
76 mHasUnsupportedFeatures = false;
77 mHasShadows = false;
79 SetPermitSubpixelAA(!aItem->IsSubpixelAADisabled());
81 // Compute clip/bounds
82 auto appUnitsPerDevPixel =
83 aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
84 LayoutDeviceRect layoutBoundsRect =
85 LayoutDeviceRect::FromAppUnits(aBounds, appUnitsPerDevPixel);
86 LayoutDeviceRect layoutClipRect = layoutBoundsRect;
87 mBoundsRect = wr::ToLayoutRect(layoutBoundsRect);
89 // Add 1 pixel of dirty area around clip rect to allow us to paint
90 // antialiased pixels beyond the measured text extents.
91 layoutClipRect.Inflate(1);
92 mSize = IntSize::Ceil(layoutClipRect.Width(), layoutClipRect.Height());
93 mClipStack.ClearAndRetainStorage();
94 mClipStack.AppendElement(layoutClipRect);
96 mBackfaceVisible = !aItem->BackfaceIsHidden();
98 if (!mCallerDoesSaveRestore) {
99 mBuilder.Save();
103 void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
104 bool CheckHasUnsupportedFeatures() {
105 MOZ_ASSERT(mCallerDoesSaveRestore);
106 #ifdef DEBUG
107 MOZ_ASSERT(!mFinished);
108 mFinished = true;
109 #endif
110 return mHasUnsupportedFeatures;
113 bool Finish() {
114 MOZ_ASSERT(!mCallerDoesSaveRestore);
115 #ifdef DEBUG
116 mFinished = true;
117 #endif
118 if (mHasUnsupportedFeatures) {
119 mBuilder.Restore();
120 return false;
122 mBuilder.ClearSave();
123 return true;
126 wr::FontInstanceFlags GetWRGlyphFlags() const { return mWRGlyphFlags; }
127 void SetWRGlyphFlags(wr::FontInstanceFlags aFlags) { mWRGlyphFlags = aFlags; }
129 class AutoRestoreWRGlyphFlags {
130 public:
131 ~AutoRestoreWRGlyphFlags() {
132 if (mTarget) {
133 mTarget->SetWRGlyphFlags(mFlags);
137 void Save(TextDrawTarget* aTarget) {
138 // This allows for recursive saves, in case the flags need to be modified
139 // under multiple conditions (i.e. transforms and synthetic italics),
140 // since the flags will be restored to the first saved value in the
141 // destructor on scope exit.
142 if (!mTarget) {
143 // Only record the first save with the original flags that will be
144 // restored.
145 mTarget = aTarget;
146 mFlags = aTarget->GetWRGlyphFlags();
147 } else {
148 // Ensure that this is actually a recursive save to the same target
149 MOZ_ASSERT(
150 mTarget == aTarget,
151 "Recursive save of WR glyph flags to different TextDrawTargets");
155 private:
156 TextDrawTarget* mTarget = nullptr;
157 wr::FontInstanceFlags mFlags = {0};
160 // This overload just stores the glyphs/font/color.
161 void FillGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
162 const Pattern& aPattern,
163 const DrawOptions& aOptions) override {
164 // Make sure we're only given boring color patterns
165 MOZ_RELEASE_ASSERT(aOptions.mCompositionOp == CompositionOp::OP_OVER);
166 MOZ_RELEASE_ASSERT(aOptions.mAlpha == 1.0f);
167 MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
169 // Make sure the font exists, and can be serialized
170 MOZ_RELEASE_ASSERT(aFont);
171 if (!aFont->CanSerialize()) {
172 FoundUnsupportedFeature();
173 return;
176 auto* colorPat = static_cast<const ColorPattern*>(&aPattern);
177 auto color = wr::ToColorF(colorPat->mColor);
178 MOZ_ASSERT(aBuffer.mNumGlyphs);
179 auto glyphs = Range<const wr::GlyphInstance>(
180 reinterpret_cast<const wr::GlyphInstance*>(aBuffer.mGlyphs),
181 aBuffer.mNumGlyphs);
182 // MSVC won't let us use offsetof on the following directly so we give it a
183 // name with typedef
184 typedef std::remove_reference<decltype(aBuffer.mGlyphs[0])>::type GlyphType;
185 // Compare gfx::Glyph and wr::GlyphInstance to make sure that they are
186 // structurally equivalent to ensure that our cast above was ok
187 static_assert(
188 std::is_same<decltype(aBuffer.mGlyphs[0].mIndex),
189 decltype(glyphs[0].index)>() &&
190 std::is_same<decltype(aBuffer.mGlyphs[0].mPosition.x),
191 decltype(glyphs[0].point.x)>() &&
192 std::is_same<decltype(aBuffer.mGlyphs[0].mPosition.y),
193 decltype(glyphs[0].point.y)>() &&
194 offsetof(GlyphType, mIndex) == offsetof(wr::GlyphInstance, index) &&
195 offsetof(GlyphType, mPosition) ==
196 offsetof(wr::GlyphInstance, point) &&
197 offsetof(decltype(aBuffer.mGlyphs[0].mPosition), x) ==
198 offsetof(decltype(glyphs[0].point), x) &&
199 offsetof(decltype(aBuffer.mGlyphs[0].mPosition), y) ==
200 offsetof(decltype(glyphs[0].point), y) &&
201 std::is_standard_layout<
202 std::remove_reference<decltype(aBuffer.mGlyphs[0])>>::value &&
203 std::is_standard_layout<
204 std::remove_reference<decltype(glyphs[0])>>::value &&
205 sizeof(aBuffer.mGlyphs[0]) == sizeof(glyphs[0]) &&
206 sizeof(aBuffer.mGlyphs[0].mPosition) == sizeof(glyphs[0].point),
207 "glyph buf types don't match");
209 wr::GlyphOptions glyphOptions;
210 glyphOptions.render_mode =
211 wr::ToFontRenderMode(aOptions.mAntialiasMode, GetPermitSubpixelAA());
212 glyphOptions.flags = mWRGlyphFlags;
214 mManager->WrBridge()->PushGlyphs(mBuilder, glyphs, aFont, color, *mSc,
215 mBoundsRect, ClipRect(), mBackfaceVisible,
216 &glyphOptions);
219 void PushClipRect(const Rect& aRect) override {
220 LayoutDeviceRect rect = LayoutDeviceRect::FromUnknownRect(aRect);
221 rect = rect.Intersect(mClipStack.LastElement());
222 mClipStack.AppendElement(rect);
225 void PopClip() override { mClipStack.RemoveLastElement(); }
227 IntSize GetSize() const override { return mSize; }
229 void AppendShadow(const wr::Shadow& aShadow, bool aInflate) {
230 mBuilder.PushShadow(mBoundsRect, ClipRect(), mBackfaceVisible, aShadow,
231 aInflate);
232 mHasShadows = true;
235 void TerminateShadows() {
236 if (mHasShadows) {
237 mBuilder.PopAllShadows();
238 mHasShadows = false;
242 void AppendSelectionRect(const LayoutDeviceRect& aRect,
243 const DeviceColor& aColor) {
244 auto rect = wr::ToLayoutRect(aRect);
245 auto color = wr::ToColorF(aColor);
246 mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, color);
249 // This function is basically designed to slide into the decoration drawing
250 // code of nsCSSRendering with minimum disruption, to minimize the
251 // chances of implementation drift. As such, it mostly looks like a call
252 // to a skia-style StrokeLine method: two end-points, with a thickness
253 // and style. Notably the end-points are *centered* in the block direction,
254 // even though webrender wants a rect-like representation, where the points
255 // are on corners.
257 // So we mangle the format here in a single centralized place, where neither
258 // webrender nor nsCSSRendering has to care about this mismatch.
260 // NOTE: we assume the points are axis-aligned, and aStart should be used
261 // as the top-left corner of the rect.
262 void AppendDecoration(const Point& aStart, const Point& aEnd,
263 const float aThickness, const bool aVertical,
264 const DeviceColor& aColor, const uint8_t aStyle) {
265 auto pos = LayoutDevicePoint::FromUnknownPoint(aStart);
266 LayoutDeviceSize size;
268 if (aVertical) {
269 pos.x -= aThickness / 2; // adjust from center to corner
270 size = LayoutDeviceSize(aThickness, aEnd.y - aStart.y);
271 } else {
272 pos.y -= aThickness / 2; // adjust from center to corner
273 size = LayoutDeviceSize(aEnd.x - aStart.x, aThickness);
276 wr::Line decoration;
277 decoration.bounds = wr::ToLayoutRect(LayoutDeviceRect(pos, size));
278 decoration.wavyLineThickness = 0; // dummy value, unused
279 decoration.color = wr::ToColorF(aColor);
280 decoration.orientation = aVertical ? wr::LineOrientation::Vertical
281 : wr::LineOrientation::Horizontal;
283 switch (aStyle) {
284 case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
285 decoration.style = wr::LineStyle::Solid;
286 break;
287 case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED:
288 decoration.style = wr::LineStyle::Dotted;
289 break;
290 case NS_STYLE_TEXT_DECORATION_STYLE_DASHED:
291 decoration.style = wr::LineStyle::Dashed;
292 break;
293 // Wavy lines should go through AppendWavyDecoration
294 case NS_STYLE_TEXT_DECORATION_STYLE_WAVY:
295 // Double lines should be lowered to two solid lines
296 case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE:
297 default:
298 MOZ_CRASH("TextDrawTarget received unsupported line style");
301 mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
304 // Seperated out from AppendDecoration because Wavy Lines are completely
305 // different, and trying to merge the concept is more of a mess than it's
306 // worth.
307 void AppendWavyDecoration(const Rect& aBounds, const float aThickness,
308 const bool aVertical, const DeviceColor& aColor) {
309 wr::Line decoration;
311 decoration.bounds =
312 wr::ToLayoutRect(LayoutDeviceRect::FromUnknownRect(aBounds));
313 decoration.wavyLineThickness = aThickness;
314 decoration.color = wr::ToColorF(aColor);
315 decoration.orientation = aVertical ? wr::LineOrientation::Vertical
316 : wr::LineOrientation::Horizontal;
317 decoration.style = wr::LineStyle::Wavy;
319 mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
322 layers::WebRenderBridgeChild* WrBridge() { return mManager->WrBridge(); }
323 layers::WebRenderLayerManager* WrLayerManager() {
324 return mManager->LayerManager();
327 Maybe<wr::ImageKey> DefineImage(const IntSize& aSize, uint32_t aStride,
328 SurfaceFormat aFormat, const uint8_t* aData) {
329 wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
330 wr::ImageDescriptor desc(aSize, aStride, aFormat);
331 Range<uint8_t> bytes(const_cast<uint8_t*>(aData), aStride * aSize.height);
332 if (mResources->AddImage(key, desc, bytes)) {
333 return Some(key);
335 return Nothing();
338 void PushImage(wr::ImageKey aKey, const Rect& aBounds, const Rect& aClip,
339 wr::ImageRendering aFilter, const wr::ColorF& aColor) {
340 if (!aClip.Intersects(GeckoClipRect().ToUnknownRect())) {
341 return;
343 mBuilder.PushImage(wr::ToLayoutRect(aBounds), wr::ToLayoutRect(aClip), true,
344 aFilter, aKey, true, aColor);
347 private:
348 wr::LayoutRect ClipRect() {
349 return wr::ToLayoutRect(mClipStack.LastElement());
351 LayoutDeviceRect GeckoClipRect() { return mClipStack.LastElement(); }
352 // Whether anything unsupported was encountered. This will result in this
353 // text being emitted as a blob, which means subpixel-AA can't be used and
354 // that performance will probably be a bit worse. At this point, we've
355 // properly implemented everything that shows up a lot, so you can assume
356 // that the remaining things we don't implement are fairly rare. The complete
357 // set of things that we don't implement are as follows:
359 // * Unserializable Fonts: WR lives across an IPC boundary
360 // * Text-Combine-Upright Squishing: no one's really bothered to impl it yet
361 // * Text-Stroke: not a real standard (exists for webcompat)
362 // * SVG Glyphs: not a real standard (we got overzealous with svg)
363 // * Color Glyphs (Emoji) With Transparency: requires us to apply transparency
364 // with a composited layer (a single emoji can be many single-color glyphs)
366 // The transparent colored-glyphs issue is probably the most valuable to fix,
367 // since ideally it would also result in us fixing transparency for all
368 // intersecting glyphs (which currently look bad with or without webrender,
369 // so there's no fallback like with emoji). Specifically, transparency
370 // looks bad for "cursive" fonts where glyphs overlap at the seams. Since
371 // this is more common for non-latin scripts (e.g. मनीष), this amounts to us
372 // treating non-latin scripts poorly... unless they're emoji. Yikes!
373 bool mHasUnsupportedFeatures = false;
375 // The caller promises to call Save/Restore on the builder as needed.
376 bool mCallerDoesSaveRestore = false;
377 #ifdef DEBUG
378 bool mFinished = false;
379 #endif
381 // Whether PopAllShadows needs to be called
382 bool mHasShadows = false;
384 // Things used to push to webrender
385 wr::DisplayListBuilder& mBuilder;
386 wr::IpcResourceUpdateQueue* mResources;
387 const layers::StackingContextHelper* mSc;
388 layers::RenderRootStateManager* mManager;
390 // Computed facts
391 IntSize mSize;
392 wr::LayoutRect mBoundsRect;
393 AutoTArray<LayoutDeviceRect, 3> mClipStack;
394 bool mBackfaceVisible;
396 wr::FontInstanceFlags mWRGlyphFlags = {0};
398 // The rest of this is dummy implementations of DrawTarget's API
399 public:
400 DrawTargetType GetType() const override {
401 return DrawTargetType::SOFTWARE_RASTER;
404 BackendType GetBackendType() const override {
405 return BackendType::WEBRENDER_TEXT;
408 bool IsRecording() const override { return true; }
409 bool IsCaptureDT() const override { return false; }
411 already_AddRefed<SourceSurface> Snapshot() override {
412 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
413 return nullptr;
416 already_AddRefed<SourceSurface> IntoLuminanceSource(
417 LuminanceType aLuminanceType, float aOpacity) override {
418 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
419 return nullptr;
422 void Flush() override {
423 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
426 void DrawCapturedDT(DrawTargetCapture* aCaptureDT,
427 const Matrix& aTransform) override {
428 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
431 void DrawSurface(SourceSurface* aSurface, const Rect& aDest,
432 const Rect& aSource, const DrawSurfaceOptions& aSurfOptions,
433 const DrawOptions& aOptions) override {
434 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
437 void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
438 const Point& aDestPoint,
439 const DrawOptions& aOptions) override {
440 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
443 void DrawSurfaceWithShadow(SourceSurface* aSurface, const Point& aDest,
444 const DeviceColor& aColor, const Point& aOffset,
445 Float aSigma, CompositionOp aOperator) override {
446 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
449 void ClearRect(const Rect& aRect) override {
450 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
453 void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
454 const IntPoint& aDestination) override {
455 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
458 void FillRect(const Rect& aRect, const Pattern& aPattern,
459 const DrawOptions& aOptions = DrawOptions()) override {
460 MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
462 if (!aRect.Intersects(GeckoClipRect().ToUnknownRect())) {
463 return;
465 auto rect = wr::ToLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
466 auto color =
467 wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
468 mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, color);
471 void StrokeRect(const Rect& aRect, const Pattern& aPattern,
472 const StrokeOptions& aStrokeOptions,
473 const DrawOptions& aOptions) override {
474 MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR &&
475 aStrokeOptions.mDashLength == 0);
477 wr::LayoutSideOffsets widths = {
478 aStrokeOptions.mLineWidth, aStrokeOptions.mLineWidth,
479 aStrokeOptions.mLineWidth, aStrokeOptions.mLineWidth};
480 wr::ColorF color =
481 wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
482 wr::BorderSide sides[4] = {{color, wr::BorderStyle::Solid},
483 {color, wr::BorderStyle::Solid},
484 {color, wr::BorderStyle::Solid},
485 {color, wr::BorderStyle::Solid}};
486 wr::BorderRadius radius = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
487 LayoutDeviceRect rect = LayoutDeviceRect::FromUnknownRect(aRect);
488 rect.Inflate(aStrokeOptions.mLineWidth / 2);
489 if (!rect.Intersects(GeckoClipRect())) {
490 return;
492 wr::LayoutRect bounds = wr::ToLayoutRect(rect);
493 mBuilder.PushBorder(bounds, ClipRect(), true, widths,
494 Range<const wr::BorderSide>(sides, 4), radius);
497 void StrokeLine(const Point& aStart, const Point& aEnd,
498 const Pattern& aPattern, const StrokeOptions& aStrokeOptions,
499 const DrawOptions& aOptions) override {
500 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
503 void Stroke(const Path* aPath, const Pattern& aPattern,
504 const StrokeOptions& aStrokeOptions,
505 const DrawOptions& aOptions) override {
506 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
509 void Fill(const Path* aPath, const Pattern& aPattern,
510 const DrawOptions& aOptions) override {
511 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
514 void StrokeGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
515 const Pattern& aPattern,
516 const StrokeOptions& aStrokeOptions,
517 const DrawOptions& aOptions) override {
518 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
521 void Mask(const Pattern& aSource, const Pattern& aMask,
522 const DrawOptions& aOptions) override {
523 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
526 void MaskSurface(const Pattern& aSource, SourceSurface* aMask, Point aOffset,
527 const DrawOptions& aOptions) override {
528 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
531 bool Draw3DTransformedSurface(SourceSurface* aSurface,
532 const Matrix4x4& aMatrix) override {
533 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
536 void PushClip(const Path* aPath) override {
537 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
540 void PushDeviceSpaceClipRects(const IntRect* aRects,
541 uint32_t aCount) override {
542 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
545 void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
546 const Matrix& aMaskTransform, const IntRect& aBounds,
547 bool aCopyBackground) override {
548 // Fine to pretend we do this
551 void PopLayer() override {
552 // Fine to pretend we do this
555 already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
556 unsigned char* aData, const IntSize& aSize, int32_t aStride,
557 SurfaceFormat aFormat) const override {
558 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
559 return nullptr;
562 already_AddRefed<SourceSurface> OptimizeSourceSurface(
563 SourceSurface* aSurface) const override {
564 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
565 return nullptr;
568 already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
569 const NativeSurface& aSurface) const override {
570 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
571 return nullptr;
574 already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
575 const IntSize& aSize, SurfaceFormat aFormat) const override {
576 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
577 return nullptr;
580 bool CanCreateSimilarDrawTarget(const IntSize& aSize,
581 SurfaceFormat aFormat) const override {
582 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
583 return false;
586 virtual RefPtr<DrawTarget> CreateClippedDrawTarget(
587 const Rect& aBounds, SurfaceFormat aFormat) override {
588 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
589 return nullptr;
592 already_AddRefed<PathBuilder> CreatePathBuilder(
593 FillRule aFillRule) const override {
594 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
595 return nullptr;
598 already_AddRefed<FilterNode> CreateFilter(FilterType aType) override {
599 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
600 return nullptr;
603 already_AddRefed<GradientStops> CreateGradientStops(
604 GradientStop* aStops, uint32_t aNumStops,
605 ExtendMode aExtendMode) const override {
606 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
607 return nullptr;
610 void DetachAllSnapshots() override {
611 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
615 } // namespace layout
616 } // namespace mozilla
618 #endif