Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/TextDrawTarget.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
#ifndef TextDrawTarget_h
8
#define TextDrawTarget_h
9
10
#include "mozilla/gfx/2D.h"
11
#include "mozilla/layers/WebRenderLayerManager.h"
12
#include "mozilla/layers/WebRenderBridgeChild.h"
13
#include "mozilla/webrender/WebRenderAPI.h"
14
#include "mozilla/layers/StackingContextHelper.h"
15
#include "mozilla/layers/IpcResourceUpdateQueue.h"
16
17
namespace mozilla {
18
namespace layout {
19
20
using namespace gfx;
21
22
// This class is fake DrawTarget, used to intercept text draw calls, while
23
// also collecting up the other aspects of text natively.
24
//
25
// When using advanced-layers in nsDisplayText's constructor, we construct this
26
// and run the full painting algorithm with this as the DrawTarget. This is
27
// done to avoid having to massively refactor gecko's text painting code (which
28
// has lots of components shared between other rendering algorithms).
29
//
30
// In some phases of the painting algorithm, we can grab the relevant values
31
// and feed them directly into TextDrawTarget. For instance, selections,
32
// decorations, and shadows are handled in this manner. In those cases we can
33
// also short-circuit the painting algorithm to save work.
34
//
35
// In other phases, the computed values are sufficiently buried in complex
36
// code that it's best for us to just intercept the final draw calls. This
37
// is how we handle computing the glyphs of the main text and text-emphasis
38
// (see our overloaded FillGlyphs implementation).
39
//
40
// To be clear: this is a big hack. With time we hope to refactor the codebase
41
// so that all the elements of text are handled directly by TextDrawTarget,
42
// which is to say everything is done like we do selections and shadows now.
43
// This design is a good step for doing this work incrementally.
44
//
45
// This is also likely to be a bit buggy (missing or misinterpreted info)
46
// while we further develop the design.
47
//
48
// TextDrawTarget doesn't yet support all features. See mHasUnsupportedFeatures
49
// for details.
50
class TextDrawTarget : public DrawTarget
51
{
52
public:
53
  explicit TextDrawTarget(wr::DisplayListBuilder& aBuilder,
54
                          wr::IpcResourceUpdateQueue& aResources,
55
                          const layers::StackingContextHelper& aSc,
56
                          layers::WebRenderLayerManager* aManager,
57
                          nsDisplayItem* aItem,
58
                          nsRect& aBounds)
59
    : mBuilder(aBuilder), mResources(aResources), mSc(aSc), mManager(aManager)
60
0
  {
61
0
    SetPermitSubpixelAA(!aItem->IsSubpixelAADisabled());
62
0
63
0
    // Compute clip/bounds
64
0
    auto appUnitsPerDevPixel = aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
65
0
    LayoutDeviceRect layoutBoundsRect = LayoutDeviceRect::FromAppUnits(
66
0
        aBounds, appUnitsPerDevPixel);
67
0
    LayoutDeviceRect layoutClipRect = layoutBoundsRect;
68
0
    mBoundsRect = wr::ToRoundedLayoutRect(layoutBoundsRect);
69
0
70
0
    // Add 1 pixel of dirty area around clip rect to allow us to paint
71
0
    // antialiased pixels beyond the measured text extents.
72
0
    layoutClipRect.Inflate(1);
73
0
    mSize = IntSize::Ceil(layoutClipRect.Width(), layoutClipRect.Height());
74
0
    mClipStack.AppendElement(layoutClipRect);
75
0
76
0
    mBackfaceVisible = !aItem->BackfaceIsHidden();
77
0
78
0
    mBuilder.Save();
79
0
  }
80
81
  // Prevent this from being copied
82
  TextDrawTarget(const TextDrawTarget& src) = delete;
83
  TextDrawTarget& operator=(const TextDrawTarget&) = delete;
84
85
  ~TextDrawTarget()
86
0
  {
87
0
    if (mHasUnsupportedFeatures) {
88
0
      mBuilder.Restore();
89
0
    } else {
90
0
      mBuilder.ClearSave();
91
0
    }
92
0
  }
93
94
  void FoundUnsupportedFeature() { mHasUnsupportedFeatures = true; }
95
0
  bool HasUnsupportedFeatures() { return mHasUnsupportedFeatures; }
96
97
  wr::FontInstanceFlags GetWRGlyphFlags() const { return mWRGlyphFlags; }
98
  void SetWRGlyphFlags(wr::FontInstanceFlags aFlags) { mWRGlyphFlags = aFlags; }
99
100
  class AutoRestoreWRGlyphFlags
101
  {
102
  public:
103
    ~AutoRestoreWRGlyphFlags()
104
    {
105
      if (mTarget) {
106
        mTarget->SetWRGlyphFlags(mFlags);
107
      }
108
    }
109
110
    void Save(TextDrawTarget* aTarget)
111
    {
112
      // This allows for recursive saves, in case the flags need to be modified
113
      // under multiple conditions (i.e. transforms and synthetic italics),
114
      // since the flags will be restored to the first saved value in the
115
      // destructor on scope exit.
116
      if (!mTarget) {
117
        // Only record the first save with the original flags that will be restored.
118
        mTarget = aTarget;
119
        mFlags = aTarget->GetWRGlyphFlags();
120
      } else {
121
        // Ensure that this is actually a recursive save to the same target
122
        MOZ_ASSERT(mTarget == aTarget,
123
                   "Recursive save of WR glyph flags to different TextDrawTargets");
124
      }
125
    }
126
127
  private:
128
    TextDrawTarget* mTarget = nullptr;
129
    wr::FontInstanceFlags mFlags = {0};
130
  };
131
132
  // This overload just stores the glyphs/font/color.
133
  void
134
  FillGlyphs(ScaledFont* aFont,
135
             const GlyphBuffer& aBuffer,
136
             const Pattern& aPattern,
137
             const DrawOptions& aOptions) override
138
0
  {
139
0
    // Make sure we're only given boring color patterns
140
0
    MOZ_RELEASE_ASSERT(aOptions.mCompositionOp == CompositionOp::OP_OVER);
141
0
    MOZ_RELEASE_ASSERT(aOptions.mAlpha == 1.0f);
142
0
    MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
143
0
144
0
    // Make sure the font exists, and can be serialized
145
0
    MOZ_RELEASE_ASSERT(aFont);
146
0
    if (!aFont->CanSerialize()) {
147
0
      FoundUnsupportedFeature();
148
0
      return;
149
0
    }
150
0
151
0
    auto* colorPat = static_cast<const ColorPattern*>(&aPattern);
152
0
    auto color = wr::ToColorF(colorPat->mColor);
153
0
    MOZ_ASSERT(aBuffer.mNumGlyphs);
154
0
    auto glyphs = Range<const wr::GlyphInstance>(reinterpret_cast<const wr::GlyphInstance*>(aBuffer.mGlyphs), aBuffer.mNumGlyphs);
155
0
    // MSVC won't let us use offsetof on the following directly so we give it a
156
0
    // name with typedef
157
0
    typedef std::remove_reference<decltype(aBuffer.mGlyphs[0])>::type GlyphType;
158
0
    // Compare gfx::Glyph and wr::GlyphInstance to make sure that they are
159
0
    // structurally equivalent to ensure that our cast above was ok
160
0
    static_assert(std::is_same<decltype(aBuffer.mGlyphs[0].mIndex), decltype(glyphs[0].index)>()
161
0
                  && std::is_same<decltype(aBuffer.mGlyphs[0].mPosition.x), decltype(glyphs[0].point.x)>()
162
0
                  && std::is_same<decltype(aBuffer.mGlyphs[0].mPosition.y), decltype(glyphs[0].point.y)>()
163
0
                  && offsetof(GlyphType, mIndex) == offsetof(wr::GlyphInstance, index)
164
0
                  && offsetof(GlyphType, mPosition) == offsetof(wr::GlyphInstance, point)
165
0
                  && offsetof(decltype(aBuffer.mGlyphs[0].mPosition), x) == offsetof(decltype(glyphs[0].point), x)
166
0
                  && offsetof(decltype(aBuffer.mGlyphs[0].mPosition), y) == offsetof(decltype(glyphs[0].point), y)
167
0
                  && std::is_standard_layout<std::remove_reference<decltype(aBuffer.mGlyphs[0])>>::value
168
0
                  && std::is_standard_layout<std::remove_reference<decltype(glyphs[0])>>::value
169
0
                  && sizeof(aBuffer.mGlyphs[0]) == sizeof(glyphs[0])
170
0
                  && sizeof(aBuffer.mGlyphs[0].mPosition) == sizeof(glyphs[0].point)
171
0
                  , "glyph buf types don't match");
172
0
173
0
    wr::GlyphOptions glyphOptions;
174
0
    glyphOptions.render_mode = wr::ToFontRenderMode(aOptions.mAntialiasMode, GetPermitSubpixelAA());
175
0
    glyphOptions.flags = mWRGlyphFlags;
176
0
177
0
    mManager->WrBridge()->PushGlyphs(mBuilder, glyphs, aFont, color, mSc,
178
0
                                     mBoundsRect, ClipRect(), mBackfaceVisible,
179
0
                                     &glyphOptions);
180
0
  }
181
182
  void
183
0
  PushClipRect(const Rect &aRect) override {
184
0
    LayoutDeviceRect rect = LayoutDeviceRect::FromUnknownRect(aRect);
185
0
    rect = rect.Intersect(mClipStack.LastElement());
186
0
    mClipStack.AppendElement(rect);
187
0
  }
188
189
  void
190
0
  PopClip() override {
191
0
    mClipStack.RemoveLastElement();
192
0
  }
193
194
0
  IntSize GetSize() const override {
195
0
    return mSize;
196
0
  }
197
198
  void
199
  AppendShadow(const wr::Shadow& aShadow)
200
0
  {
201
0
    mBuilder.PushShadow(mBoundsRect, ClipRect(), mBackfaceVisible, aShadow);
202
0
    mHasShadows = true;
203
0
  }
204
205
  void
206
  TerminateShadows()
207
0
  {
208
0
    if (mHasShadows) {
209
0
      mBuilder.PopAllShadows();
210
0
      mHasShadows = false;
211
0
    }
212
0
  }
213
214
  void
215
  AppendSelectionRect(const LayoutDeviceRect& aRect, const Color& aColor)
216
0
  {
217
0
    auto rect = wr::ToLayoutRect(aRect);
218
0
    auto color = wr::ToColorF(aColor);
219
0
    mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, color);
220
0
  }
221
222
223
  // This function is basically designed to slide into the decoration drawing
224
  // code of nsCSSRendering with minimum disruption, to minimize the
225
  // chances of implementation drift. As such, it mostly looks like a call
226
  // to a skia-style StrokeLine method: two end-points, with a thickness
227
  // and style. Notably the end-points are *centered* in the block direction,
228
  // even though webrender wants a rect-like representation, where the points
229
  // are on corners.
230
  //
231
  // So we mangle the format here in a single centralized place, where neither
232
  // webrender nor nsCSSRendering has to care about this mismatch.
233
  //
234
  // NOTE: we assume the points are axis-aligned, and aStart should be used
235
  // as the top-left corner of the rect.
236
  void
237
  AppendDecoration(const Point& aStart,
238
                   const Point& aEnd,
239
                   const float aThickness,
240
                   const bool aVertical,
241
                   const Color& aColor,
242
                   const uint8_t aStyle)
243
0
  {
244
0
    auto pos = LayoutDevicePoint::FromUnknownPoint(aStart);
245
0
    LayoutDeviceSize size;
246
0
247
0
    if (aVertical) {
248
0
      pos.x -= aThickness / 2; // adjust from center to corner
249
0
      size = LayoutDeviceSize(aThickness, aEnd.y - aStart.y);
250
0
    } else {
251
0
      pos.y -= aThickness / 2; // adjust from center to corner
252
0
      size = LayoutDeviceSize(aEnd.x - aStart.x, aThickness);
253
0
    }
254
0
255
0
    wr::Line decoration;
256
0
    decoration.bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect(pos, size));
257
0
    decoration.wavyLineThickness = 0; // dummy value, unused
258
0
    decoration.color = wr::ToColorF(aColor);
259
0
    decoration.orientation = aVertical
260
0
      ? wr::LineOrientation::Vertical
261
0
      : wr::LineOrientation::Horizontal;
262
0
263
0
    switch (aStyle) {
264
0
      case NS_STYLE_TEXT_DECORATION_STYLE_SOLID:
265
0
        decoration.style = wr::LineStyle::Solid;
266
0
        break;
267
0
      case NS_STYLE_TEXT_DECORATION_STYLE_DOTTED:
268
0
        decoration.style = wr::LineStyle::Dotted;
269
0
        break;
270
0
      case NS_STYLE_TEXT_DECORATION_STYLE_DASHED:
271
0
        decoration.style = wr::LineStyle::Dashed;
272
0
        break;
273
0
      // Wavy lines should go through AppendWavyDecoration
274
0
      case NS_STYLE_TEXT_DECORATION_STYLE_WAVY:
275
0
      // Double lines should be lowered to two solid lines
276
0
      case NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE:
277
0
      default:
278
0
        MOZ_CRASH("TextDrawTarget received unsupported line style");
279
0
    }
280
0
281
0
    mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
282
0
  }
283
284
  // Seperated out from AppendDecoration because Wavy Lines are completely
285
  // different, and trying to merge the concept is more of a mess than it's
286
  // worth.
287
  void
288
  AppendWavyDecoration(const Rect& aBounds,
289
                       const float aThickness,
290
                       const bool aVertical,
291
                       const Color& aColor)
292
0
  {
293
0
    wr::Line decoration;
294
0
295
0
    decoration.bounds = wr::ToRoundedLayoutRect(
296
0
      LayoutDeviceRect::FromUnknownRect(aBounds));
297
0
    decoration.wavyLineThickness = aThickness;
298
0
    decoration.color = wr::ToColorF(aColor);
299
0
    decoration.orientation = aVertical
300
0
      ? wr::LineOrientation::Vertical
301
0
      : wr::LineOrientation::Horizontal;
302
0
    decoration.style = wr::LineStyle::Wavy;
303
0
304
0
    mBuilder.PushLine(ClipRect(), mBackfaceVisible, decoration);
305
0
  }
306
307
  layers::WebRenderBridgeChild* WrBridge() { return mManager->WrBridge(); }
308
  layers::WebRenderLayerManager* WrLayerManager() { return mManager; }
309
310
  Maybe<wr::ImageKey>
311
  DefineImage(const IntSize& aSize,
312
              uint32_t aStride,
313
              SurfaceFormat aFormat,
314
              const uint8_t* aData)
315
  {
316
    wr::ImageKey key = mManager->WrBridge()->GetNextImageKey();
317
    wr::ImageDescriptor desc(aSize, aStride, aFormat);
318
    Range<uint8_t> bytes(const_cast<uint8_t*>(aData), aStride * aSize.height);
319
    if (mResources.AddImage(key, desc, bytes)) {
320
        return Some(key);
321
    }
322
    return Nothing();
323
  }
324
325
  void PushImage(wr::ImageKey aKey,
326
                 const wr::LayoutRect& aBounds,
327
                 const wr::LayoutRect& aClip,
328
                 wr::ImageRendering aFilter,
329
                 const wr::ColorF& aColor)
330
  {
331
    mBuilder.PushImage(aBounds, aClip, true, aFilter, aKey, true, aColor);
332
  }
333
334
private:
335
  wr::LayoutRect ClipRect()
336
0
  {
337
0
    return wr::ToRoundedLayoutRect(mClipStack.LastElement());
338
0
  }
339
  // Whether anything unsupported was encountered. Currently:
340
  //
341
  // * Synthetic bold/italics
342
  // * SVG fonts
343
  // * Unserializable fonts
344
  // * Tofu glyphs
345
  // * Pratial ligatures
346
  // * Text writing-mode
347
  // * Text stroke
348
  bool mHasUnsupportedFeatures = false;
349
350
  // Whether PopAllShadows needs to be called
351
  bool mHasShadows = false;
352
353
  // Things used to push to webrender
354
  wr::DisplayListBuilder& mBuilder;
355
  wr::IpcResourceUpdateQueue& mResources;
356
  const layers::StackingContextHelper& mSc;
357
  layers::WebRenderLayerManager* mManager;
358
359
  // Computed facts
360
  IntSize mSize;
361
  wr::LayoutRect mBoundsRect;
362
  nsTArray<LayoutDeviceRect> mClipStack;
363
  bool mBackfaceVisible;
364
365
  wr::FontInstanceFlags mWRGlyphFlags = {0};
366
367
  // The rest of this is dummy implementations of DrawTarget's API
368
public:
369
0
  DrawTargetType GetType() const override {
370
0
    return DrawTargetType::SOFTWARE_RASTER;
371
0
  }
372
373
0
  BackendType GetBackendType() const override {
374
0
    return BackendType::WEBRENDER_TEXT;
375
0
  }
376
377
0
  bool IsRecording() const override { return true; }
378
0
  bool IsCaptureDT() const override { return false; }
379
380
0
  already_AddRefed<SourceSurface> Snapshot() override {
381
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
382
0
    return nullptr;
383
0
  }
384
385
  already_AddRefed<SourceSurface> IntoLuminanceSource(LuminanceType aLuminanceType,
386
0
                                                      float aOpacity) override {
387
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
388
0
    return nullptr;
389
0
  }
390
391
0
  void Flush() override {
392
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
393
0
  }
394
395
  void DrawCapturedDT(DrawTargetCapture *aCaptureDT,
396
0
                      const Matrix& aTransform) override {
397
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
398
0
  }
399
400
  void DrawSurface(SourceSurface *aSurface,
401
                   const Rect &aDest,
402
                   const Rect &aSource,
403
                   const DrawSurfaceOptions &aSurfOptions,
404
0
                   const DrawOptions &aOptions) override {
405
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
406
0
  }
407
408
  void DrawFilter(FilterNode *aNode,
409
                          const Rect &aSourceRect,
410
                          const Point &aDestPoint,
411
0
                          const DrawOptions &aOptions) override {
412
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
413
0
  }
414
415
  void DrawSurfaceWithShadow(SourceSurface *aSurface,
416
                             const Point &aDest,
417
                             const Color &aColor,
418
                             const Point &aOffset,
419
                             Float aSigma,
420
0
                             CompositionOp aOperator) override {
421
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
422
0
  }
423
424
0
  void ClearRect(const Rect &aRect) override {
425
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
426
0
  }
427
428
  void CopySurface(SourceSurface *aSurface,
429
                   const IntRect &aSourceRect,
430
0
                   const IntPoint &aDestination) override {
431
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
432
0
  }
433
434
  void FillRect(const Rect &aRect,
435
                const Pattern &aPattern,
436
0
                const DrawOptions &aOptions = DrawOptions()) override {
437
0
    MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR);
438
0
439
0
    auto rect = wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(aRect));
