Bug 1867925 - Mark some storage-access-api tests as intermittent after wpt-sync....
[gecko.git] / layout / generic / TextDrawTarget.h
blob551dde2ff044a4b3e05ea073ca4fe10aebb0beb1
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(true);
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.value),
191 decltype(glyphs[0].point.x)>() &&
192 std::is_same<decltype(aBuffer.mGlyphs[0].mPosition.y.value),
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, *mResources, glyphs, aFont,
215 color, *mSc, mBoundsRect, ClipRect(),
216 mBackfaceVisible, &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, false, false, 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,
265 const StyleTextDecorationStyle aStyle) {
266 auto pos = LayoutDevicePoint::FromUnknownPoint(aStart);
267 LayoutDeviceSize size;
269 if (aVertical) {
270 pos.x -= aThickness / 2; // adjust from center to corner
271 size = LayoutDeviceSize(aThickness,
272 ViewAs<LayoutDevicePixel>(aEnd.y - aStart.y));
273 } else {
274 pos.y -= aThickness / 2; // adjust from center to corner
275 size = LayoutDeviceSize(ViewAs<LayoutDevicePixel>(aEnd.x - aStart.x),
276 aThickness);
279 wr::Line decoration;
280 decoration.bounds = wr::ToLayoutRect(LayoutDeviceRect(pos, size));
281 decoration.wavyLineThickness = 0; // dummy value, unused
282 decoration.color = wr::ToColorF(aColor);
283 decoration.orientation = aVertical ? wr::LineOrientation::Vertical
284 : wr::LineOrientation::Horizontal;
286 switch (aStyle) {
287 case StyleTextDecorationStyle::Solid:
288 decoration.style = wr::LineStyle::Solid;
289 break;
290 case StyleTextDecorationStyle::Dotted:
291 decoration.style = wr::LineStyle::Dotted;
292 break;
293 case StyleTextDecorationStyle::Dashed:
294 decoration.style = wr::LineStyle::Dashed;
295 break;
296 // Wavy lines should go through AppendWavyDecoration
297 case StyleTextDecorationStyle::Wavy:
298 // Double lines should be lowered to two solid lines
299 case StyleTextDecorationStyle::Double:
300 default:
301 MOZ_CRASH("TextDrawTarget received unsupported line style");
304 mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
307 // Seperated out from AppendDecoration because Wavy Lines are completely
308 // different, and trying to merge the concept is more of a mess than it's
309 // worth.
310 void AppendWavyDecoration(const Rect& aBounds, const float aThickness,
311 const bool aVertical, const DeviceColor& aColor) {
312 wr::Line decoration;
314 decoration.bounds =
315 wr::ToLayoutRect(LayoutDeviceRect::FromUnknownRect(aBounds));
316 decoration.wavyLineThickness = aThickness;
317 decoration.color = wr::ToColorF(aColor);
318 decoration.orientation = aVertical ? wr::LineOrientation::Vertical
319 : wr::LineOrientation::Horizontal;
320 decoration.style = wr::LineStyle::Wavy;
322 mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
325 layers::WebRenderBridgeChild* WrBridge() { return mManager->WrBridge(); }
326 layers::WebRenderLayerManager* WrLayerManager() {
327 return mManager->LayerManager();
330 Maybe<wr::ImageKey> DefineImage(const IntSize& aSize, uint32_t aStride,
331 SurfaceFormat aFormat, const uint8_t* aData) {
332 wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
333 wr::ImageDescriptor desc(aSize, aStride, aFormat);
334 Range<uint8_t> bytes(const_cast<uint8_t*>(aData), aStride * aSize.height);
335 if (mResources->AddImage(key, desc, bytes)) {
336 return Some(key);
338 return Nothing();
341 void PushImage(wr::ImageKey aKey, const Rect& aBounds, const Rect& aClip,
342 wr::ImageRendering aFilter, const wr::ColorF& aColor) {
343 if (!aClip.Intersects(GeckoClipRect().ToUnknownRect())) {
344 return;
346 mBuilder.PushImage(wr::ToLayoutRect(aBounds), wr::ToLayoutRect(aClip), true,
347 false, aFilter, aKey, true, aColor);
350 LayoutDeviceRect GeckoClipRect() { return mClipStack.LastElement(); }
352 private:
353 wr::LayoutRect ClipRect() {
354 return wr::ToLayoutRect(mClipStack.LastElement());
356 // Whether anything unsupported was encountered. This will result in this
357 // text being emitted as a blob, which means subpixel-AA can't be used and
358 // that performance will probably be a bit worse. At this point, we've
359 // properly implemented everything that shows up a lot, so you can assume
360 // that the remaining things we don't implement are fairly rare. The complete
361 // set of things that we don't implement are as follows:
363 // * Unserializable Fonts: WR lives across an IPC boundary
364 // * Text-Combine-Upright Squishing: no one's really bothered to impl it yet
365 // * Text-Stroke: not a real standard (exists for webcompat)
366 // * SVG Glyphs: not a real standard (we got overzealous with svg)
367 // * Color Glyphs (Emoji) With Transparency: requires us to apply transparency
368 // with a composited layer (a single emoji can be many single-color glyphs)
370 // The transparent colored-glyphs issue is probably the most valuable to fix,
371 // since ideally it would also result in us fixing transparency for all
372 // intersecting glyphs (which currently look bad with or without webrender,
373 // so there's no fallback like with emoji). Specifically, transparency
374 // looks bad for "cursive" fonts where glyphs overlap at the seams. Since
375 // this is more common for non-latin scripts (e.g. मनीष), this amounts to us
376 // treating non-latin scripts poorly... unless they're emoji. Yikes!
377 bool mHasUnsupportedFeatures = false;
379 // The caller promises to call Save/Restore on the builder as needed.
380 bool mCallerDoesSaveRestore = false;
381 #ifdef DEBUG
382 bool mFinished = false;
383 #endif
385 // Whether PopAllShadows needs to be called
386 bool mHasShadows = false;
388 // Things used to push to webrender
389 wr::DisplayListBuilder& mBuilder;
390 wr::IpcResourceUpdateQueue* mResources;
391 const layers::StackingContextHelper* mSc;
392 layers::RenderRootStateManager* mManager;
394 // Computed facts
395 IntSize mSize;
396 wr::LayoutRect mBoundsRect;
397 AutoTArray<LayoutDeviceRect, 3> mClipStack;
398 bool mBackfaceVisible;
400 wr::FontInstanceFlags mWRGlyphFlags = {0};
402 // The rest of this is dummy implementations of DrawTarget's API
403 public:
404 DrawTargetType GetType() const override {
405 return DrawTargetType::SOFTWARE_RASTER;
408 BackendType GetBackendType() const override {
409 return BackendType::WEBRENDER_TEXT;
412 bool IsRecording() const override { return true; }
414 already_AddRefed<SourceSurface> Snapshot() override {
415 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
416 return nullptr;
419 already_AddRefed<SourceSurface> IntoLuminanceSource(
420 LuminanceType aLuminanceType, float aOpacity) override {
421 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
422 return nullptr;
425 void Flush() override {
426 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
429 void DrawSurface(SourceSurface* aSurface, const Rect& aDest,
430 const Rect& aSource, const DrawSurfaceOptions& aSurfOptions,
431 const DrawOptions& aOptions) override {
432 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
435 void DrawFilter(FilterNode* aNode, const Rect& aSourceRect,
436 const Point& aDestPoint,
437 const DrawOptions& aOptions) override {
438 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
441 void DrawSurfaceWithShadow(SourceSurface* aSurface, const Point& aDest,
442 const ShadowOptions& aShadow,
443 CompositionOp aOperator) override {
444 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
447 void ClearRect(const Rect& aRect) override {
448 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
451 void CopySurface(SourceSurface* aSurface, const IntRect& aSourceRect,
452 const IntPoint& aDestination) override {
453 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
456 void FillRect(const Rect& aRect, const Pattern& aPattern,
457 const DrawOptions& aOptions = DrawOptions()) override {
458 MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
460 if (!aRect.Intersects(GeckoClipRect().ToUnknownRect())) {
461 return;
463 auto rect = wr::ToLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
464 auto color =
465 wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
466 mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, false, false, color);
469 void StrokeRect(const Rect& aRect, const Pattern& aPattern,
470 const StrokeOptions& aStrokeOptions,
471 const DrawOptions& aOptions) override {
472 MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR &&
473 aStrokeOptions.mDashLength == 0);
475 wr::LayoutSideOffsets widths = {
476 aStrokeOptions.mLineWidth, aStrokeOptions.mLineWidth,
477 aStrokeOptions.mLineWidth, aStrokeOptions.mLineWidth};
478 wr::ColorF color =
479 wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
480 wr::BorderSide sides[4] = {{color, wr::BorderStyle::Solid},
481 {color, wr::BorderStyle::Solid},
482 {color, wr::BorderStyle::Solid},
483 {color, wr::BorderStyle::Solid}};
484 wr::BorderRadius radius = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
485 LayoutDeviceRect rect = LayoutDeviceRect::FromUnknownRect(aRect);
486 rect.Inflate(aStrokeOptions.mLineWidth / 2);
487 if (!rect.Intersects(GeckoClipRect())) {
488 return;
490 wr::LayoutRect bounds = wr::ToLayoutRect(rect);
491 mBuilder.PushBorder(bounds, ClipRect(), true, widths,
492 Range<const wr::BorderSide>(sides, 4), radius);
495 void StrokeLine(const Point& aStart, const Point& aEnd,
496 const Pattern& aPattern, const StrokeOptions& aStrokeOptions,
497 const DrawOptions& aOptions) override {
498 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
501 void Stroke(const Path* aPath, const Pattern& aPattern,
502 const StrokeOptions& aStrokeOptions,
503 const DrawOptions& aOptions) override {
504 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
507 void Fill(const Path* aPath, const Pattern& aPattern,
508 const DrawOptions& aOptions) override {
509 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
512 void StrokeGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
513 const Pattern& aPattern,
514 const StrokeOptions& aStrokeOptions,
515 const DrawOptions& aOptions) override {
516 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
519 void Mask(const Pattern& aSource, const Pattern& aMask,
520 const DrawOptions& aOptions) override {
521 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
524 void MaskSurface(const Pattern& aSource, SourceSurface* aMask, Point aOffset,
525 const DrawOptions& aOptions) override {
526 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
529 bool Draw3DTransformedSurface(SourceSurface* aSurface,
530 const Matrix4x4& aMatrix) override {
531 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
534 void PushClip(const Path* aPath) override {
535 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
538 void PushDeviceSpaceClipRects(const IntRect* aRects,
539 uint32_t aCount) override {
540 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
543 void PushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
544 const Matrix& aMaskTransform, const IntRect& aBounds,
545 bool aCopyBackground) override {
546 // Fine to pretend we do this
549 void PopLayer() override {
550 // Fine to pretend we do this
553 already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(
554 unsigned char* aData, const IntSize& aSize, int32_t aStride,
555 SurfaceFormat aFormat) const override {
556 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
557 return nullptr;
560 already_AddRefed<SourceSurface> OptimizeSourceSurface(
561 SourceSurface* aSurface) const override {
562 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
563 return nullptr;
566 already_AddRefed<SourceSurface> CreateSourceSurfaceFromNativeSurface(
567 const NativeSurface& aSurface) const override {
568 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
569 return nullptr;
572 already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
573 const IntSize& aSize, SurfaceFormat aFormat) const override {
574 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
575 return nullptr;
578 bool CanCreateSimilarDrawTarget(const IntSize& aSize,
579 SurfaceFormat aFormat) const override {
580 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
581 return false;
584 virtual RefPtr<DrawTarget> CreateClippedDrawTarget(
585 const Rect& aBounds, SurfaceFormat aFormat) override {
586 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
587 return nullptr;
590 already_AddRefed<PathBuilder> CreatePathBuilder(
591 FillRule aFillRule) const override {
592 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
593 return nullptr;
596 already_AddRefed<FilterNode> CreateFilter(FilterType aType) override {
597 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
598 return nullptr;
601 already_AddRefed<GradientStops> CreateGradientStops(
602 GradientStop* aStops, uint32_t aNumStops,
603 ExtendMode aExtendMode) const override {
604 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
605 return nullptr;
608 void DetachAllSnapshots() override {
609 MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
613 } // namespace layout
614 } // namespace mozilla
616 #endif