440
0
    auto color = wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
441
0
    mBuilder.PushRect(rect, ClipRect(), mBackfaceVisible, color);
442
0
  }
443
444
  void StrokeRect(const Rect &aRect,
445
                  const Pattern &aPattern,
446
                  const StrokeOptions &aStrokeOptions,
447
0
                  const DrawOptions &aOptions) override {
448
0
    MOZ_RELEASE_ASSERT(aPattern.GetType() == PatternType::COLOR &&
449
0
                       aStrokeOptions.mDashLength == 0);
450
0
451
0
    wr::LayoutSideOffsets widths = {
452
0
        aStrokeOptions.mLineWidth,
453
0
        aStrokeOptions.mLineWidth,
454
0
        aStrokeOptions.mLineWidth,
455
0
        aStrokeOptions.mLineWidth
456
0
    };
457
0
    wr::ColorF color = wr::ToColorF(static_cast<const ColorPattern&>(aPattern).mColor);
458
0
    wr::BorderSide sides[4] = {
459
0
        { color, wr::BorderStyle::Solid },
460
0
        { color, wr::BorderStyle::Solid },
461
0
        { color, wr::BorderStyle::Solid },
462
0
        { color, wr::BorderStyle::Solid }
463
0
    };
464
0
    wr::BorderRadius radius = {
465
0
        { 0, 0 },
466
0
        { 0, 0 },
467
0
        { 0, 0 },
468
0
        { 0, 0 }
469
0
    };
470
0
    Rect rect(aRect);
471
0
    rect.Inflate(aStrokeOptions.mLineWidth / 2);
472
0
    wr::LayoutRect bounds = wr::ToRoundedLayoutRect(LayoutDeviceRect::FromUnknownRect(rect));
473
0
    mBuilder.PushBorder(bounds, ClipRect(), true, widths, Range<const wr::BorderSide>(sides, 4), radius);
474
0
  }
475
476
  void StrokeLine(const Point &aStart,
477
                  const Point &aEnd,
478
                  const Pattern &aPattern,
479
                  const StrokeOptions &aStrokeOptions,
480
0
                  const DrawOptions &aOptions) override {
481
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
482
0
  }
483
484
485
  void Stroke(const Path *aPath,
486
              const Pattern &aPattern,
487
              const StrokeOptions &aStrokeOptions,
488
0
              const DrawOptions &aOptions) override {
489
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
490
0
  }
491
492
  void Fill(const Path *aPath,
493
            const Pattern &aPattern,
494
0
            const DrawOptions &aOptions) override {
495
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
496
0
  }
497
498
  void StrokeGlyphs(ScaledFont* aFont,
499
                    const GlyphBuffer& aBuffer,
500
                    const Pattern& aPattern,
501
                    const StrokeOptions& aStrokeOptions,
502
0
                    const DrawOptions& aOptions) override {
503
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
504
0
  }
505
506
  void Mask(const Pattern &aSource,
507
                    const Pattern &aMask,
508
0
                    const DrawOptions &aOptions) override {
509
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
510
0
  }
511
512
  void MaskSurface(const Pattern &aSource,
513
                   SourceSurface *aMask,
514
                   Point aOffset,
515
0
                   const DrawOptions &aOptions) override {
516
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
517
0
  }
518
519
  bool Draw3DTransformedSurface(SourceSurface* aSurface,
520
0
                                const Matrix4x4& aMatrix) override {
521
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
522
0
  }
523
524
0
  void PushClip(const Path *aPath) override {
525
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
526
0
  }
527
528
0
  void PushDeviceSpaceClipRects(const IntRect* aRects, uint32_t aCount) override {
529
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
530
0
  }
531
532
533
534
  void PushLayer(bool aOpaque, Float aOpacity,
535
                         SourceSurface* aMask,
536
                         const Matrix& aMaskTransform,
537
                         const IntRect& aBounds,
538
0
                         bool aCopyBackground) override {
539
0
    // Fine to pretend we do this
540
0
  }
541
542
0
  void PopLayer() override {
543
0
    // Fine to pretend we do this
544
0
  }
545
546
547
  already_AddRefed<SourceSurface> CreateSourceSurfaceFromData(unsigned char *aData,
548
                                                              const IntSize &aSize,
549
                                                              int32_t aStride,
550
0
                                                              SurfaceFormat aFormat) const override {
551
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
552
0
    return nullptr;
553
0
  }
554
555
0
  already_AddRefed<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const override {
556
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
557
0
    return nullptr;
558
0
  }
559
560
  already_AddRefed<SourceSurface>
561
0
  CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const override {
562
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
563
0
    return nullptr;
564
0
  }
565
566
  already_AddRefed<DrawTarget>
567
0
  CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override {
568
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
569
0
    return nullptr;
570
0
  }
571
572
0
  already_AddRefed<PathBuilder> CreatePathBuilder(FillRule aFillRule) const override {
573
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
574
0
    return nullptr;
575
0
  }
576
577
0
  already_AddRefed<FilterNode> CreateFilter(FilterType aType) override {
578
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
579
0
    return nullptr;
580
0
  }
581
582
  already_AddRefed<GradientStops>
583
  CreateGradientStops(GradientStop *aStops,
584
                      uint32_t aNumStops,
585
0
                      ExtendMode aExtendMode) const override {
586
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
587
0
    return nullptr;
588
0
  }
589
590
0
  void* GetNativeSurface(NativeSurfaceType aType) override {
591
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
592
0
    return nullptr;
593
0
  }
594
595
0
  void DetachAllSnapshots() override {
596
0
    MOZ_CRASH("TextDrawTarget: Method shouldn't be called");
597
0
  }
598
};
599
600
}
601
}
602
603
#endif