tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

RecordedEventImpl.h (143146B)


      1 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #ifndef MOZILLA_GFX_RECORDEDEVENTIMPL_H_
      7 #define MOZILLA_GFX_RECORDEDEVENTIMPL_H_
      8 
      9 #include "RecordedEvent.h"
     10 
     11 #include "PathRecording.h"
     12 #include "RecordingTypes.h"
     13 #include "Tools.h"
     14 #include "Filters.h"
     15 #include "Logging.h"
     16 #include "ScaledFontBase.h"
     17 #include "SFNTData.h"
     18 
     19 #include "mozilla/dom/CanvasRenderingContextHelper.h"
     20 #include "mozilla/layers/BuildConstants.h"
     21 #include "mozilla/layers/LayersSurfaces.h"
     22 #include "mozilla/ipc/SerializeToBytesUtil.h"
     23 
     24 namespace mozilla {
     25 namespace gfx {
     26 
     27 class RecordedDrawTargetCreation
     28    : public RecordedEventDerived<RecordedDrawTargetCreation> {
     29 public:
     30  RecordedDrawTargetCreation(ReferencePtr aRefPtr, BackendType aType,
     31                             const IntRect& aRect, SurfaceFormat aFormat,
     32                             bool aHasExistingData = false,
     33                             SourceSurface* aExistingData = nullptr)
     34      : RecordedEventDerived(DRAWTARGETCREATION),
     35        mRefPtr(aRefPtr),
     36        mBackendType(aType),
     37        mRect(aRect),
     38        mFormat(aFormat),
     39        mHasExistingData(aHasExistingData),
     40        mExistingData(aExistingData) {}
     41 
     42  bool PlayEvent(Translator* aTranslator) const override;
     43 
     44  template <class S>
     45  void Record(S& aStream) const;
     46  virtual void OutputSimpleEventInfo(
     47      std::stringstream& aStringStream) const override;
     48 
     49  std::string GetName() const override { return "DrawTarget Creation"; }
     50 
     51  ReferencePtr mRefPtr;
     52  BackendType mBackendType;
     53  IntRect mRect;
     54  SurfaceFormat mFormat;
     55  bool mHasExistingData = false;
     56  RefPtr<SourceSurface> mExistingData;
     57 
     58 private:
     59  friend class RecordedEvent;
     60 
     61  template <class S>
     62  MOZ_IMPLICIT RecordedDrawTargetCreation(S& aStream);
     63 };
     64 
     65 class RecordedDrawTargetDestruction
     66    : public RecordedEventDerived<RecordedDrawTargetDestruction> {
     67 public:
     68  MOZ_IMPLICIT RecordedDrawTargetDestruction(ReferencePtr aRefPtr)
     69      : RecordedEventDerived(DRAWTARGETDESTRUCTION),
     70        mRefPtr(aRefPtr),
     71        mBackendType(BackendType::NONE) {}
     72 
     73  bool PlayEvent(Translator* aTranslator) const override;
     74 
     75  template <class S>
     76  void Record(S& aStream) const;
     77  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
     78 
     79  std::string GetName() const override { return "DrawTarget Destruction"; }
     80 
     81  ReferencePtr mRefPtr;
     82 
     83  BackendType mBackendType;
     84 
     85 private:
     86  friend class RecordedEvent;
     87 
     88  template <class S>
     89  MOZ_IMPLICIT RecordedDrawTargetDestruction(S& aStream);
     90 };
     91 
     92 class RecordedSetCurrentDrawTarget
     93    : public RecordedEventDerived<RecordedSetCurrentDrawTarget> {
     94 public:
     95  MOZ_IMPLICIT RecordedSetCurrentDrawTarget(ReferencePtr aRefPtr)
     96      : RecordedEventDerived(SETCURRENTDRAWTARGET), mRefPtr(aRefPtr) {}
     97 
     98  bool PlayEvent(Translator* aTranslator) const override;
     99 
    100  template <class S>
    101  void Record(S& aStream) const;
    102  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    103 
    104  std::string GetName() const override { return "SetCurrentDrawTarget"; }
    105 
    106  ReferencePtr mRefPtr;
    107 
    108 private:
    109  friend class RecordedEvent;
    110 
    111  template <class S>
    112  MOZ_IMPLICIT RecordedSetCurrentDrawTarget(S& aStream);
    113 };
    114 
    115 class RecordedCreateSimilarDrawTarget
    116    : public RecordedEventDerived<RecordedCreateSimilarDrawTarget> {
    117 public:
    118  RecordedCreateSimilarDrawTarget(ReferencePtr aRefPtr, const IntSize& aSize,
    119                                  SurfaceFormat aFormat)
    120      : RecordedEventDerived(CREATESIMILARDRAWTARGET),
    121        mRefPtr(aRefPtr),
    122        mSize(aSize),
    123        mFormat(aFormat) {}
    124 
    125  bool PlayEvent(Translator* aTranslator) const override;
    126 
    127  template <class S>
    128  void Record(S& aStream) const;
    129  virtual void OutputSimpleEventInfo(
    130      std::stringstream& aStringStream) const override;
    131 
    132  std::string GetName() const override { return "CreateSimilarDrawTarget"; }
    133 
    134  ReferencePtr mRefPtr;
    135  IntSize mSize;
    136  SurfaceFormat mFormat;
    137 
    138 private:
    139  friend class RecordedEvent;
    140 
    141  template <class S>
    142  MOZ_IMPLICIT RecordedCreateSimilarDrawTarget(S& aStream);
    143 };
    144 
    145 class RecordedCreateClippedDrawTarget
    146    : public RecordedEventDerived<RecordedCreateClippedDrawTarget> {
    147 public:
    148  RecordedCreateClippedDrawTarget(ReferencePtr aRefPtr, const Rect& aBounds,
    149                                  SurfaceFormat aFormat)
    150      : RecordedEventDerived(CREATECLIPPEDDRAWTARGET),
    151        mRefPtr(aRefPtr),
    152        mBounds(aBounds),
    153        mFormat(aFormat) {}
    154 
    155  bool PlayEvent(Translator* aTranslator) const override;
    156 
    157  template <class S>
    158  void Record(S& aStream) const;
    159  virtual void OutputSimpleEventInfo(
    160      std::stringstream& aStringStream) const override;
    161 
    162  std::string GetName() const override { return "CreateClippedDrawTarget"; }
    163 
    164  ReferencePtr mRefPtr;
    165  Rect mBounds;
    166  SurfaceFormat mFormat;
    167 
    168 private:
    169  friend class RecordedEvent;
    170 
    171  template <class S>
    172  MOZ_IMPLICIT RecordedCreateClippedDrawTarget(S& aStream);
    173 };
    174 
    175 class RecordedCreateDrawTargetForFilter
    176    : public RecordedEventDerived<RecordedCreateDrawTargetForFilter> {
    177 public:
    178  RecordedCreateDrawTargetForFilter(ReferencePtr aRefPtr,
    179                                    const IntSize& aMaxSize,
    180                                    SurfaceFormat aFormat, FilterNode* aFilter,
    181                                    FilterNode* aSource,
    182                                    const Rect& aSourceRect,
    183                                    const Point& aDestPoint)
    184      : RecordedEventDerived(CREATEDRAWTARGETFORFILTER),
    185        mRefPtr(aRefPtr),
    186        mMaxSize(aMaxSize),
    187        mFormat(aFormat),
    188        mFilter(aFilter),
    189        mSource(aSource),
    190        mSourceRect(aSourceRect),
    191        mDestPoint(aDestPoint) {}
    192 
    193  bool PlayEvent(Translator* aTranslator) const override;
    194 
    195  template <class S>
    196  void Record(S& aStream) const;
    197  virtual void OutputSimpleEventInfo(
    198      std::stringstream& aStringStream) const override;
    199 
    200  std::string GetName() const override {
    201    return "CreateSimilarDrawTargetForFilter";
    202  }
    203 
    204  ReferencePtr mRefPtr;
    205  IntSize mMaxSize;
    206  SurfaceFormat mFormat;
    207  ReferencePtr mFilter;
    208  ReferencePtr mSource;
    209  Rect mSourceRect;
    210  Point mDestPoint;
    211 
    212 private:
    213  friend class RecordedEvent;
    214 
    215  template <class S>
    216  MOZ_IMPLICIT RecordedCreateDrawTargetForFilter(S& aStream);
    217 };
    218 
    219 class RecordedFillRect : public RecordedEventDerived<RecordedFillRect> {
    220 public:
    221  RecordedFillRect(const Rect& aRect, const Pattern& aPattern,
    222                   const DrawOptions& aOptions)
    223      : RecordedEventDerived(FILLRECT),
    224        mRect(aRect),
    225        mPattern(),
    226        mOptions(aOptions) {
    227    StorePattern(mPattern, aPattern);
    228  }
    229 
    230  bool PlayEvent(Translator* aTranslator) const override;
    231 
    232  template <class S>
    233  void Record(S& aStream) const;
    234  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    235 
    236  std::string GetName() const override { return "FillRect"; }
    237 
    238 private:
    239  friend class RecordedEvent;
    240 
    241  template <class S>
    242  MOZ_IMPLICIT RecordedFillRect(S& aStream);
    243 
    244  Rect mRect;
    245  PatternStorage mPattern;
    246  DrawOptions mOptions;
    247 };
    248 
    249 class RecordedStrokeRect : public RecordedEventDerived<RecordedStrokeRect>,
    250                           public RecordedStrokeOptionsMixin {
    251 public:
    252  RecordedStrokeRect(const Rect& aRect, const Pattern& aPattern,
    253                     const StrokeOptions& aStrokeOptions,
    254                     const DrawOptions& aOptions)
    255      : RecordedEventDerived(STROKERECT),
    256        mRect(aRect),
    257        mPattern(),
    258        mStrokeOptions(aStrokeOptions),
    259        mOptions(aOptions) {
    260    StorePattern(mPattern, aPattern);
    261  }
    262 
    263  bool PlayEvent(Translator* aTranslator) const override;
    264 
    265  template <class S>
    266  void Record(S& aStream) const;
    267  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    268 
    269  std::string GetName() const override { return "StrokeRect"; }
    270 
    271 private:
    272  friend class RecordedEvent;
    273 
    274  template <class S>
    275  MOZ_IMPLICIT RecordedStrokeRect(S& aStream);
    276 
    277  Rect mRect;
    278  PatternStorage mPattern;
    279  StrokeOptions mStrokeOptions;
    280  DrawOptions mOptions;
    281 };
    282 
    283 class RecordedStrokeLine : public RecordedEventDerived<RecordedStrokeLine>,
    284                           public RecordedStrokeOptionsMixin {
    285 public:
    286  RecordedStrokeLine(const Point& aBegin, const Point& aEnd,
    287                     const Pattern& aPattern,
    288                     const StrokeOptions& aStrokeOptions,
    289                     const DrawOptions& aOptions)
    290      : RecordedEventDerived(STROKELINE),
    291        mBegin(aBegin),
    292        mEnd(aEnd),
    293        mPattern(),
    294        mStrokeOptions(aStrokeOptions),
    295        mOptions(aOptions) {
    296    StorePattern(mPattern, aPattern);
    297  }
    298 
    299  bool PlayEvent(Translator* aTranslator) const override;
    300 
    301  template <class S>
    302  void Record(S& aStream) const;
    303  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    304 
    305  std::string GetName() const override { return "StrokeLine"; }
    306 
    307 private:
    308  friend class RecordedEvent;
    309 
    310  template <class S>
    311  MOZ_IMPLICIT RecordedStrokeLine(S& aStream);
    312 
    313  Point mBegin;
    314  Point mEnd;
    315  PatternStorage mPattern;
    316  StrokeOptions mStrokeOptions;
    317  DrawOptions mOptions;
    318 };
    319 
    320 class RecordedStrokeCircle : public RecordedEventDerived<RecordedStrokeCircle>,
    321                             public RecordedStrokeOptionsMixin {
    322 public:
    323  RecordedStrokeCircle(Circle aCircle, const Pattern& aPattern,
    324                       const StrokeOptions& aStrokeOptions,
    325                       const DrawOptions& aOptions)
    326      : RecordedEventDerived(STROKECIRCLE),
    327        mCircle(aCircle),
    328        mPattern(),
    329        mStrokeOptions(aStrokeOptions),
    330        mOptions(aOptions) {
    331    StorePattern(mPattern, aPattern);
    332  }
    333 
    334  bool PlayEvent(Translator* aTranslator) const override;
    335 
    336  template <class S>
    337  void Record(S& aStream) const;
    338  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    339 
    340  std::string GetName() const override { return "StrokeCircle"; }
    341 
    342 private:
    343  friend class RecordedEvent;
    344 
    345  template <class S>
    346  MOZ_IMPLICIT RecordedStrokeCircle(S& aStream);
    347 
    348  Circle mCircle;
    349  PatternStorage mPattern;
    350  StrokeOptions mStrokeOptions;
    351  DrawOptions mOptions;
    352 };
    353 
    354 class RecordedFill : public RecordedEventDerived<RecordedFill> {
    355 public:
    356  RecordedFill(ReferencePtr aPath, const Pattern& aPattern,
    357               const DrawOptions& aOptions)
    358      : RecordedEventDerived(FILL),
    359        mPath(aPath),
    360        mPattern(),
    361        mOptions(aOptions) {
    362    StorePattern(mPattern, aPattern);
    363  }
    364 
    365  bool PlayEvent(Translator* aTranslator) const override;
    366 
    367  template <class S>
    368  void Record(S& aStream) const;
    369  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    370 
    371  std::string GetName() const override { return "Fill"; }
    372 
    373 private:
    374  friend class RecordedEvent;
    375 
    376  template <class S>
    377  MOZ_IMPLICIT RecordedFill(S& aStream);
    378 
    379  ReferencePtr mPath;
    380  PatternStorage mPattern;
    381  DrawOptions mOptions;
    382 };
    383 
    384 class RecordedFillCircle : public RecordedEventDerived<RecordedFillCircle> {
    385 public:
    386  RecordedFillCircle(Circle aCircle, const Pattern& aPattern,
    387                     const DrawOptions& aOptions)
    388      : RecordedEventDerived(FILLCIRCLE),
    389        mCircle(aCircle),
    390        mPattern(),
    391        mOptions(aOptions) {
    392    StorePattern(mPattern, aPattern);
    393  }
    394 
    395  bool PlayEvent(Translator* aTranslator) const override;
    396 
    397  template <class S>
    398  void Record(S& aStream) const;
    399  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    400 
    401  std::string GetName() const override { return "FillCircle"; }
    402 
    403 private:
    404  friend class RecordedEvent;
    405 
    406  template <class S>
    407  MOZ_IMPLICIT RecordedFillCircle(S& aStream);
    408 
    409  Circle mCircle;
    410  PatternStorage mPattern;
    411  DrawOptions mOptions;
    412 };
    413 
    414 template <class Derived>
    415 class RecordedDrawGlyphs : public RecordedEventDerived<Derived> {
    416 public:
    417  RecordedDrawGlyphs(RecordedEvent::EventType aType, ReferencePtr aScaledFont,
    418                     const Pattern& aPattern, const DrawOptions& aOptions,
    419                     const Glyph* aGlyphs, uint32_t aNumGlyphs)
    420      : RecordedEventDerived<Derived>(aType),
    421        mScaledFont(aScaledFont),
    422        mPattern(),
    423        mOptions(aOptions) {
    424    this->StorePattern(mPattern, aPattern);
    425    mGlyphs.Assign(aGlyphs, aNumGlyphs);
    426  }
    427 
    428  bool PlayEvent(Translator* aTranslator) const override;
    429 
    430  template <class S>
    431  void Record(S& aStream) const;
    432  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    433 
    434 protected:
    435  friend class RecordedEvent;
    436 
    437  template <class S>
    438  RecordedDrawGlyphs(RecordedEvent::EventType aType, S& aStream);
    439 
    440  virtual void DrawGlyphs(DrawTarget* aDT, ScaledFont* aScaledFont,
    441                          const GlyphBuffer& aBuffer,
    442                          const Pattern& aPattern) const = 0;
    443 
    444  ReferencePtr mScaledFont;
    445  PatternStorage mPattern;
    446  DrawOptions mOptions;
    447  RecordedEventArray<Glyph, uint32_t> mGlyphs;
    448 };
    449 
    450 class RecordedFillGlyphs : public RecordedDrawGlyphs<RecordedFillGlyphs> {
    451 public:
    452  RecordedFillGlyphs(ReferencePtr aScaledFont, const Pattern& aPattern,
    453                     const DrawOptions& aOptions, const Glyph* aGlyphs,
    454                     uint32_t aNumGlyphs)
    455      : RecordedDrawGlyphs(FILLGLYPHS, aScaledFont, aPattern, aOptions, aGlyphs,
    456                           aNumGlyphs) {}
    457 
    458  std::string GetName() const override { return "FillGlyphs"; }
    459 
    460 private:
    461  friend class RecordedEvent;
    462 
    463  template <class S>
    464  MOZ_IMPLICIT RecordedFillGlyphs(S& aStream)
    465      : RecordedDrawGlyphs(FILLGLYPHS, aStream) {}
    466 
    467  void DrawGlyphs(DrawTarget* aDT, ScaledFont* aScaledFont,
    468                  const GlyphBuffer& aBuffer,
    469                  const Pattern& aPattern) const override {
    470    aDT->FillGlyphs(aScaledFont, aBuffer, aPattern, mOptions);
    471  }
    472 };
    473 
    474 class RecordedStrokeGlyphs : public RecordedDrawGlyphs<RecordedStrokeGlyphs>,
    475                             public RecordedStrokeOptionsMixin {
    476 public:
    477  RecordedStrokeGlyphs(ReferencePtr aScaledFont, const Pattern& aPattern,
    478                       const StrokeOptions& aStrokeOptions,
    479                       const DrawOptions& aOptions, const Glyph* aGlyphs,
    480                       uint32_t aNumGlyphs)
    481      : RecordedDrawGlyphs(STROKEGLYPHS, aScaledFont, aPattern, aOptions,
    482                           aGlyphs, aNumGlyphs),
    483        mStrokeOptions(aStrokeOptions) {}
    484 
    485  std::string GetName() const override { return "StrokeGlyphs"; }
    486 
    487  template <class S>
    488  void Record(S& aStream) const {
    489    RecordedDrawGlyphs::Record(aStream);
    490    RecordStrokeOptions(aStream, mStrokeOptions);
    491  }
    492 
    493 private:
    494  friend class RecordedEvent;
    495 
    496  template <class S>
    497  MOZ_IMPLICIT RecordedStrokeGlyphs(S& aStream)
    498      : RecordedDrawGlyphs(STROKEGLYPHS, aStream) {
    499    ReadStrokeOptions(aStream, mStrokeOptions);
    500  }
    501 
    502  void DrawGlyphs(DrawTarget* aDT, ScaledFont* aScaledFont,
    503                  const GlyphBuffer& aBuffer,
    504                  const Pattern& aPattern) const override {
    505    aDT->StrokeGlyphs(aScaledFont, aBuffer, aPattern, mStrokeOptions, mOptions);
    506  }
    507 
    508  StrokeOptions mStrokeOptions;
    509 };
    510 
    511 class RecordedMask : public RecordedEventDerived<RecordedMask> {
    512 public:
    513  RecordedMask(const Pattern& aSource, const Pattern& aMask,
    514               const DrawOptions& aOptions)
    515      : RecordedEventDerived(MASK), mSource(), mMask(), mOptions(aOptions) {
    516    StorePattern(mSource, aSource);
    517    StorePattern(mMask, aMask);
    518  }
    519 
    520  bool PlayEvent(Translator* aTranslator) const override;
    521 
    522  template <class S>
    523  void Record(S& aStream) const;
    524  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    525 
    526  std::string GetName() const override { return "Mask"; }
    527 
    528 private:
    529  friend class RecordedEvent;
    530 
    531  template <class S>
    532  MOZ_IMPLICIT RecordedMask(S& aStream);
    533 
    534  PatternStorage mSource;
    535  PatternStorage mMask;
    536  DrawOptions mOptions;
    537 };
    538 
    539 class RecordedStroke : public RecordedEventDerived<RecordedStroke>,
    540                       public RecordedStrokeOptionsMixin {
    541 public:
    542  RecordedStroke(ReferencePtr aPath, const Pattern& aPattern,
    543                 const StrokeOptions& aStrokeOptions,
    544                 const DrawOptions& aOptions)
    545      : RecordedEventDerived(STROKE),
    546        mPath(aPath),
    547        mPattern(),
    548        mStrokeOptions(aStrokeOptions),
    549        mOptions(aOptions) {
    550    StorePattern(mPattern, aPattern);
    551  }
    552 
    553  bool PlayEvent(Translator* aTranslator) const override;
    554 
    555  template <class S>
    556  void Record(S& aStream) const;
    557  virtual void OutputSimpleEventInfo(
    558      std::stringstream& aStringStream) const override;
    559 
    560  std::string GetName() const override { return "Stroke"; }
    561 
    562 private:
    563  friend class RecordedEvent;
    564 
    565  template <class S>
    566  MOZ_IMPLICIT RecordedStroke(S& aStream);
    567 
    568  ReferencePtr mPath;
    569  PatternStorage mPattern;
    570  StrokeOptions mStrokeOptions;
    571  DrawOptions mOptions;
    572 };
    573 
    574 class RecordedClearRect : public RecordedEventDerived<RecordedClearRect> {
    575 public:
    576  explicit RecordedClearRect(const Rect& aRect)
    577      : RecordedEventDerived(CLEARRECT), mRect(aRect) {}
    578 
    579  bool PlayEvent(Translator* aTranslator) const override;
    580 
    581  template <class S>
    582  void Record(S& aStream) const;
    583  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    584 
    585  std::string GetName() const override { return "ClearRect"; }
    586 
    587 private:
    588  friend class RecordedEvent;
    589 
    590  template <class S>
    591  MOZ_IMPLICIT RecordedClearRect(S& aStream);
    592 
    593  Rect mRect;
    594 };
    595 
    596 class RecordedCopySurface : public RecordedEventDerived<RecordedCopySurface> {
    597 public:
    598  RecordedCopySurface(ReferencePtr aSourceSurface, const IntRect& aSourceRect,
    599                      const IntPoint& aDest)
    600      : RecordedEventDerived(COPYSURFACE),
    601        mSourceSurface(aSourceSurface),
    602        mSourceRect(aSourceRect),
    603        mDest(aDest) {}
    604 
    605  bool PlayEvent(Translator* aTranslator) const override;
    606 
    607  template <class S>
    608  void Record(S& aStream) const;
    609  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    610 
    611  std::string GetName() const override { return "CopySurface"; }
    612 
    613 private:
    614  friend class RecordedEvent;
    615 
    616  template <class S>
    617  MOZ_IMPLICIT RecordedCopySurface(S& aStream);
    618 
    619  ReferencePtr mSourceSurface;
    620  IntRect mSourceRect;
    621  IntPoint mDest;
    622 };
    623 
    624 class RecordedPushClip : public RecordedEventDerived<RecordedPushClip> {
    625 public:
    626  explicit RecordedPushClip(ReferencePtr aPath)
    627      : RecordedEventDerived(PUSHCLIP), mPath(aPath) {}
    628 
    629  bool PlayEvent(Translator* aTranslator) const override;
    630 
    631  template <class S>
    632  void Record(S& aStream) const;
    633  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    634 
    635  std::string GetName() const override { return "PushClip"; }
    636 
    637 private:
    638  friend class RecordedEvent;
    639 
    640  template <class S>
    641  MOZ_IMPLICIT RecordedPushClip(S& aStream);
    642 
    643  ReferencePtr mPath;
    644 };
    645 
    646 class RecordedPushClipRect : public RecordedEventDerived<RecordedPushClipRect> {
    647 public:
    648  explicit RecordedPushClipRect(const Rect& aRect)
    649      : RecordedEventDerived(PUSHCLIPRECT), mRect(aRect) {}
    650 
    651  bool PlayEvent(Translator* aTranslator) const override;
    652 
    653  template <class S>
    654  void Record(S& aStream) const;
    655  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    656 
    657  std::string GetName() const override { return "PushClipRect"; }
    658 
    659 private:
    660  friend class RecordedEvent;
    661 
    662  template <class S>
    663  MOZ_IMPLICIT RecordedPushClipRect(S& aStream);
    664 
    665  Rect mRect;
    666 };
    667 
    668 class RecordedPopClip : public RecordedEventDerived<RecordedPopClip> {
    669 public:
    670  MOZ_IMPLICIT RecordedPopClip() : RecordedEventDerived(POPCLIP) {}
    671 
    672  bool PlayEvent(Translator* aTranslator) const override;
    673 
    674  template <class S>
    675  void Record(S& aStream) const;
    676  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    677 
    678  std::string GetName() const override { return "PopClip"; }
    679 
    680 private:
    681  friend class RecordedEvent;
    682 
    683  template <class S>
    684  MOZ_IMPLICIT RecordedPopClip(S& aStream);
    685 };
    686 
    687 class RecordedRemoveAllClips
    688    : public RecordedEventDerived<RecordedRemoveAllClips> {
    689 public:
    690  MOZ_IMPLICIT RecordedRemoveAllClips()
    691      : RecordedEventDerived(REMOVEALLCLIPS) {}
    692 
    693  bool PlayEvent(Translator* aTranslator) const override;
    694 
    695  template <class S>
    696  void Record(S& aStream) const;
    697  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    698 
    699  std::string GetName() const override { return "RemoveAllClips"; }
    700 
    701 private:
    702  friend class RecordedEvent;
    703 
    704  template <class S>
    705  MOZ_IMPLICIT RecordedRemoveAllClips(S& aStream);
    706 };
    707 
    708 class RecordedPushLayer : public RecordedEventDerived<RecordedPushLayer> {
    709 public:
    710  RecordedPushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
    711                    const Matrix& aMaskTransform, const IntRect& aBounds,
    712                    bool aCopyBackground)
    713      : RecordedEventDerived(PUSHLAYER),
    714        mOpaque(aOpaque),
    715        mOpacity(aOpacity),
    716        mMask(aMask),
    717        mMaskTransform(aMaskTransform),
    718        mBounds(aBounds),
    719        mCopyBackground(aCopyBackground) {}
    720 
    721  bool PlayEvent(Translator* aTranslator) const override;
    722 
    723  template <class S>
    724  void Record(S& aStream) const;
    725  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    726 
    727  std::string GetName() const override { return "PushLayer"; }
    728 
    729 private:
    730  friend class RecordedEvent;
    731 
    732  template <class S>
    733  MOZ_IMPLICIT RecordedPushLayer(S& aStream);
    734 
    735  bool mOpaque = false;
    736  Float mOpacity = 1.0f;
    737  ReferencePtr mMask;
    738  Matrix mMaskTransform;
    739  IntRect mBounds;
    740  bool mCopyBackground = false;
    741 };
    742 
    743 class RecordedPushLayerWithBlend
    744    : public RecordedEventDerived<RecordedPushLayerWithBlend> {
    745 public:
    746  RecordedPushLayerWithBlend(bool aOpaque, Float aOpacity, SourceSurface* aMask,
    747                             const Matrix& aMaskTransform,
    748                             const IntRect& aBounds, bool aCopyBackground,
    749                             CompositionOp aCompositionOp)
    750      : RecordedEventDerived(PUSHLAYERWITHBLEND),
    751        mOpaque(aOpaque),
    752        mOpacity(aOpacity),
    753        mMask(aMask),
    754        mMaskTransform(aMaskTransform),
    755        mBounds(aBounds),
    756        mCopyBackground(aCopyBackground),
    757        mCompositionOp(aCompositionOp) {}
    758 
    759  bool PlayEvent(Translator* aTranslator) const override;
    760 
    761  template <class S>
    762  void Record(S& aStream) const;
    763  virtual void OutputSimpleEventInfo(
    764      std::stringstream& aStringStream) const override;
    765 
    766  std::string GetName() const override { return "PushLayerWithBlend"; }
    767 
    768 private:
    769  friend class RecordedEvent;
    770 
    771  template <class S>
    772  MOZ_IMPLICIT RecordedPushLayerWithBlend(S& aStream);
    773 
    774  bool mOpaque = false;
    775  Float mOpacity = 1.0f;
    776  ReferencePtr mMask;
    777  Matrix mMaskTransform;
    778  IntRect mBounds;
    779  bool mCopyBackground = false;
    780  CompositionOp mCompositionOp = CompositionOp::OP_OVER;
    781 };
    782 
    783 class RecordedPopLayer : public RecordedEventDerived<RecordedPopLayer> {
    784 public:
    785  RecordedPopLayer() : RecordedEventDerived(POPLAYER) {}
    786 
    787  bool PlayEvent(Translator* aTranslator) const override;
    788 
    789  template <class S>
    790  void Record(S& aStream) const;
    791  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    792 
    793  std::string GetName() const override { return "PopLayer"; }
    794 
    795 private:
    796  friend class RecordedEvent;
    797 
    798  template <class S>
    799  MOZ_IMPLICIT RecordedPopLayer(S& aStream);
    800 };
    801 
    802 class RecordedSetPermitSubpixelAA
    803    : public RecordedEventDerived<RecordedSetPermitSubpixelAA> {
    804 public:
    805  explicit RecordedSetPermitSubpixelAA(bool aPermitSubpixelAA)
    806      : RecordedEventDerived(SETPERMITSUBPIXELAA),
    807        mPermitSubpixelAA(aPermitSubpixelAA) {}
    808 
    809  bool PlayEvent(Translator* aTranslator) const override;
    810 
    811  template <class S>
    812  void Record(S& aStream) const;
    813  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    814 
    815  std::string GetName() const override { return "SetPermitSubpixelAA"; }
    816 
    817 private:
    818  friend class RecordedEvent;
    819 
    820  template <class S>
    821  MOZ_IMPLICIT RecordedSetPermitSubpixelAA(S& aStream);
    822 
    823  bool mPermitSubpixelAA = false;
    824 };
    825 
    826 class RecordedSetTransform : public RecordedEventDerived<RecordedSetTransform> {
    827 public:
    828  explicit RecordedSetTransform(const Matrix& aTransform)
    829      : RecordedEventDerived(SETTRANSFORM), mTransform(aTransform) {}
    830 
    831  bool PlayEvent(Translator* aTranslator) const override;
    832 
    833  template <class S>
    834  void Record(S& aStream) const;
    835  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    836 
    837  std::string GetName() const override { return "SetTransform"; }
    838 
    839  Matrix mTransform;
    840 
    841 private:
    842  friend class RecordedEvent;
    843 
    844  template <class S>
    845  MOZ_IMPLICIT RecordedSetTransform(S& aStream);
    846 };
    847 
    848 class RecordedDrawSurface : public RecordedEventDerived<RecordedDrawSurface> {
    849 public:
    850  RecordedDrawSurface(ReferencePtr aRefSource, const Rect& aDest,
    851                      const Rect& aSource, const DrawSurfaceOptions& aDSOptions,
    852                      const DrawOptions& aOptions)
    853      : RecordedEventDerived(DRAWSURFACE),
    854        mRefSource(aRefSource),
    855        mDest(aDest),
    856        mSource(aSource),
    857        mDSOptions(aDSOptions),
    858        mOptions(aOptions) {}
    859 
    860  bool PlayEvent(Translator* aTranslator) const override;
    861 
    862  template <class S>
    863  void Record(S& aStream) const;
    864  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    865 
    866  std::string GetName() const override { return "DrawSurface"; }
    867 
    868 private:
    869  friend class RecordedEvent;
    870 
    871  template <class S>
    872  MOZ_IMPLICIT RecordedDrawSurface(S& aStream);
    873 
    874  ReferencePtr mRefSource;
    875  Rect mDest;
    876  Rect mSource;
    877  DrawSurfaceOptions mDSOptions;
    878  DrawOptions mOptions;
    879 };
    880 
    881 class RecordedDrawSurfaceDescriptor
    882    : public RecordedEventDerived<RecordedDrawSurfaceDescriptor> {
    883 public:
    884  RecordedDrawSurfaceDescriptor(const layers::SurfaceDescriptor& aDesc,
    885                                const Rect& aDest, const Rect& aSource,
    886                                const DrawSurfaceOptions& aDSOptions,
    887                                const DrawOptions& aOptions)
    888      : RecordedEventDerived(DRAWSURFACEDESCRIPTOR),
    889        mDesc(aDesc),
    890        mDest(aDest),
    891        mSource(aSource),
    892        mDSOptions(aDSOptions),
    893        mOptions(aOptions) {}
    894 
    895  bool PlayEvent(Translator* aTranslator) const override;
    896 
    897  template <class S>
    898  void Record(S& aStream) const;
    899  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    900 
    901  std::string GetName() const override { return "DrawSurfaceDescriptor"; }
    902 
    903 private:
    904  friend class RecordedEvent;
    905 
    906  template <class S>
    907  MOZ_IMPLICIT RecordedDrawSurfaceDescriptor(S& aStream);
    908 
    909  layers::SurfaceDescriptor mDesc;
    910  Rect mDest;
    911  Rect mSource;
    912  DrawSurfaceOptions mDSOptions;
    913  DrawOptions mOptions;
    914 };
    915 
    916 class RecordedDrawDependentSurface
    917    : public RecordedEventDerived<RecordedDrawDependentSurface> {
    918 public:
    919  RecordedDrawDependentSurface(uint64_t aId, const Rect& aDest)
    920      : RecordedEventDerived(DRAWDEPENDENTSURFACE), mId(aId), mDest(aDest) {}
    921 
    922  bool PlayEvent(Translator* aTranslator) const override;
    923 
    924  template <class S>
    925  void Record(S& aStream) const;
    926  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    927 
    928  std::string GetName() const override { return "DrawDependentSurface"; }
    929 
    930 private:
    931  friend class RecordedEvent;
    932 
    933  template <class S>
    934  MOZ_IMPLICIT RecordedDrawDependentSurface(S& aStream);
    935 
    936  uint64_t mId;
    937  Rect mDest;
    938 };
    939 
    940 class RecordedDrawSurfaceWithShadow
    941    : public RecordedEventDerived<RecordedDrawSurfaceWithShadow> {
    942 public:
    943  RecordedDrawSurfaceWithShadow(ReferencePtr aRefSource, const Point& aDest,
    944                                const ShadowOptions& aShadow, CompositionOp aOp)
    945      : RecordedEventDerived(DRAWSURFACEWITHSHADOW),
    946        mRefSource(aRefSource),
    947        mDest(aDest),
    948        mShadow(aShadow),
    949        mOp(aOp) {}
    950 
    951  bool PlayEvent(Translator* aTranslator) const override;
    952 
    953  template <class S>
    954  void Record(S& aStream) const;
    955  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    956 
    957  std::string GetName() const override { return "DrawSurfaceWithShadow"; }
    958 
    959 private:
    960  friend class RecordedEvent;
    961 
    962  template <class S>
    963  MOZ_IMPLICIT RecordedDrawSurfaceWithShadow(S& aStream);
    964 
    965  ReferencePtr mRefSource;
    966  Point mDest;
    967  ShadowOptions mShadow;
    968  CompositionOp mOp;
    969 };
    970 
    971 class RecordedDrawShadow : public RecordedEventDerived<RecordedDrawShadow>,
    972                           public RecordedStrokeOptionsMixin {
    973 public:
    974  RecordedDrawShadow(ReferencePtr aPath, const Pattern& aPattern,
    975                     const ShadowOptions& aShadow, const DrawOptions& aOptions,
    976                     const StrokeOptions* aStrokeOptions)
    977      : RecordedEventDerived(DRAWSHADOW),
    978        mPath(aPath),
    979        mPattern(),
    980        mShadow(aShadow),
    981        mOptions(aOptions),
    982        mHasStrokeOptions(!!aStrokeOptions),
    983        mStrokeOptions(aStrokeOptions ? *aStrokeOptions : StrokeOptions()) {
    984    StorePattern(mPattern, aPattern);
    985  }
    986 
    987  bool PlayEvent(Translator* aTranslator) const override;
    988 
    989  template <class S>
    990  void Record(S& aStream) const;
    991  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
    992 
    993  std::string GetName() const override { return "DrawShadow"; }
    994 
    995 private:
    996  friend class RecordedEvent;
    997 
    998  template <class S>
    999  MOZ_IMPLICIT RecordedDrawShadow(S& aStream);
   1000 
   1001  ReferencePtr mPath;
   1002  PatternStorage mPattern;
   1003  ShadowOptions mShadow;
   1004  DrawOptions mOptions;
   1005  bool mHasStrokeOptions = false;
   1006  StrokeOptions mStrokeOptions;
   1007 };
   1008 
   1009 class RecordedDrawFilter : public RecordedEventDerived<RecordedDrawFilter> {
   1010 public:
   1011  RecordedDrawFilter(ReferencePtr aNode, const Rect& aSourceRect,
   1012                     const Point& aDestPoint, const DrawOptions& aOptions)
   1013      : RecordedEventDerived(DRAWFILTER),
   1014        mNode(aNode),
   1015        mSourceRect(aSourceRect),
   1016        mDestPoint(aDestPoint),
   1017        mOptions(aOptions) {}
   1018 
   1019  bool PlayEvent(Translator* aTranslator) const override;
   1020 
   1021  template <class S>
   1022  void Record(S& aStream) const;
   1023  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1024 
   1025  std::string GetName() const override { return "DrawFilter"; }
   1026 
   1027 private:
   1028  friend class RecordedEvent;
   1029 
   1030  template <class S>
   1031  MOZ_IMPLICIT RecordedDrawFilter(S& aStream);
   1032 
   1033  ReferencePtr mNode;
   1034  Rect mSourceRect;
   1035  Point mDestPoint;
   1036  DrawOptions mOptions;
   1037 };
   1038 
   1039 class RecordedPathCreation : public RecordedEventDerived<RecordedPathCreation> {
   1040 public:
   1041  MOZ_IMPLICIT RecordedPathCreation(PathRecording* aPath);
   1042 
   1043  bool PlayEvent(Translator* aTranslator) const override;
   1044 
   1045  template <class S>
   1046  void Record(S& aStream) const;
   1047  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1048 
   1049  std::string GetName() const override { return "Path Creation"; }
   1050 
   1051 private:
   1052  friend class RecordedEvent;
   1053 
   1054  ReferencePtr mDT;
   1055  ReferencePtr mRefPtr;
   1056  FillRule mFillRule;
   1057  RefPtr<PathRecording> mPath;
   1058  UniquePtr<PathOps> mPathOps;
   1059 
   1060  template <class S>
   1061  MOZ_IMPLICIT RecordedPathCreation(S& aStream);
   1062 };
   1063 
   1064 class RecordedPathDestruction
   1065    : public RecordedEventDerived<RecordedPathDestruction> {
   1066 public:
   1067  MOZ_IMPLICIT RecordedPathDestruction(PathRecording* aPath)
   1068      : RecordedEventDerived(PATHDESTRUCTION), mRefPtr(aPath) {}
   1069 
   1070  bool PlayEvent(Translator* aTranslator) const override;
   1071 
   1072  template <class S>
   1073  void Record(S& aStream) const;
   1074  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1075 
   1076  std::string GetName() const override { return "Path Destruction"; }
   1077 
   1078 private:
   1079  friend class RecordedEvent;
   1080 
   1081  ReferencePtr mRefPtr;
   1082 
   1083  template <class S>
   1084  MOZ_IMPLICIT RecordedPathDestruction(S& aStream);
   1085 };
   1086 
   1087 class RecordedSourceSurfaceCreation
   1088    : public RecordedEventDerived<RecordedSourceSurfaceCreation> {
   1089 public:
   1090  RecordedSourceSurfaceCreation(ReferencePtr aRefPtr,
   1091                                const RefPtr<DataSourceSurface>& aDataSurface)
   1092      : RecordedEventDerived(SOURCESURFACECREATION),
   1093        mRefPtr(aRefPtr),
   1094        mDataSurface(aDataSurface) {}
   1095 
   1096  bool PlayEvent(Translator* aTranslator) const override;
   1097 
   1098  template <class S>
   1099  void Record(S& aStream) const;
   1100  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1101 
   1102  std::string GetName() const override { return "SourceSurface Creation"; }
   1103 
   1104 private:
   1105  friend class RecordedEvent;
   1106 
   1107  ReferencePtr mRefPtr;
   1108  RefPtr<DataSourceSurface> mDataSurface;
   1109 
   1110  template <class S>
   1111  MOZ_IMPLICIT RecordedSourceSurfaceCreation(S& aStream);
   1112 };
   1113 
   1114 class RecordedSourceSurfaceDestruction
   1115    : public RecordedEventDerived<RecordedSourceSurfaceDestruction> {
   1116 public:
   1117  MOZ_IMPLICIT RecordedSourceSurfaceDestruction(ReferencePtr aRefPtr)
   1118      : RecordedEventDerived(SOURCESURFACEDESTRUCTION), mRefPtr(aRefPtr) {}
   1119 
   1120  bool PlayEvent(Translator* aTranslator) const override;
   1121 
   1122  template <class S>
   1123  void Record(S& aStream) const;
   1124  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1125 
   1126  std::string GetName() const override { return "SourceSurface Destruction"; }
   1127 
   1128 private:
   1129  friend class RecordedEvent;
   1130 
   1131  ReferencePtr mRefPtr;
   1132 
   1133  template <class S>
   1134  MOZ_IMPLICIT RecordedSourceSurfaceDestruction(S& aStream);
   1135 };
   1136 
   1137 class RecordedOptimizeSourceSurface
   1138    : public RecordedEventDerived<RecordedOptimizeSourceSurface> {
   1139 public:
   1140  RecordedOptimizeSourceSurface(ReferencePtr aSurface,
   1141                                ReferencePtr aOptimizedSurface)
   1142      : RecordedEventDerived(OPTIMIZESOURCESURFACE),
   1143        mSurface(aSurface),
   1144        mOptimizedSurface(aOptimizedSurface) {}
   1145 
   1146  bool PlayEvent(Translator* aTranslator) const override;
   1147 
   1148  template <class S>
   1149  void Record(S& aStream) const;
   1150  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1151 
   1152  std::string GetName() const override { return "OptimizeSourceSurface"; }
   1153 
   1154 private:
   1155  friend class RecordedEvent;
   1156 
   1157  ReferencePtr mSurface;
   1158  ReferencePtr mOptimizedSurface;
   1159 
   1160  template <class S>
   1161  MOZ_IMPLICIT RecordedOptimizeSourceSurface(S& aStream);
   1162 };
   1163 
   1164 class RecordedExternalSurfaceCreation
   1165    : public RecordedEventDerived<RecordedExternalSurfaceCreation> {
   1166 public:
   1167  RecordedExternalSurfaceCreation(ReferencePtr aRefPtr, const uint64_t aKey)
   1168      : RecordedEventDerived(EXTERNALSURFACECREATION),
   1169        mRefPtr(aRefPtr),
   1170        mKey(aKey) {}
   1171 
   1172  ~RecordedExternalSurfaceCreation() = default;
   1173 
   1174  virtual bool PlayEvent(Translator* aTranslator) const;
   1175 
   1176  template <class S>
   1177  void Record(S& aStream) const;
   1178  virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const;
   1179 
   1180  virtual std::string GetName() const {
   1181    return "SourceSurfaceSharedData Creation";
   1182  }
   1183 
   1184 private:
   1185  friend class RecordedEvent;
   1186 
   1187  ReferencePtr mRefPtr;
   1188  uint64_t mKey;
   1189 
   1190  template <class S>
   1191  MOZ_IMPLICIT RecordedExternalSurfaceCreation(S& aStream);
   1192 };
   1193 
   1194 class RecordedFilterNodeCreation
   1195    : public RecordedEventDerived<RecordedFilterNodeCreation> {
   1196 public:
   1197  RecordedFilterNodeCreation(ReferencePtr aRefPtr, FilterType aType)
   1198      : RecordedEventDerived(FILTERNODECREATION),
   1199        mRefPtr(aRefPtr),
   1200        mType(aType) {}
   1201 
   1202  ~RecordedFilterNodeCreation();
   1203 
   1204  bool PlayEvent(Translator* aTranslator) const override;
   1205 
   1206  template <class S>
   1207  void Record(S& aStream) const;
   1208  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1209 
   1210  std::string GetName() const override { return "FilterNode Creation"; }
   1211 
   1212 private:
   1213  friend class RecordedEvent;
   1214 
   1215  ReferencePtr mRefPtr;
   1216  FilterType mType;
   1217 
   1218  template <class S>
   1219  MOZ_IMPLICIT RecordedFilterNodeCreation(S& aStream);
   1220 };
   1221 
   1222 class RecordedDeferFilterInput
   1223    : public RecordedEventDerived<RecordedDeferFilterInput>,
   1224      public RecordedStrokeOptionsMixin {
   1225 public:
   1226  RecordedDeferFilterInput(ReferencePtr aRefPtr, ReferencePtr aPath,
   1227                           const Pattern& aPattern, const IntRect& aSourceRect,
   1228                           const IntPoint& aDestOffset,
   1229                           const DrawOptions& aOptions,
   1230                           const StrokeOptions* aStrokeOptions)
   1231      : RecordedEventDerived(DEFERFILTERINPUT),
   1232        mRefPtr(aRefPtr),
   1233        mPath(aPath),
   1234        mPattern(),
   1235        mSourceRect(aSourceRect),
   1236        mDestOffset(aDestOffset),
   1237        mOptions(aOptions),
   1238        mHasStrokeOptions(!!aStrokeOptions),
   1239        mStrokeOptions(aStrokeOptions ? *aStrokeOptions : StrokeOptions()) {
   1240    StorePattern(mPattern, aPattern);
   1241  }
   1242 
   1243  bool PlayEvent(Translator* aTranslator) const override;
   1244 
   1245  template <class S>
   1246  void Record(S& aStream) const;
   1247  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1248 
   1249  std::string GetName() const override { return "DeferFilterInput"; }
   1250 
   1251 private:
   1252  friend class RecordedEvent;
   1253 
   1254  template <class S>
   1255  MOZ_IMPLICIT RecordedDeferFilterInput(S& aStream);
   1256 
   1257  ReferencePtr mRefPtr;
   1258  ReferencePtr mPath;
   1259  PatternStorage mPattern;
   1260  IntRect mSourceRect;
   1261  IntPoint mDestOffset;
   1262  DrawOptions mOptions;
   1263  bool mHasStrokeOptions = false;
   1264  StrokeOptions mStrokeOptions;
   1265 };
   1266 
   1267 class RecordedFilterNodeDestruction
   1268    : public RecordedEventDerived<RecordedFilterNodeDestruction> {
   1269 public:
   1270  MOZ_IMPLICIT RecordedFilterNodeDestruction(ReferencePtr aRefPtr)
   1271      : RecordedEventDerived(FILTERNODEDESTRUCTION), mRefPtr(aRefPtr) {}
   1272 
   1273  bool PlayEvent(Translator* aTranslator) const override;
   1274 
   1275  template <class S>
   1276  void Record(S& aStream) const;
   1277  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1278 
   1279  std::string GetName() const override { return "FilterNode Destruction"; }
   1280 
   1281 private:
   1282  friend class RecordedEvent;
   1283 
   1284  ReferencePtr mRefPtr;
   1285 
   1286  template <class S>
   1287  MOZ_IMPLICIT RecordedFilterNodeDestruction(S& aStream);
   1288 };
   1289 
   1290 class RecordedGradientStopsCreation
   1291    : public RecordedEventDerived<RecordedGradientStopsCreation> {
   1292 public:
   1293  RecordedGradientStopsCreation(ReferencePtr aRefPtr, GradientStop* aStops,
   1294                                uint32_t aNumStops, ExtendMode aExtendMode)
   1295      : RecordedEventDerived(GRADIENTSTOPSCREATION),
   1296        mRefPtr(aRefPtr),
   1297        mStops(aStops),
   1298        mNumStops(aNumStops),
   1299        mExtendMode(aExtendMode),
   1300        mDataOwned(false) {}
   1301 
   1302  ~RecordedGradientStopsCreation();
   1303 
   1304  bool PlayEvent(Translator* aTranslator) const override;
   1305 
   1306  template <class S>
   1307  void Record(S& aStream) const;
   1308  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1309 
   1310  std::string GetName() const override { return "GradientStops Creation"; }
   1311 
   1312 private:
   1313  friend class RecordedEvent;
   1314 
   1315  ReferencePtr mRefPtr;
   1316  GradientStop* mStops = nullptr;
   1317  uint32_t mNumStops = 0;
   1318  ExtendMode mExtendMode;
   1319  bool mDataOwned;
   1320 
   1321  template <class S>
   1322  MOZ_IMPLICIT RecordedGradientStopsCreation(S& aStream);
   1323 };
   1324 
   1325 class RecordedGradientStopsDestruction
   1326    : public RecordedEventDerived<RecordedGradientStopsDestruction> {
   1327 public:
   1328  MOZ_IMPLICIT RecordedGradientStopsDestruction(ReferencePtr aRefPtr)
   1329      : RecordedEventDerived(GRADIENTSTOPSDESTRUCTION), mRefPtr(aRefPtr) {}
   1330 
   1331  bool PlayEvent(Translator* aTranslator) const override;
   1332 
   1333  template <class S>
   1334  void Record(S& aStream) const;
   1335  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1336 
   1337  std::string GetName() const override { return "GradientStops Destruction"; }
   1338 
   1339 private:
   1340  friend class RecordedEvent;
   1341 
   1342  ReferencePtr mRefPtr;
   1343 
   1344  template <class S>
   1345  MOZ_IMPLICIT RecordedGradientStopsDestruction(S& aStream);
   1346 };
   1347 
   1348 class RecordedFlush : public RecordedEventDerived<RecordedFlush> {
   1349 public:
   1350  explicit RecordedFlush() : RecordedEventDerived(FLUSH) {}
   1351 
   1352  bool PlayEvent(Translator* aTranslator) const final;
   1353 
   1354  template <class S>
   1355  void Record(S& aStream) const;
   1356  virtual void OutputSimpleEventInfo(
   1357      std::stringstream& aStringStream) const override;
   1358 
   1359  virtual std::string GetName() const override { return "Flush"; }
   1360 
   1361 private:
   1362  friend class RecordedEvent;
   1363 
   1364  template <class S>
   1365  MOZ_IMPLICIT RecordedFlush(S& aStream);
   1366 };
   1367 
   1368 class RecordedDetachAllSnapshots
   1369    : public RecordedEventDerived<RecordedDetachAllSnapshots> {
   1370 public:
   1371  explicit RecordedDetachAllSnapshots()
   1372      : RecordedEventDerived(DETACHALLSNAPSHOTS) {}
   1373 
   1374  bool PlayEvent(Translator* aTranslator) const final;
   1375 
   1376  template <class S>
   1377  void Record(S& aStream) const;
   1378  virtual void OutputSimpleEventInfo(
   1379      std::stringstream& aStringStream) const override;
   1380 
   1381  virtual std::string GetName() const override { return "DetachAllSnapshots"; }
   1382 
   1383 private:
   1384  friend class RecordedEvent;
   1385 
   1386  template <class S>
   1387  MOZ_IMPLICIT RecordedDetachAllSnapshots(S& aStream);
   1388 };
   1389 
   1390 class RecordedSnapshot : public RecordedEventDerived<RecordedSnapshot> {
   1391 public:
   1392  explicit RecordedSnapshot(ReferencePtr aRefPtr)
   1393      : RecordedEventDerived(SNAPSHOT), mRefPtr(aRefPtr) {}
   1394 
   1395  bool PlayEvent(Translator* aTranslator) const override;
   1396 
   1397  template <class S>
   1398  void Record(S& aStream) const;
   1399  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1400 
   1401  std::string GetName() const override { return "Snapshot"; }
   1402 
   1403 private:
   1404  friend class RecordedEvent;
   1405 
   1406  ReferencePtr mRefPtr;
   1407 
   1408  template <class S>
   1409  MOZ_IMPLICIT RecordedSnapshot(S& aStream);
   1410 };
   1411 
   1412 class RecordedIntoLuminanceSource
   1413    : public RecordedEventDerived<RecordedIntoLuminanceSource> {
   1414 public:
   1415  RecordedIntoLuminanceSource(ReferencePtr aRefPtr,
   1416                              LuminanceType aLuminanceType, float aOpacity)
   1417      : RecordedEventDerived(INTOLUMINANCE),
   1418        mRefPtr(aRefPtr),
   1419        mLuminanceType(aLuminanceType),
   1420        mOpacity(aOpacity) {}
   1421 
   1422  bool PlayEvent(Translator* aTranslator) const override;
   1423 
   1424  template <class S>
   1425  void Record(S& aStream) const;
   1426  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1427 
   1428  std::string GetName() const override { return "IntoLuminanceSource"; }
   1429 
   1430 private:
   1431  friend class RecordedEvent;
   1432 
   1433  ReferencePtr mRefPtr;
   1434  LuminanceType mLuminanceType;
   1435  float mOpacity;
   1436 
   1437  template <class S>
   1438  MOZ_IMPLICIT RecordedIntoLuminanceSource(S& aStream);
   1439 };
   1440 
   1441 class RecordedExtractSubrect
   1442    : public RecordedEventDerived<RecordedExtractSubrect> {
   1443 public:
   1444  RecordedExtractSubrect(ReferencePtr aRefPtr, ReferencePtr aSourceSurface,
   1445                         const IntRect& aSubrect)
   1446      : RecordedEventDerived(EXTRACTSUBRECT),
   1447        mRefPtr(aRefPtr),
   1448        mSourceSurface(aSourceSurface),
   1449        mSubrect(aSubrect) {}
   1450 
   1451  bool PlayEvent(Translator* aTranslator) const override;
   1452 
   1453  template <class S>
   1454  void Record(S& aStream) const;
   1455  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1456 
   1457  std::string GetName() const override { return "ExtractSubrect"; }
   1458 
   1459 private:
   1460  friend class RecordedEvent;
   1461 
   1462  ReferencePtr mRefPtr;
   1463  ReferencePtr mSourceSurface;
   1464  IntRect mSubrect;
   1465 
   1466  template <class S>
   1467  MOZ_IMPLICIT RecordedExtractSubrect(S& aStream);
   1468 };
   1469 
   1470 class RecordedFontData : public RecordedEventDerived<RecordedFontData> {
   1471 public:
   1472  static void FontDataProc(const uint8_t* aData, uint32_t aSize,
   1473                           uint32_t aIndex, void* aBaton) {
   1474    auto recordedFontData = static_cast<RecordedFontData*>(aBaton);
   1475    recordedFontData->SetFontData(aData, aSize, aIndex);
   1476  }
   1477 
   1478  explicit RecordedFontData(UnscaledFont* aUnscaledFont)
   1479      : RecordedEventDerived(FONTDATA),
   1480        mType(aUnscaledFont->GetType()),
   1481        mFontDetails() {
   1482    if (!aUnscaledFont->GetFontFileData(&FontDataProc, this)) {
   1483      mGetFontFileDataSucceeded = false;
   1484    }
   1485  }
   1486 
   1487  bool IsValid() const { return mGetFontFileDataSucceeded; }
   1488 
   1489  bool PlayEvent(Translator* aTranslator) const override;
   1490 
   1491  template <class S>
   1492  void Record(S& aStream) const;
   1493  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1494 
   1495  std::string GetName() const override { return "Font Data"; }
   1496 
   1497  void SetFontData(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
   1498 
   1499  bool GetFontDetails(RecordedFontDetails& fontDetails);
   1500 
   1501 private:
   1502  friend class RecordedEvent;
   1503 
   1504  FontType mType;
   1505  RecordedEventArray<uint8_t, uint32_t> mData;
   1506  RecordedFontDetails mFontDetails;
   1507 
   1508  bool mGetFontFileDataSucceeded = true;
   1509 
   1510  template <class S>
   1511  MOZ_IMPLICIT RecordedFontData(S& aStream);
   1512 };
   1513 
   1514 class RecordedFontDescriptor
   1515    : public RecordedEventDerived<RecordedFontDescriptor> {
   1516 public:
   1517  static void FontDescCb(const uint8_t* aData, uint32_t aSize, uint32_t aIndex,
   1518                         void* aBaton) {
   1519    auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton);
   1520    recordedFontDesc->SetFontDescriptor(aData, aSize, aIndex);
   1521  }
   1522 
   1523  explicit RecordedFontDescriptor(UnscaledFont* aUnscaledFont)
   1524      : RecordedEventDerived(FONTDESC),
   1525        mType(aUnscaledFont->GetType()),
   1526        mIndex(0),
   1527        mRefPtr(aUnscaledFont) {
   1528    mHasDesc = aUnscaledFont->GetFontDescriptor(FontDescCb, this);
   1529  }
   1530 
   1531  virtual ~RecordedFontDescriptor();
   1532 
   1533  bool IsValid() const { return mHasDesc; }
   1534 
   1535  bool PlayEvent(Translator* aTranslator) const override;
   1536 
   1537  template <class S>
   1538  void Record(S& aStream) const;
   1539  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1540 
   1541  std::string GetName() const override { return "Font Desc"; }
   1542 
   1543 private:
   1544  friend class RecordedEvent;
   1545 
   1546  void SetFontDescriptor(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
   1547 
   1548  bool mHasDesc;
   1549 
   1550  FontType mType;
   1551  RecordedEventArray<uint8_t> mData;
   1552  uint32_t mIndex;
   1553  ReferencePtr mRefPtr;
   1554 
   1555  template <class S>
   1556  MOZ_IMPLICIT RecordedFontDescriptor(S& aStream);
   1557 };
   1558 
   1559 class RecordedUnscaledFontCreation
   1560    : public RecordedEventDerived<RecordedUnscaledFontCreation> {
   1561 public:
   1562  static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize,
   1563                                   void* aBaton) {
   1564    auto recordedUnscaledFontCreation =
   1565        static_cast<RecordedUnscaledFontCreation*>(aBaton);
   1566    recordedUnscaledFontCreation->SetFontInstanceData(aData, aSize);
   1567  }
   1568 
   1569  RecordedUnscaledFontCreation(UnscaledFont* aUnscaledFont,
   1570                               RecordedFontDetails aFontDetails)
   1571      : RecordedEventDerived(UNSCALEDFONTCREATION),
   1572        mRefPtr(aUnscaledFont),
   1573        mFontDataKey(aFontDetails.fontDataKey),
   1574        mIndex(aFontDetails.index) {
   1575    aUnscaledFont->GetFontInstanceData(FontInstanceDataProc, this);
   1576  }
   1577 
   1578  bool PlayEvent(Translator* aTranslator) const override;
   1579 
   1580  template <class S>
   1581  void Record(S& aStream) const;
   1582  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1583 
   1584  std::string GetName() const override { return "UnscaledFont Creation"; }
   1585 
   1586  void SetFontInstanceData(const uint8_t* aData, uint32_t aSize);
   1587 
   1588 private:
   1589  friend class RecordedEvent;
   1590 
   1591  ReferencePtr mRefPtr;
   1592  uint64_t mFontDataKey;
   1593  uint32_t mIndex;
   1594  RecordedEventArray<uint8_t> mInstanceData;
   1595 
   1596  template <class S>
   1597  MOZ_IMPLICIT RecordedUnscaledFontCreation(S& aStream);
   1598 };
   1599 
   1600 class RecordedUnscaledFontDestruction
   1601    : public RecordedEventDerived<RecordedUnscaledFontDestruction> {
   1602 public:
   1603  MOZ_IMPLICIT RecordedUnscaledFontDestruction(ReferencePtr aRefPtr)
   1604      : RecordedEventDerived(UNSCALEDFONTDESTRUCTION), mRefPtr(aRefPtr) {}
   1605 
   1606  bool PlayEvent(Translator* aTranslator) const override;
   1607  template <class S>
   1608  void Record(S& aStream) const;
   1609  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1610 
   1611  std::string GetName() const override { return "UnscaledFont Destruction"; }
   1612 
   1613 private:
   1614  friend class RecordedEvent;
   1615 
   1616  ReferencePtr mRefPtr;
   1617 
   1618  template <class S>
   1619  MOZ_IMPLICIT RecordedUnscaledFontDestruction(S& aStream);
   1620 };
   1621 
   1622 class RecordedScaledFontCreation
   1623    : public RecordedEventDerived<RecordedScaledFontCreation> {
   1624 public:
   1625  static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize,
   1626                                   const FontVariation* aVariations,
   1627                                   uint32_t aNumVariations, void* aBaton) {
   1628    auto recordedScaledFontCreation =
   1629        static_cast<RecordedScaledFontCreation*>(aBaton);
   1630    recordedScaledFontCreation->SetFontInstanceData(aData, aSize, aVariations,
   1631                                                    aNumVariations);
   1632  }
   1633 
   1634  RecordedScaledFontCreation(ScaledFont* aScaledFont,
   1635                             UnscaledFont* aUnscaledFont)
   1636      : RecordedEventDerived(SCALEDFONTCREATION),
   1637        mRefPtr(aScaledFont),
   1638        mUnscaledFont(aUnscaledFont),
   1639        mGlyphSize(aScaledFont->GetSize()) {
   1640    aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
   1641  }
   1642 
   1643  bool PlayEvent(Translator* aTranslator) const override;
   1644 
   1645  template <class S>
   1646  void Record(S& aStream) const;
   1647  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1648 
   1649  std::string GetName() const override { return "ScaledFont Creation"; }
   1650 
   1651  void SetFontInstanceData(const uint8_t* aData, uint32_t aSize,
   1652                           const FontVariation* aVariations,
   1653                           uint32_t aNumVariations);
   1654 
   1655 private:
   1656  friend class RecordedEvent;
   1657 
   1658  ReferencePtr mRefPtr;
   1659  ReferencePtr mUnscaledFont;
   1660  Float mGlyphSize;
   1661  RecordedEventArray<uint8_t> mInstanceData;
   1662  RecordedEventArray<FontVariation> mVariations;
   1663 
   1664  template <class S>
   1665  MOZ_IMPLICIT RecordedScaledFontCreation(S& aStream);
   1666 };
   1667 
   1668 class RecordedScaledFontDestruction
   1669    : public RecordedEventDerived<RecordedScaledFontDestruction> {
   1670 public:
   1671  MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr)
   1672      : RecordedEventDerived(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr) {}
   1673 
   1674  bool PlayEvent(Translator* aTranslator) const override;
   1675 
   1676  template <class S>
   1677  void Record(S& aStream) const;
   1678  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1679 
   1680  std::string GetName() const override { return "ScaledFont Destruction"; }
   1681 
   1682 private:
   1683  friend class RecordedEvent;
   1684 
   1685  ReferencePtr mRefPtr;
   1686 
   1687  template <class S>
   1688  MOZ_IMPLICIT RecordedScaledFontDestruction(S& aStream);
   1689 };
   1690 
   1691 class RecordedMaskSurface : public RecordedEventDerived<RecordedMaskSurface> {
   1692 public:
   1693  RecordedMaskSurface(const Pattern& aPattern, ReferencePtr aRefMask,
   1694                      const Point& aOffset, const DrawOptions& aOptions)
   1695      : RecordedEventDerived(MASKSURFACE),
   1696        mPattern(),
   1697        mRefMask(aRefMask),
   1698        mOffset(aOffset),
   1699        mOptions(aOptions) {
   1700    StorePattern(mPattern, aPattern);
   1701  }
   1702 
   1703  bool PlayEvent(Translator* aTranslator) const override;
   1704 
   1705  template <class S>
   1706  void Record(S& aStream) const;
   1707  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1708 
   1709  std::string GetName() const override { return "MaskSurface"; }
   1710 
   1711 private:
   1712  friend class RecordedEvent;
   1713 
   1714  template <class S>
   1715  MOZ_IMPLICIT RecordedMaskSurface(S& aStream);
   1716 
   1717  PatternStorage mPattern;
   1718  ReferencePtr mRefMask;
   1719  Point mOffset;
   1720  DrawOptions mOptions;
   1721 };
   1722 
   1723 class RecordedFilterNodeSetAttribute
   1724    : public RecordedEventDerived<RecordedFilterNodeSetAttribute> {
   1725 public:
   1726  enum ArgType {
   1727    ARGTYPE_UINT32,
   1728    ARGTYPE_BOOL,
   1729    ARGTYPE_FLOAT,
   1730    ARGTYPE_SIZE,
   1731    ARGTYPE_INTSIZE,
   1732    ARGTYPE_INTPOINT,
   1733    ARGTYPE_RECT,
   1734    ARGTYPE_INTRECT,
   1735    ARGTYPE_POINT,
   1736    ARGTYPE_MATRIX,
   1737    ARGTYPE_MATRIX5X4,
   1738    ARGTYPE_POINT3D,
   1739    ARGTYPE_COLOR,
   1740    ARGTYPE_FLOAT_ARRAY
   1741  };
   1742 
   1743  template <typename T>
   1744  void WritePayload(const T& aValue) {
   1745    mPayload.Assign(reinterpret_cast<const uint8_t*>(&aValue), sizeof(T));
   1746  }
   1747 
   1748  void WritePayload(const bool& aValue) {
   1749    uint8_t data = aValue ? 1 : 0;
   1750    mPayload.Assign(&data, 1);
   1751  }
   1752 
   1753  template <typename T>
   1754  RecordedFilterNodeSetAttribute(FilterNode* aNode, uint32_t aIndex,
   1755                                 T aArgument, ArgType aArgType)
   1756      : RecordedEventDerived(FILTERNODESETATTRIBUTE),
   1757        mNode(aNode),
   1758        mIndex(aIndex),
   1759        mArgType(aArgType) {
   1760    WritePayload(aArgument);
   1761  }
   1762 
   1763  RecordedFilterNodeSetAttribute(FilterNode* aNode, uint32_t aIndex,
   1764                                 const Float* aFloat, uint32_t aSize)
   1765      : RecordedEventDerived(FILTERNODESETATTRIBUTE),
   1766        mNode(aNode),
   1767        mIndex(aIndex),
   1768        mArgType(ARGTYPE_FLOAT_ARRAY) {
   1769    mPayload.Assign(reinterpret_cast<const uint8_t*>(aFloat),
   1770                    sizeof(Float) * aSize);
   1771  }
   1772 
   1773  bool PlayEvent(Translator* aTranslator) const override;
   1774  template <class S>
   1775  void Record(S& aStream) const;
   1776  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1777 
   1778  std::string GetName() const override { return "SetAttribute"; }
   1779 
   1780 private:
   1781  friend class RecordedEvent;
   1782 
   1783  ReferencePtr mNode;
   1784 
   1785  uint32_t mIndex;
   1786  ArgType mArgType;
   1787  RecordedEventArray<uint8_t> mPayload;
   1788 
   1789  template <class S>
   1790  MOZ_IMPLICIT RecordedFilterNodeSetAttribute(S& aStream);
   1791 };
   1792 
   1793 class RecordedFilterNodeSetInput
   1794    : public RecordedEventDerived<RecordedFilterNodeSetInput> {
   1795 public:
   1796  RecordedFilterNodeSetInput(FilterNode* aNode, uint32_t aIndex,
   1797                             FilterNode* aInputNode)
   1798      : RecordedEventDerived(FILTERNODESETINPUT),
   1799        mNode(aNode),
   1800        mIndex(aIndex),
   1801        mInputFilter(aInputNode),
   1802        mInputSurface(nullptr) {}
   1803 
   1804  RecordedFilterNodeSetInput(FilterNode* aNode, uint32_t aIndex,
   1805                             SourceSurface* aInputSurface)
   1806      : RecordedEventDerived(FILTERNODESETINPUT),
   1807        mNode(aNode),
   1808        mIndex(aIndex),
   1809        mInputFilter(nullptr),
   1810        mInputSurface(aInputSurface) {}
   1811 
   1812  bool PlayEvent(Translator* aTranslator) const override;
   1813  template <class S>
   1814  void Record(S& aStream) const;
   1815  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1816 
   1817  std::string GetName() const override { return "SetInput"; }
   1818 
   1819 private:
   1820  friend class RecordedEvent;
   1821 
   1822  ReferencePtr mNode;
   1823  uint32_t mIndex;
   1824  ReferencePtr mInputFilter;
   1825  ReferencePtr mInputSurface;
   1826 
   1827  template <class S>
   1828  MOZ_IMPLICIT RecordedFilterNodeSetInput(S& aStream);
   1829 };
   1830 
   1831 class RecordedLink : public RecordedEventDerived<RecordedLink> {
   1832 public:
   1833  RecordedLink(const char* aLocalDest, const char* aURI, const Rect& aRect)
   1834      : RecordedEventDerived(LINK),
   1835        mLocalDest(aLocalDest),
   1836        mURI(aURI),
   1837        mRect(aRect) {}
   1838 
   1839  bool PlayEvent(Translator* aTranslator) const override;
   1840  template <class S>
   1841  void Record(S& aStream) const;
   1842  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1843 
   1844  std::string GetName() const override { return "Link"; }
   1845 
   1846 private:
   1847  friend class RecordedEvent;
   1848 
   1849  RecordedEventCString mLocalDest;
   1850  RecordedEventCString mURI;
   1851  Rect mRect;
   1852 
   1853  template <class S>
   1854  MOZ_IMPLICIT RecordedLink(S& aStream);
   1855 };
   1856 
   1857 class RecordedDestination : public RecordedEventDerived<RecordedDestination> {
   1858 public:
   1859  RecordedDestination(const char* aDestination, const Point& aPoint)
   1860      : RecordedEventDerived(DESTINATION),
   1861        mDestination(aDestination),
   1862        mPoint(aPoint) {}
   1863 
   1864  bool PlayEvent(Translator* aTranslator) const override;
   1865  template <class S>
   1866  void Record(S& aStream) const;
   1867  void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
   1868 
   1869  std::string GetName() const override { return "Destination"; }
   1870 
   1871 private:
   1872  friend class RecordedEvent;
   1873 
   1874  RecordedEventCString mDestination;
   1875  Point mPoint;
   1876 
   1877  template <class S>
   1878  MOZ_IMPLICIT RecordedDestination(S& aStream);
   1879 };
   1880 
   1881 static std::string NameFromBackend(BackendType aType) {
   1882  switch (aType) {
   1883    case BackendType::NONE:
   1884      return "None";
   1885    default:
   1886      return "Unknown";
   1887  }
   1888 }
   1889 
   1890 template <class S>
   1891 void RecordedEvent::RecordPatternData(S& aStream,
   1892                                      const PatternStorage& aPattern) const {
   1893  WriteElement(aStream, aPattern.mType);
   1894 
   1895  switch (aPattern.mType) {
   1896    case PatternType::COLOR: {
   1897      WriteElement(aStream, *reinterpret_cast<const ColorPatternStorage*>(
   1898                                &aPattern.mStorage));
   1899      return;
   1900    }
   1901    case PatternType::LINEAR_GRADIENT: {
   1902      WriteElement(aStream,
   1903                   *reinterpret_cast<const LinearGradientPatternStorage*>(
   1904                       &aPattern.mStorage));
   1905      return;
   1906    }
   1907    case PatternType::RADIAL_GRADIENT: {
   1908      WriteElement(aStream,
   1909                   *reinterpret_cast<const RadialGradientPatternStorage*>(
   1910                       &aPattern.mStorage));
   1911      return;
   1912    }
   1913    case PatternType::CONIC_GRADIENT: {
   1914      WriteElement(aStream,
   1915                   *reinterpret_cast<const ConicGradientPatternStorage*>(
   1916                       &aPattern.mStorage));
   1917      return;
   1918    }
   1919    case PatternType::SURFACE: {
   1920      WriteElement(aStream, *reinterpret_cast<const SurfacePatternStorage*>(
   1921                                &aPattern.mStorage));
   1922      return;
   1923    }
   1924    default:
   1925      return;
   1926  }
   1927 }
   1928 
   1929 template <class S>
   1930 void RecordedEvent::ReadPatternData(S& aStream,
   1931                                    PatternStorage& aPattern) const {
   1932  ReadElementConstrained(aStream, aPattern.mType, PatternType::COLOR,
   1933                         kHighestPatternType);
   1934 
   1935  switch (aPattern.mType) {
   1936    case PatternType::COLOR: {
   1937      ReadElement(aStream,
   1938                  *reinterpret_cast<ColorPatternStorage*>(&aPattern.mStorage));
   1939      return;
   1940    }
   1941    case PatternType::LINEAR_GRADIENT: {
   1942      ReadElement(aStream, *reinterpret_cast<LinearGradientPatternStorage*>(
   1943                               &aPattern.mStorage));
   1944      return;
   1945    }
   1946    case PatternType::RADIAL_GRADIENT: {
   1947      ReadElement(aStream, *reinterpret_cast<RadialGradientPatternStorage*>(
   1948                               &aPattern.mStorage));
   1949      return;
   1950    }
   1951    case PatternType::CONIC_GRADIENT: {
   1952      ReadElement(aStream, *reinterpret_cast<ConicGradientPatternStorage*>(
   1953                               &aPattern.mStorage));
   1954      return;
   1955    }
   1956    case PatternType::SURFACE: {
   1957      SurfacePatternStorage* sps =
   1958          reinterpret_cast<SurfacePatternStorage*>(&aPattern.mStorage);
   1959      ReadElement(aStream, *sps);
   1960      if (sps->mExtend < ExtendMode::CLAMP ||
   1961          sps->mExtend > ExtendMode::REFLECT) {
   1962        aStream.SetIsBad();
   1963        return;
   1964      }
   1965 
   1966      if (sps->mSamplingFilter < SamplingFilter::GOOD ||
   1967          sps->mSamplingFilter >= SamplingFilter::SENTINEL) {
   1968        aStream.SetIsBad();
   1969      }
   1970      return;
   1971    }
   1972    default:
   1973      return;
   1974  }
   1975 }
   1976 
   1977 inline void RecordedEvent::StorePattern(PatternStorage& aDestination,
   1978                                        const Pattern& aSource) const {
   1979  aDestination.mType = aSource.GetType();
   1980 
   1981  switch (aSource.GetType()) {
   1982    case PatternType::COLOR: {
   1983      reinterpret_cast<ColorPatternStorage*>(&aDestination.mStorage)->mColor =
   1984          static_cast<const ColorPattern*>(&aSource)->mColor;
   1985      return;
   1986    }
   1987    case PatternType::LINEAR_GRADIENT: {
   1988      LinearGradientPatternStorage* store =
   1989          reinterpret_cast<LinearGradientPatternStorage*>(
   1990              &aDestination.mStorage);
   1991      const LinearGradientPattern* pat =
   1992          static_cast<const LinearGradientPattern*>(&aSource);
   1993      store->mBegin = pat->mBegin;
   1994      store->mEnd = pat->mEnd;
   1995      store->mMatrix = pat->mMatrix;
   1996      store->mStops = pat->mStops.get();
   1997      return;
   1998    }
   1999    case PatternType::RADIAL_GRADIENT: {
   2000      RadialGradientPatternStorage* store =
   2001          reinterpret_cast<RadialGradientPatternStorage*>(
   2002              &aDestination.mStorage);
   2003      const RadialGradientPattern* pat =
   2004          static_cast<const RadialGradientPattern*>(&aSource);
   2005      store->mCenter1 = pat->mCenter1;
   2006      store->mCenter2 = pat->mCenter2;
   2007      store->mRadius1 = pat->mRadius1;
   2008      store->mRadius2 = pat->mRadius2;
   2009      store->mMatrix = pat->mMatrix;
   2010      store->mStops = pat->mStops.get();
   2011      return;
   2012    }
   2013    case PatternType::CONIC_GRADIENT: {
   2014      ConicGradientPatternStorage* store =
   2015          reinterpret_cast<ConicGradientPatternStorage*>(
   2016              &aDestination.mStorage);
   2017      const ConicGradientPattern* pat =
   2018          static_cast<const ConicGradientPattern*>(&aSource);
   2019      store->mCenter = pat->mCenter;
   2020      store->mAngle = pat->mAngle;
   2021      store->mStartOffset = pat->mStartOffset;
   2022      store->mEndOffset = pat->mEndOffset;
   2023      store->mMatrix = pat->mMatrix;
   2024      store->mStops = pat->mStops.get();
   2025      return;
   2026    }
   2027    case PatternType::SURFACE: {
   2028      SurfacePatternStorage* store =
   2029          reinterpret_cast<SurfacePatternStorage*>(&aDestination.mStorage);
   2030      const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aSource);
   2031      store->mExtend = pat->mExtendMode;
   2032      store->mSamplingFilter = pat->mSamplingFilter;
   2033      store->mMatrix = pat->mMatrix;
   2034      store->mSurface = pat->mSurface;
   2035      store->mSamplingRect = pat->mSamplingRect;
   2036      return;
   2037    }
   2038  }
   2039 }
   2040 
   2041 template <class S>
   2042 void RecordedStrokeOptionsMixin::RecordStrokeOptions(
   2043    S& aStream, const StrokeOptions& aStrokeOptions) const {
   2044  JoinStyle joinStyle = aStrokeOptions.mLineJoin;
   2045  CapStyle capStyle = aStrokeOptions.mLineCap;
   2046 
   2047  WriteElement(aStream, uint64_t(aStrokeOptions.mDashLength));
   2048  WriteElement(aStream, aStrokeOptions.mLineWidth);
   2049  WriteElement(aStream, aStrokeOptions.mMiterLimit);
   2050  WriteElement(aStream, joinStyle);
   2051  WriteElement(aStream, capStyle);
   2052 
   2053  if (!aStrokeOptions.mDashPattern) {
   2054    return;
   2055  }
   2056 
   2057  WriteElement(aStream, aStrokeOptions.mDashOffset);
   2058  aStream.write((char*)aStrokeOptions.mDashPattern,
   2059                sizeof(Float) * aStrokeOptions.mDashLength);
   2060 }
   2061 
   2062 template <class S>
   2063 void RecordedStrokeOptionsMixin::ReadStrokeOptions(
   2064    S& aStream, StrokeOptions& aStrokeOptions) {
   2065  uint64_t dashLength64 = 0;
   2066  JoinStyle joinStyle;
   2067  CapStyle capStyle;
   2068 
   2069  ReadElement(aStream, dashLength64);
   2070  ReadElement(aStream, aStrokeOptions.mLineWidth);
   2071  ReadElement(aStream, aStrokeOptions.mMiterLimit);
   2072  ReadElementConstrained(aStream, joinStyle, JoinStyle::BEVEL,
   2073                         JoinStyle::MITER_OR_BEVEL);
   2074  ReadElementConstrained(aStream, capStyle, CapStyle::BUTT, CapStyle::SQUARE);
   2075  aStrokeOptions.mLineJoin = joinStyle;
   2076  aStrokeOptions.mLineCap = capStyle;
   2077 
   2078  // On 32 bit we truncate the value of dashLength.
   2079  // See also bug 811850 for history.
   2080  size_t dashLength = size_t(dashLength64);
   2081  if (!dashLength || !aStream.good()) {
   2082    return;
   2083  }
   2084 
   2085  ReadElement(aStream, aStrokeOptions.mDashOffset);
   2086 
   2087  mDashPatternStorage = MakeUniqueFallible<Float[]>(dashLength);
   2088  if (!mDashPatternStorage) {
   2089    aStream.SetIsBad();
   2090    return;
   2091  }
   2092  aStream.read((char*)mDashPatternStorage.get(), sizeof(Float) * dashLength);
   2093  if (!aStream.good()) {
   2094    aStream.SetIsBad();
   2095    return;
   2096  }
   2097  aStrokeOptions.mDashLength = dashLength;
   2098  aStrokeOptions.mDashPattern = mDashPatternStorage.get();
   2099 }
   2100 
   2101 template <class S>
   2102 static void ReadDrawOptions(S& aStream, DrawOptions& aDrawOptions) {
   2103  ReadElement(aStream, aDrawOptions);
   2104  if (aDrawOptions.mAntialiasMode < AntialiasMode::NONE ||
   2105      aDrawOptions.mAntialiasMode > AntialiasMode::DEFAULT) {
   2106    aStream.SetIsBad();
   2107    return;
   2108  }
   2109 
   2110  if (aDrawOptions.mCompositionOp < CompositionOp::OP_CLEAR ||
   2111      aDrawOptions.mCompositionOp > CompositionOp::OP_COUNT) {
   2112    aStream.SetIsBad();
   2113  }
   2114 }
   2115 
   2116 template <class S>
   2117 static void ReadDrawSurfaceOptions(S& aStream,
   2118                                   DrawSurfaceOptions& aDrawSurfaceOptions) {
   2119  ReadElement(aStream, aDrawSurfaceOptions);
   2120  if (aDrawSurfaceOptions.mSamplingFilter < SamplingFilter::GOOD ||
   2121      aDrawSurfaceOptions.mSamplingFilter >= SamplingFilter::SENTINEL) {
   2122    aStream.SetIsBad();
   2123    return;
   2124  }
   2125 
   2126  if (aDrawSurfaceOptions.mSamplingBounds < SamplingBounds::UNBOUNDED ||
   2127      aDrawSurfaceOptions.mSamplingBounds > SamplingBounds::BOUNDED) {
   2128    aStream.SetIsBad();
   2129  }
   2130 }
   2131 
   2132 inline void RecordedEvent::OutputSimplePatternInfo(
   2133    const PatternStorage& aStorage, std::stringstream& aOutput) const {
   2134  switch (aStorage.mType) {
   2135    case PatternType::COLOR: {
   2136      const DeviceColor color =
   2137          reinterpret_cast<const ColorPatternStorage*>(&aStorage.mStorage)
   2138              ->mColor;
   2139      aOutput << "DeviceColor: (" << color.r << ", " << color.g << ", "
   2140              << color.b << ", " << color.a << ")";
   2141      return;
   2142    }
   2143    case PatternType::LINEAR_GRADIENT: {
   2144      const LinearGradientPatternStorage* store =
   2145          reinterpret_cast<const LinearGradientPatternStorage*>(
   2146              &aStorage.mStorage);
   2147 
   2148      aOutput << "LinearGradient (" << store->mBegin.x << ", "
   2149              << store->mBegin.y << ") - (" << store->mEnd.x << ", "
   2150              << store->mEnd.y << ") Stops: " << store->mStops;
   2151      return;
   2152    }
   2153    case PatternType::RADIAL_GRADIENT: {
   2154      const RadialGradientPatternStorage* store =
   2155          reinterpret_cast<const RadialGradientPatternStorage*>(
   2156              &aStorage.mStorage);
   2157      aOutput << "RadialGradient (Center 1: (" << store->mCenter1.x << ", "
   2158              << store->mCenter2.y << ") Radius 2: " << store->mRadius2;
   2159      return;
   2160    }
   2161    case PatternType::CONIC_GRADIENT: {
   2162      const ConicGradientPatternStorage* store =
   2163          reinterpret_cast<const ConicGradientPatternStorage*>(
   2164              &aStorage.mStorage);
   2165      aOutput << "ConicGradient (Center: (" << store->mCenter.x << ", "
   2166              << store->mCenter.y << ") Angle: " << store->mAngle
   2167              << " Range:" << store->mStartOffset << " - " << store->mEndOffset;
   2168      return;
   2169    }
   2170    case PatternType::SURFACE: {
   2171      const SurfacePatternStorage* store =
   2172          reinterpret_cast<const SurfacePatternStorage*>(&aStorage.mStorage);
   2173      aOutput << "Surface (0x" << store->mSurface << ")";
   2174      return;
   2175    }
   2176  }
   2177 }
   2178 
   2179 inline bool RecordedDrawTargetCreation::PlayEvent(
   2180    Translator* aTranslator) const {
   2181  RefPtr<DrawTarget> newDT =
   2182      aTranslator->CreateDrawTarget(mRefPtr, mRect.Size(), mFormat);
   2183 
   2184  // If we couldn't create a DrawTarget this will probably cause us to crash
   2185  // with nullptr later in the playback, so return false to abort.
   2186  if (!newDT) {
   2187    return false;
   2188  }
   2189 
   2190  if (mHasExistingData) {
   2191    Rect dataRect(0, 0, mExistingData->GetSize().width,
   2192                  mExistingData->GetSize().height);
   2193    newDT->DrawSurface(mExistingData, dataRect, dataRect);
   2194  }
   2195 
   2196  return true;
   2197 }
   2198 
   2199 template <class S>
   2200 void RecordedDrawTargetCreation::Record(S& aStream) const {
   2201  WriteElement(aStream, mRefPtr);
   2202  WriteElement(aStream, mBackendType);
   2203  WriteElement(aStream, mRect);
   2204  WriteElement(aStream, mFormat);
   2205  WriteElement(aStream, mHasExistingData);
   2206 
   2207  if (mHasExistingData) {
   2208    MOZ_ASSERT(mExistingData);
   2209    MOZ_ASSERT(mExistingData->GetSize() == mRect.Size());
   2210    RefPtr<DataSourceSurface> dataSurf = mExistingData->GetDataSurface();
   2211 
   2212    DataSourceSurface::ScopedMap map(dataSurf, DataSourceSurface::READ);
   2213    for (int y = 0; y < mRect.height; y++) {
   2214      aStream.write((const char*)map.GetData() + y * map.GetStride(),
   2215                    BytesPerPixel(mFormat) * mRect.width);
   2216    }
   2217  }
   2218 }
   2219 
   2220 template <class S>
   2221 RecordedDrawTargetCreation::RecordedDrawTargetCreation(S& aStream)
   2222    : RecordedEventDerived(DRAWTARGETCREATION), mExistingData(nullptr) {
   2223  ReadElement(aStream, mRefPtr);
   2224  ReadElementConstrained(aStream, mBackendType, BackendType::NONE,
   2225                         BackendType::WEBRENDER_TEXT);
   2226  ReadElement(aStream, mRect);
   2227  ReadElementConstrained(aStream, mFormat, SurfaceFormat::B8G8R8A8,
   2228                         SurfaceFormat::UNKNOWN);
   2229  ReadElement(aStream, mHasExistingData);
   2230 
   2231  if (mHasExistingData) {
   2232    RefPtr<DataSourceSurface> dataSurf =
   2233        Factory::CreateDataSourceSurface(mRect.Size(), mFormat);
   2234    if (!dataSurf) {
   2235      gfxWarning()
   2236          << "RecordedDrawTargetCreation had to reset mHasExistingData";
   2237      mHasExistingData = false;
   2238      return;
   2239    }
   2240 
   2241    DataSourceSurface::ScopedMap map(dataSurf, DataSourceSurface::READ);
   2242    for (int y = 0; y < mRect.height; y++) {
   2243      aStream.read((char*)map.GetData() + y * map.GetStride(),
   2244                   BytesPerPixel(mFormat) * mRect.width);
   2245    }
   2246    mExistingData = dataSurf;
   2247  }
   2248 }
   2249 
   2250 inline void RecordedDrawTargetCreation::OutputSimpleEventInfo(
   2251    std::stringstream& aStringStream) const {
   2252  aStringStream << "[" << mRefPtr << "] DrawTarget Creation (Type: "
   2253                << NameFromBackend(mBackendType) << ", Size: " << mRect.width
   2254                << "x" << mRect.height << ")";
   2255 }
   2256 
   2257 inline bool RecordedDrawTargetDestruction::PlayEvent(
   2258    Translator* aTranslator) const {
   2259  aTranslator->RemoveDrawTarget(mRefPtr);
   2260  return true;
   2261 }
   2262 
   2263 template <class S>
   2264 void RecordedDrawTargetDestruction::Record(S& aStream) const {
   2265  WriteElement(aStream, mRefPtr);
   2266 }
   2267 
   2268 template <class S>
   2269 RecordedDrawTargetDestruction::RecordedDrawTargetDestruction(S& aStream)
   2270    : RecordedEventDerived(DRAWTARGETDESTRUCTION) {
   2271  ReadElement(aStream, mRefPtr);
   2272 }
   2273 
   2274 inline void RecordedDrawTargetDestruction::OutputSimpleEventInfo(
   2275    std::stringstream& aStringStream) const {
   2276  aStringStream << "[" << mRefPtr << "] DrawTarget Destruction";
   2277 }
   2278 
   2279 inline bool RecordedSetCurrentDrawTarget::PlayEvent(
   2280    Translator* aTranslator) const {
   2281  return aTranslator->SetCurrentDrawTarget(mRefPtr);
   2282 }
   2283 
   2284 template <class S>
   2285 void RecordedSetCurrentDrawTarget::Record(S& aStream) const {
   2286  WriteElement(aStream, mRefPtr);
   2287 }
   2288 
   2289 template <class S>
   2290 RecordedSetCurrentDrawTarget::RecordedSetCurrentDrawTarget(S& aStream)
   2291    : RecordedEventDerived(SETCURRENTDRAWTARGET) {
   2292  ReadElement(aStream, mRefPtr);
   2293 }
   2294 
   2295 inline void RecordedSetCurrentDrawTarget::OutputSimpleEventInfo(
   2296    std::stringstream& aStringStream) const {
   2297  aStringStream << "[" << mRefPtr << "] SetCurrentDrawTarget";
   2298 }
   2299 
   2300 inline bool RecordedCreateSimilarDrawTarget::PlayEvent(
   2301    Translator* aTranslator) const {
   2302  DrawTarget* drawTarget = aTranslator->GetCurrentDrawTarget();
   2303  if (!drawTarget) {
   2304    return false;
   2305  }
   2306 
   2307  RefPtr<DrawTarget> newDT =
   2308      drawTarget->CreateSimilarDrawTarget(mSize, mFormat);
   2309 
   2310  // If we couldn't create a DrawTarget this will probably cause us to crash
   2311  // with nullptr later in the playback, so return false to abort.
   2312  if (!newDT) {
   2313    return false;
   2314  }
   2315 
   2316  aTranslator->AddDrawTarget(mRefPtr, newDT);
   2317  return true;
   2318 }
   2319 
   2320 template <class S>
   2321 void RecordedCreateSimilarDrawTarget::Record(S& aStream) const {
   2322  WriteElement(aStream, mRefPtr);
   2323  WriteElement(aStream, mSize);
   2324  WriteElement(aStream, mFormat);
   2325 }
   2326 
   2327 template <class S>
   2328 RecordedCreateSimilarDrawTarget::RecordedCreateSimilarDrawTarget(S& aStream)
   2329    : RecordedEventDerived(CREATESIMILARDRAWTARGET) {
   2330  ReadElement(aStream, mRefPtr);
   2331  ReadElement(aStream, mSize);
   2332  ReadElementConstrained(aStream, mFormat, SurfaceFormat::B8G8R8A8,
   2333                         SurfaceFormat::UNKNOWN);
   2334 }
   2335 
   2336 inline void RecordedCreateSimilarDrawTarget::OutputSimpleEventInfo(
   2337    std::stringstream& aStringStream) const {
   2338  aStringStream << "[" << mRefPtr
   2339                << "] CreateSimilarDrawTarget (Size: " << mSize.width << "x"
   2340                << mSize.height << ")";
   2341 }
   2342 
   2343 inline bool RecordedCreateDrawTargetForFilter::PlayEvent(
   2344    Translator* aTranslator) const {
   2345  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2346  if (!dt) {
   2347    return false;
   2348  }
   2349 
   2350  IntRect baseRect = dt->GetRect();
   2351 
   2352  auto maxRect = IntRect(IntPoint(0, 0), mMaxSize);
   2353 
   2354  auto clone = dt->GetTransform();
   2355  bool invertible = clone.Invert();
   2356  // mSourceRect is in filter space. The filter outputs from mSourceRect need
   2357  // to be drawn at mDestPoint in user space.
   2358  Rect userSpaceSource = Rect(mDestPoint, mSourceRect.Size());
   2359  if (invertible) {
   2360    // Try to reduce the source rect so that it's not much bigger
   2361    // than the draw target. The result is not minimal. Examples
   2362    // are left as an exercise for the reader.
   2363    auto destRect = IntRectToRect(baseRect);
   2364    Rect userSpaceBounds = clone.TransformBounds(destRect);
   2365    userSpaceSource = userSpaceSource.Intersect(userSpaceBounds);
   2366  }
   2367 
   2368  // Compute how much we moved the top-left of the source rect by, and use that
   2369  // to compute the new dest point, and move our intersected source rect back
   2370  // into the (new) filter space.
   2371  Point shift = userSpaceSource.TopLeft() - mDestPoint;
   2372  Rect filterSpaceSource =
   2373      Rect(mSourceRect.TopLeft() + shift, userSpaceSource.Size());
   2374 
   2375  baseRect = RoundedOut(filterSpaceSource);
   2376  FilterNode* filter = aTranslator->LookupFilterNode(mFilter);
   2377  if (!filter) {
   2378    return false;
   2379  }
   2380 
   2381  IntRect transformedRect = filter->MapRectToSource(
   2382      baseRect, maxRect, aTranslator->LookupFilterNode(mSource));
   2383 
   2384  // Intersect with maxRect to make sure we didn't end up with something bigger
   2385  transformedRect = transformedRect.Intersect(maxRect);
   2386 
   2387  // If we end up with an empty rect make it 1x1 so that things don't break.
   2388  if (transformedRect.IsEmpty()) {
   2389    transformedRect = IntRect(0, 0, 1, 1);
   2390  }
   2391 
   2392  RefPtr<DrawTarget> newDT =
   2393      dt->CreateSimilarDrawTarget(transformedRect.Size(), mFormat);
   2394  if (!newDT) {
   2395    return false;
   2396  }
   2397  newDT =
   2398      gfx::Factory::CreateOffsetDrawTarget(newDT, transformedRect.TopLeft());
   2399 
   2400  // If we couldn't create a DrawTarget this will probably cause us to crash
   2401  // with nullptr later in the playback, so return false to abort.
   2402  if (!newDT) {
   2403    return false;
   2404  }
   2405 
   2406  aTranslator->AddDrawTarget(mRefPtr, newDT);
   2407  return true;
   2408 }
   2409 
   2410 inline bool RecordedCreateClippedDrawTarget::PlayEvent(
   2411    Translator* aTranslator) const {
   2412  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2413  if (!dt) {
   2414    return false;
   2415  }
   2416 
   2417  RefPtr<DrawTarget> newDT = dt->CreateClippedDrawTarget(mBounds, mFormat);
   2418 
   2419  // If we couldn't create a DrawTarget this will probably cause us to crash
   2420  // with nullptr later in the playback, so return false to abort.
   2421  if (!newDT) {
   2422    return false;
   2423  }
   2424 
   2425  aTranslator->AddDrawTarget(mRefPtr, newDT);
   2426  return true;
   2427 }
   2428 
   2429 template <class S>
   2430 void RecordedCreateClippedDrawTarget::Record(S& aStream) const {
   2431  WriteElement(aStream, mRefPtr);
   2432  WriteElement(aStream, mBounds);
   2433  WriteElement(aStream, mFormat);
   2434 }
   2435 
   2436 template <class S>
   2437 RecordedCreateClippedDrawTarget::RecordedCreateClippedDrawTarget(S& aStream)
   2438    : RecordedEventDerived(CREATECLIPPEDDRAWTARGET) {
   2439  ReadElement(aStream, mRefPtr);
   2440  ReadElement(aStream, mBounds);
   2441  ReadElementConstrained(aStream, mFormat, SurfaceFormat::B8G8R8A8,
   2442                         SurfaceFormat::UNKNOWN);
   2443 }
   2444 
   2445 inline void RecordedCreateClippedDrawTarget::OutputSimpleEventInfo(
   2446    std::stringstream& aStringStream) const {
   2447  aStringStream << "[" << mRefPtr << "] CreateClippedDrawTarget ()";
   2448 }
   2449 
   2450 template <class S>
   2451 void RecordedCreateDrawTargetForFilter::Record(S& aStream) const {
   2452  WriteElement(aStream, mRefPtr);
   2453  WriteElement(aStream, mMaxSize);
   2454  WriteElement(aStream, mFormat);
   2455  WriteElement(aStream, mFilter);
   2456  WriteElement(aStream, mSource);
   2457  WriteElement(aStream, mSourceRect);
   2458  WriteElement(aStream, mDestPoint);
   2459 }
   2460 
   2461 template <class S>
   2462 RecordedCreateDrawTargetForFilter::RecordedCreateDrawTargetForFilter(S& aStream)
   2463    : RecordedEventDerived(CREATEDRAWTARGETFORFILTER) {
   2464  ReadElement(aStream, mRefPtr);
   2465  ReadElement(aStream, mMaxSize);
   2466  ReadElementConstrained(aStream, mFormat, SurfaceFormat::B8G8R8A8,
   2467                         SurfaceFormat::UNKNOWN);
   2468  ReadElement(aStream, mFilter);
   2469  ReadElement(aStream, mSource);
   2470  ReadElement(aStream, mSourceRect);
   2471  ReadElement(aStream, mDestPoint);
   2472 }
   2473 
   2474 inline void RecordedCreateDrawTargetForFilter::OutputSimpleEventInfo(
   2475    std::stringstream& aStringStream) const {
   2476  aStringStream << "[" << mRefPtr << "] CreateDrawTargetForFilter ()";
   2477 }
   2478 
   2479 struct GenericPattern {
   2480  GenericPattern(const PatternStorage& aStorage, Translator* aTranslator)
   2481      : mPattern(nullptr), mTranslator(aTranslator) {
   2482    mStorage = const_cast<PatternStorage*>(&aStorage);
   2483  }
   2484 
   2485  ~GenericPattern() {
   2486    if (mPattern) {
   2487      mPattern->~Pattern();
   2488    }
   2489  }
   2490 
   2491  operator Pattern*() {
   2492    switch (mStorage->mType) {
   2493      case PatternType::COLOR:
   2494        return new (mColPat) ColorPattern(
   2495            reinterpret_cast<ColorPatternStorage*>(&mStorage->mStorage)
   2496                ->mColor);
   2497      case PatternType::SURFACE: {
   2498        SurfacePatternStorage* storage =
   2499            reinterpret_cast<SurfacePatternStorage*>(&mStorage->mStorage);
   2500        mPattern = new (mSurfPat)
   2501            SurfacePattern(mTranslator->LookupSourceSurface(storage->mSurface),
   2502                           storage->mExtend, storage->mMatrix,
   2503                           storage->mSamplingFilter, storage->mSamplingRect);
   2504        return mPattern;
   2505      }
   2506      case PatternType::LINEAR_GRADIENT: {
   2507        LinearGradientPatternStorage* storage =
   2508            reinterpret_cast<LinearGradientPatternStorage*>(
   2509                &mStorage->mStorage);
   2510        mPattern = new (mLinGradPat) LinearGradientPattern(
   2511            storage->mBegin, storage->mEnd,
   2512            storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
   2513                            : nullptr,
   2514            storage->mMatrix);
   2515        return mPattern;
   2516      }
   2517      case PatternType::RADIAL_GRADIENT: {
   2518        RadialGradientPatternStorage* storage =
   2519            reinterpret_cast<RadialGradientPatternStorage*>(
   2520                &mStorage->mStorage);
   2521        mPattern = new (mRadGradPat) RadialGradientPattern(
   2522            storage->mCenter1, storage->mCenter2, storage->mRadius1,
   2523            storage->mRadius2,
   2524            storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
   2525                            : nullptr,
   2526            storage->mMatrix);
   2527        return mPattern;
   2528      }
   2529      case PatternType::CONIC_GRADIENT: {
   2530        ConicGradientPatternStorage* storage =
   2531            reinterpret_cast<ConicGradientPatternStorage*>(&mStorage->mStorage);
   2532        mPattern = new (mConGradPat) ConicGradientPattern(
   2533            storage->mCenter, storage->mAngle, storage->mStartOffset,
   2534            storage->mEndOffset,
   2535            storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
   2536                            : nullptr,
   2537            storage->mMatrix);
   2538        return mPattern;
   2539      }
   2540      default:
   2541        return new (mColPat) ColorPattern(DeviceColor());
   2542    }
   2543 
   2544    return mPattern;
   2545  }
   2546 
   2547  union {
   2548    char mColPat[sizeof(ColorPattern)];
   2549    char mLinGradPat[sizeof(LinearGradientPattern)];
   2550    char mRadGradPat[sizeof(RadialGradientPattern)];
   2551    char mConGradPat[sizeof(ConicGradientPattern)];
   2552    char mSurfPat[sizeof(SurfacePattern)];
   2553  };
   2554 
   2555  PatternStorage* mStorage;
   2556  Pattern* mPattern;
   2557  Translator* mTranslator;
   2558 };
   2559 
   2560 inline bool RecordedFillRect::PlayEvent(Translator* aTranslator) const {
   2561  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2562  if (!dt) {
   2563    return false;
   2564  }
   2565 
   2566  dt->FillRect(mRect, *GenericPattern(mPattern, aTranslator), mOptions);
   2567  return true;
   2568 }
   2569 
   2570 template <class S>
   2571 void RecordedFillRect::Record(S& aStream) const {
   2572  WriteElement(aStream, mRect);
   2573  WriteElement(aStream, mOptions);
   2574  RecordPatternData(aStream, mPattern);
   2575 }
   2576 
   2577 template <class S>
   2578 RecordedFillRect::RecordedFillRect(S& aStream)
   2579    : RecordedEventDerived(FILLRECT) {
   2580  ReadElement(aStream, mRect);
   2581  ReadDrawOptions(aStream, mOptions);
   2582  ReadPatternData(aStream, mPattern);
   2583 }
   2584 
   2585 inline void RecordedFillRect::OutputSimpleEventInfo(
   2586    std::stringstream& aStringStream) const {
   2587  aStringStream << "FillRect (" << mRect.X() << ", " << mRect.Y() << " - "
   2588                << mRect.Width() << " x " << mRect.Height() << ") ";
   2589  OutputSimplePatternInfo(mPattern, aStringStream);
   2590 }
   2591 
   2592 inline bool RecordedStrokeRect::PlayEvent(Translator* aTranslator) const {
   2593  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2594  if (!dt) {
   2595    return false;
   2596  }
   2597 
   2598  dt->StrokeRect(mRect, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
   2599                 mOptions);
   2600  return true;
   2601 }
   2602 
   2603 template <class S>
   2604 void RecordedStrokeRect::Record(S& aStream) const {
   2605  WriteElement(aStream, mRect);
   2606  WriteElement(aStream, mOptions);
   2607  RecordPatternData(aStream, mPattern);
   2608  RecordStrokeOptions(aStream, mStrokeOptions);
   2609 }
   2610 
   2611 template <class S>
   2612 RecordedStrokeRect::RecordedStrokeRect(S& aStream)
   2613    : RecordedEventDerived(STROKERECT) {
   2614  ReadElement(aStream, mRect);
   2615  ReadDrawOptions(aStream, mOptions);
   2616  ReadPatternData(aStream, mPattern);
   2617  ReadStrokeOptions(aStream, mStrokeOptions);
   2618 }
   2619 
   2620 inline void RecordedStrokeRect::OutputSimpleEventInfo(
   2621    std::stringstream& aStringStream) const {
   2622  aStringStream << "StrokeRect (" << mRect.X() << ", " << mRect.Y() << " - "
   2623                << mRect.Width() << " x " << mRect.Height()
   2624                << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   2625  OutputSimplePatternInfo(mPattern, aStringStream);
   2626 }
   2627 
   2628 inline bool RecordedStrokeLine::PlayEvent(Translator* aTranslator) const {
   2629  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2630  if (!dt) {
   2631    return false;
   2632  }
   2633 
   2634  dt->StrokeLine(mBegin, mEnd, *GenericPattern(mPattern, aTranslator),
   2635                 mStrokeOptions, mOptions);
   2636  return true;
   2637 }
   2638 
   2639 template <class S>
   2640 void RecordedStrokeLine::Record(S& aStream) const {
   2641  WriteElement(aStream, mBegin);
   2642  WriteElement(aStream, mEnd);
   2643  WriteElement(aStream, mOptions);
   2644  RecordPatternData(aStream, mPattern);
   2645  RecordStrokeOptions(aStream, mStrokeOptions);
   2646 }
   2647 
   2648 template <class S>
   2649 RecordedStrokeLine::RecordedStrokeLine(S& aStream)
   2650    : RecordedEventDerived(STROKELINE) {
   2651  ReadElement(aStream, mBegin);
   2652  ReadElement(aStream, mEnd);
   2653  ReadDrawOptions(aStream, mOptions);
   2654  ReadPatternData(aStream, mPattern);
   2655  ReadStrokeOptions(aStream, mStrokeOptions);
   2656 }
   2657 
   2658 inline void RecordedStrokeLine::OutputSimpleEventInfo(
   2659    std::stringstream& aStringStream) const {
   2660  aStringStream << "StrokeLine (" << mBegin.x << ", " << mBegin.y << " - "
   2661                << mEnd.x << ", " << mEnd.y
   2662                << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   2663  OutputSimplePatternInfo(mPattern, aStringStream);
   2664 }
   2665 
   2666 inline bool RecordedStrokeCircle::PlayEvent(Translator* aTranslator) const {
   2667  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2668  if (!dt) {
   2669    return false;
   2670  }
   2671 
   2672  dt->StrokeCircle(mCircle.origin, mCircle.radius,
   2673                   *GenericPattern(mPattern, aTranslator), mStrokeOptions,
   2674                   mOptions);
   2675  return true;
   2676 }
   2677 
   2678 template <class S>
   2679 void RecordedStrokeCircle::Record(S& aStream) const {
   2680  WriteElement(aStream, mCircle);
   2681  WriteElement(aStream, mOptions);
   2682  RecordPatternData(aStream, mPattern);
   2683  RecordStrokeOptions(aStream, mStrokeOptions);
   2684 }
   2685 
   2686 template <class S>
   2687 RecordedStrokeCircle::RecordedStrokeCircle(S& aStream)
   2688    : RecordedEventDerived(STROKECIRCLE) {
   2689  ReadElement(aStream, mCircle);
   2690  ReadDrawOptions(aStream, mOptions);
   2691  ReadPatternData(aStream, mPattern);
   2692  ReadStrokeOptions(aStream, mStrokeOptions);
   2693 }
   2694 
   2695 inline void RecordedStrokeCircle::OutputSimpleEventInfo(
   2696    std::stringstream& aStringStream) const {
   2697  aStringStream << "StrokeCircle (" << mCircle.origin.x << ", "
   2698                << mCircle.origin.y << " - " << mCircle.radius
   2699                << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   2700  OutputSimplePatternInfo(mPattern, aStringStream);
   2701 }
   2702 
   2703 inline bool RecordedFill::PlayEvent(Translator* aTranslator) const {
   2704  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2705  if (!dt) {
   2706    return false;
   2707  }
   2708 
   2709  dt->Fill(aTranslator->LookupPath(mPath),
   2710           *GenericPattern(mPattern, aTranslator), mOptions);
   2711  return true;
   2712 }
   2713 
   2714 template <class S>
   2715 RecordedFill::RecordedFill(S& aStream) : RecordedEventDerived(FILL) {
   2716  ReadElement(aStream, mPath);
   2717  ReadDrawOptions(aStream, mOptions);
   2718  ReadPatternData(aStream, mPattern);
   2719 }
   2720 
   2721 template <class S>
   2722 void RecordedFill::Record(S& aStream) const {
   2723  WriteElement(aStream, mPath);
   2724  WriteElement(aStream, mOptions);
   2725  RecordPatternData(aStream, mPattern);
   2726 }
   2727 
   2728 inline void RecordedFill::OutputSimpleEventInfo(
   2729    std::stringstream& aStringStream) const {
   2730  aStringStream << "Fill (" << mPath << ") ";
   2731  OutputSimplePatternInfo(mPattern, aStringStream);
   2732 }
   2733 
   2734 inline bool RecordedFillCircle::PlayEvent(Translator* aTranslator) const {
   2735  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2736  if (!dt) {
   2737    return false;
   2738  }
   2739 
   2740  dt->FillCircle(mCircle.origin, mCircle.radius,
   2741                 *GenericPattern(mPattern, aTranslator), mOptions);
   2742  return true;
   2743 }
   2744 
   2745 template <class S>
   2746 void RecordedFillCircle::Record(S& aStream) const {
   2747  WriteElement(aStream, mCircle);
   2748  WriteElement(aStream, mOptions);
   2749  RecordPatternData(aStream, mPattern);
   2750 }
   2751 
   2752 template <class S>
   2753 RecordedFillCircle::RecordedFillCircle(S& aStream)
   2754    : RecordedEventDerived(FILLCIRCLE) {
   2755  ReadElement(aStream, mCircle);
   2756  ReadDrawOptions(aStream, mOptions);
   2757  ReadPatternData(aStream, mPattern);
   2758 }
   2759 
   2760 inline void RecordedFillCircle::OutputSimpleEventInfo(
   2761    std::stringstream& aStringStream) const {
   2762  aStringStream << "FillCircle (" << mCircle.origin.x << ", "
   2763                << mCircle.origin.y << " - " << mCircle.radius << ")";
   2764  OutputSimplePatternInfo(mPattern, aStringStream);
   2765 }
   2766 
   2767 template <class T>
   2768 inline bool RecordedDrawGlyphs<T>::PlayEvent(Translator* aTranslator) const {
   2769  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2770  if (!dt) {
   2771    return false;
   2772  }
   2773 
   2774  ScaledFont* scaledFont = aTranslator->LookupScaledFont(mScaledFont);
   2775  if (!scaledFont) {
   2776    return false;
   2777  }
   2778 
   2779  GlyphBuffer buffer;
   2780  buffer.mGlyphs = mGlyphs.data();
   2781  buffer.mNumGlyphs = mGlyphs.size();
   2782  DrawGlyphs(dt, scaledFont, buffer, *GenericPattern(mPattern, aTranslator));
   2783  return true;
   2784 }
   2785 
   2786 template <class T>
   2787 template <class S>
   2788 RecordedDrawGlyphs<T>::RecordedDrawGlyphs(RecordedEvent::EventType aType,
   2789                                          S& aStream)
   2790    : RecordedEventDerived<T>(aType) {
   2791  ReadElement(aStream, mScaledFont);
   2792  ReadDrawOptions(aStream, mOptions);
   2793  this->ReadPatternData(aStream, mPattern);
   2794  uint32_t numGlyphs = 0;
   2795  ReadElement(aStream, numGlyphs);
   2796  if (!aStream.good() || numGlyphs <= 0) {
   2797    return;
   2798  }
   2799 
   2800  if (!mGlyphs.Read(aStream, numGlyphs)) {
   2801    gfxCriticalNote << "RecordedDrawGlyphs failed to allocate glyphs of size "
   2802                    << numGlyphs;
   2803    aStream.SetIsBad();
   2804  }
   2805 }
   2806 
   2807 template <class T>
   2808 template <class S>
   2809 void RecordedDrawGlyphs<T>::Record(S& aStream) const {
   2810  WriteElement(aStream, mScaledFont);
   2811  WriteElement(aStream, mOptions);
   2812  this->RecordPatternData(aStream, mPattern);
   2813  WriteElement(aStream, mGlyphs.size());
   2814  mGlyphs.Write(aStream);
   2815 }
   2816 
   2817 template <class T>
   2818 inline void RecordedDrawGlyphs<T>::OutputSimpleEventInfo(
   2819    std::stringstream& aStringStream) const {
   2820  aStringStream << this->GetName() << " (" << mScaledFont << ") ";
   2821  this->OutputSimplePatternInfo(mPattern, aStringStream);
   2822 }
   2823 
   2824 inline bool RecordedMask::PlayEvent(Translator* aTranslator) const {
   2825  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2826  if (!dt) {
   2827    return false;
   2828  }
   2829 
   2830  dt->Mask(*GenericPattern(mSource, aTranslator),
   2831           *GenericPattern(mMask, aTranslator), mOptions);
   2832  return true;
   2833 }
   2834 
   2835 template <class S>
   2836 RecordedMask::RecordedMask(S& aStream) : RecordedEventDerived(MASK) {
   2837  ReadDrawOptions(aStream, mOptions);
   2838  ReadPatternData(aStream, mSource);
   2839  ReadPatternData(aStream, mMask);
   2840 }
   2841 
   2842 template <class S>
   2843 void RecordedMask::Record(S& aStream) const {
   2844  WriteElement(aStream, mOptions);
   2845  RecordPatternData(aStream, mSource);
   2846  RecordPatternData(aStream, mMask);
   2847 }
   2848 
   2849 inline void RecordedMask::OutputSimpleEventInfo(
   2850    std::stringstream& aStringStream) const {
   2851  aStringStream << "Mask (Source: ";
   2852  OutputSimplePatternInfo(mSource, aStringStream);
   2853  aStringStream << " Mask: ";
   2854  OutputSimplePatternInfo(mMask, aStringStream);
   2855 }
   2856 
   2857 inline bool RecordedStroke::PlayEvent(Translator* aTranslator) const {
   2858  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2859  if (!dt) {
   2860    return false;
   2861  }
   2862 
   2863  Path* path = aTranslator->LookupPath(mPath);
   2864  if (!path) {
   2865    return false;
   2866  }
   2867 
   2868  dt->Stroke(path, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
   2869             mOptions);
   2870  return true;
   2871 }
   2872 
   2873 template <class S>
   2874 void RecordedStroke::Record(S& aStream) const {
   2875  WriteElement(aStream, mPath);
   2876  WriteElement(aStream, mOptions);
   2877  RecordPatternData(aStream, mPattern);
   2878  RecordStrokeOptions(aStream, mStrokeOptions);
   2879 }
   2880 
   2881 template <class S>
   2882 RecordedStroke::RecordedStroke(S& aStream) : RecordedEventDerived(STROKE) {
   2883  ReadElement(aStream, mPath);
   2884  ReadDrawOptions(aStream, mOptions);
   2885  ReadPatternData(aStream, mPattern);
   2886  ReadStrokeOptions(aStream, mStrokeOptions);
   2887 }
   2888 
   2889 inline void RecordedStroke::OutputSimpleEventInfo(
   2890    std::stringstream& aStringStream) const {
   2891  aStringStream << "Stroke (" << mPath
   2892                << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
   2893  OutputSimplePatternInfo(mPattern, aStringStream);
   2894 }
   2895 
   2896 inline bool RecordedClearRect::PlayEvent(Translator* aTranslator) const {
   2897  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2898  if (!dt) {
   2899    return false;
   2900  }
   2901 
   2902  dt->ClearRect(mRect);
   2903  return true;
   2904 }
   2905 
   2906 template <class S>
   2907 void RecordedClearRect::Record(S& aStream) const {
   2908  WriteElement(aStream, mRect);
   2909 }
   2910 
   2911 template <class S>
   2912 RecordedClearRect::RecordedClearRect(S& aStream)
   2913    : RecordedEventDerived(CLEARRECT) {
   2914  ReadElement(aStream, mRect);
   2915 }
   2916 
   2917 inline void RecordedClearRect::OutputSimpleEventInfo(
   2918    std::stringstream& aStringStream) const {
   2919  aStringStream << "ClearRect (" << mRect.X() << ", " << mRect.Y() << " - "
   2920                << mRect.Width() << " x " << mRect.Height() << ") ";
   2921 }
   2922 
   2923 inline bool RecordedCopySurface::PlayEvent(Translator* aTranslator) const {
   2924  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2925  if (!dt) {
   2926    return false;
   2927  }
   2928 
   2929  SourceSurface* surface = aTranslator->LookupSourceSurface(mSourceSurface);
   2930  if (!surface) {
   2931    return false;
   2932  }
   2933 
   2934  dt->CopySurface(surface, mSourceRect, mDest);
   2935  return true;
   2936 }
   2937 
   2938 template <class S>
   2939 void RecordedCopySurface::Record(S& aStream) const {
   2940  WriteElement(aStream, mSourceSurface);
   2941  WriteElement(aStream, mSourceRect);
   2942  WriteElement(aStream, mDest);
   2943 }
   2944 
   2945 template <class S>
   2946 RecordedCopySurface::RecordedCopySurface(S& aStream)
   2947    : RecordedEventDerived(COPYSURFACE) {
   2948  ReadElement(aStream, mSourceSurface);
   2949  ReadElement(aStream, mSourceRect);
   2950  ReadElement(aStream, mDest);
   2951 }
   2952 
   2953 inline void RecordedCopySurface::OutputSimpleEventInfo(
   2954    std::stringstream& aStringStream) const {
   2955  aStringStream << "CopySurface (" << mSourceSurface << ")";
   2956 }
   2957 
   2958 inline bool RecordedPushClip::PlayEvent(Translator* aTranslator) const {
   2959  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2960  if (!dt) {
   2961    return false;
   2962  }
   2963 
   2964  Path* path = aTranslator->LookupPath(mPath);
   2965  if (!path) {
   2966    return false;
   2967  }
   2968 
   2969  dt->PushClip(path);
   2970  return true;
   2971 }
   2972 
   2973 template <class S>
   2974 void RecordedPushClip::Record(S& aStream) const {
   2975  WriteElement(aStream, mPath);
   2976 }
   2977 
   2978 template <class S>
   2979 RecordedPushClip::RecordedPushClip(S& aStream)
   2980    : RecordedEventDerived(PUSHCLIP) {
   2981  ReadElement(aStream, mPath);
   2982 }
   2983 
   2984 inline void RecordedPushClip::OutputSimpleEventInfo(
   2985    std::stringstream& aStringStream) const {
   2986  aStringStream << "PushClip (" << mPath << ") ";
   2987 }
   2988 
   2989 inline bool RecordedPushClipRect::PlayEvent(Translator* aTranslator) const {
   2990  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   2991  if (!dt) {
   2992    return false;
   2993  }
   2994 
   2995  dt->PushClipRect(mRect);
   2996  return true;
   2997 }
   2998 
   2999 template <class S>
   3000 void RecordedPushClipRect::Record(S& aStream) const {
   3001  WriteElement(aStream, mRect);
   3002 }
   3003 
   3004 template <class S>
   3005 RecordedPushClipRect::RecordedPushClipRect(S& aStream)
   3006    : RecordedEventDerived(PUSHCLIPRECT) {
   3007  ReadElement(aStream, mRect);
   3008 }
   3009 
   3010 inline void RecordedPushClipRect::OutputSimpleEventInfo(
   3011    std::stringstream& aStringStream) const {
   3012  aStringStream << "PushClipRect (" << mRect.X() << ", " << mRect.Y() << " - "
   3013                << mRect.Width() << " x " << mRect.Height() << ") ";
   3014 }
   3015 
   3016 inline bool RecordedPopClip::PlayEvent(Translator* aTranslator) const {
   3017  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3018  if (!dt) {
   3019    return false;
   3020  }
   3021 
   3022  dt->PopClip();
   3023  return true;
   3024 }
   3025 
   3026 template <class S>
   3027 void RecordedPopClip::Record(S& aStream) const {}
   3028 
   3029 template <class S>
   3030 RecordedPopClip::RecordedPopClip(S& aStream) : RecordedEventDerived(POPCLIP) {}
   3031 
   3032 inline void RecordedPopClip::OutputSimpleEventInfo(
   3033    std::stringstream& aStringStream) const {
   3034  aStringStream << "PopClip";
   3035 }
   3036 
   3037 inline bool RecordedRemoveAllClips::PlayEvent(Translator* aTranslator) const {
   3038  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3039  if (!dt) {
   3040    return false;
   3041  }
   3042 
   3043  dt->RemoveAllClips();
   3044  return true;
   3045 }
   3046 
   3047 template <class S>
   3048 void RecordedRemoveAllClips::Record(S& aStream) const {}
   3049 
   3050 template <class S>
   3051 RecordedRemoveAllClips::RecordedRemoveAllClips(S& aStream)
   3052    : RecordedEventDerived(REMOVEALLCLIPS) {}
   3053 
   3054 inline void RecordedRemoveAllClips::OutputSimpleEventInfo(
   3055    std::stringstream& aStringStream) const {
   3056  aStringStream << "RemoveAllClips";
   3057 }
   3058 
   3059 inline bool RecordedPushLayer::PlayEvent(Translator* aTranslator) const {
   3060  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3061  if (!dt) {
   3062    return false;
   3063  }
   3064 
   3065  SourceSurface* mask =
   3066      mMask ? aTranslator->LookupSourceSurface(mMask) : nullptr;
   3067  dt->PushLayer(mOpaque, mOpacity, mask, mMaskTransform, mBounds,
   3068                mCopyBackground);
   3069  return true;
   3070 }
   3071 
   3072 template <class S>
   3073 void RecordedPushLayer::Record(S& aStream) const {
   3074  WriteElement(aStream, mOpaque);
   3075  WriteElement(aStream, mOpacity);
   3076  WriteElement(aStream, mMask);
   3077  WriteElement(aStream, mMaskTransform);
   3078  WriteElement(aStream, mBounds);
   3079  WriteElement(aStream, mCopyBackground);
   3080 }
   3081 
   3082 template <class S>
   3083 RecordedPushLayer::RecordedPushLayer(S& aStream)
   3084    : RecordedEventDerived(PUSHLAYER) {
   3085  ReadElement(aStream, mOpaque);
   3086  ReadElement(aStream, mOpacity);
   3087  ReadElement(aStream, mMask);
   3088  ReadElement(aStream, mMaskTransform);
   3089  ReadElement(aStream, mBounds);
   3090  ReadElement(aStream, mCopyBackground);
   3091 }
   3092 
   3093 inline void RecordedPushLayer::OutputSimpleEventInfo(
   3094    std::stringstream& aStringStream) const {
   3095  aStringStream << "PushPLayer (Opaque=" << mOpaque << ", Opacity=" << mOpacity
   3096                << ", Mask Ref=" << mMask << ") ";
   3097 }
   3098 
   3099 inline bool RecordedPushLayerWithBlend::PlayEvent(
   3100    Translator* aTranslator) const {
   3101  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3102  if (!dt) {
   3103    return false;
   3104  }
   3105 
   3106  SourceSurface* mask =
   3107      mMask ? aTranslator->LookupSourceSurface(mMask) : nullptr;
   3108  dt->PushLayerWithBlend(mOpaque, mOpacity, mask, mMaskTransform, mBounds,
   3109                         mCopyBackground, mCompositionOp);
   3110  return true;
   3111 }
   3112 
   3113 template <class S>
   3114 void RecordedPushLayerWithBlend::Record(S& aStream) const {
   3115  WriteElement(aStream, mOpaque);
   3116  WriteElement(aStream, mOpacity);
   3117  WriteElement(aStream, mMask);
   3118  WriteElement(aStream, mMaskTransform);
   3119  WriteElement(aStream, mBounds);
   3120  WriteElement(aStream, mCopyBackground);
   3121  WriteElement(aStream, mCompositionOp);
   3122 }
   3123 
   3124 template <class S>
   3125 RecordedPushLayerWithBlend::RecordedPushLayerWithBlend(S& aStream)
   3126    : RecordedEventDerived(PUSHLAYERWITHBLEND) {
   3127  ReadElement(aStream, mOpaque);
   3128  ReadElement(aStream, mOpacity);
   3129  ReadElement(aStream, mMask);
   3130  ReadElement(aStream, mMaskTransform);
   3131  ReadElement(aStream, mBounds);
   3132  ReadElement(aStream, mCopyBackground);
   3133  ReadElementConstrained(aStream, mCompositionOp, CompositionOp::OP_OVER,
   3134                         CompositionOp::OP_COUNT);
   3135 }
   3136 
   3137 inline void RecordedPushLayerWithBlend::OutputSimpleEventInfo(
   3138    std::stringstream& aStringStream) const {
   3139  aStringStream << "PushLayerWithBlend (Opaque=" << mOpaque
   3140                << ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
   3141 }
   3142 
   3143 inline bool RecordedPopLayer::PlayEvent(Translator* aTranslator) const {
   3144  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3145  if (!dt) {
   3146    return false;
   3147  }
   3148 
   3149  dt->PopLayer();
   3150  return true;
   3151 }
   3152 
   3153 template <class S>
   3154 void RecordedPopLayer::Record(S& aStream) const {}
   3155 
   3156 template <class S>
   3157 RecordedPopLayer::RecordedPopLayer(S& aStream)
   3158    : RecordedEventDerived(POPLAYER) {}
   3159 
   3160 inline void RecordedPopLayer::OutputSimpleEventInfo(
   3161    std::stringstream& aStringStream) const {
   3162  aStringStream << "PopLayer";
   3163 }
   3164 
   3165 inline bool RecordedSetPermitSubpixelAA::PlayEvent(
   3166    Translator* aTranslator) const {
   3167  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3168  if (!dt) {
   3169    return false;
   3170  }
   3171 
   3172  dt->SetPermitSubpixelAA(mPermitSubpixelAA);
   3173  return true;
   3174 }
   3175 
   3176 template <class S>
   3177 void RecordedSetPermitSubpixelAA::Record(S& aStream) const {
   3178  WriteElement(aStream, mPermitSubpixelAA);
   3179 }
   3180 
   3181 template <class S>
   3182 RecordedSetPermitSubpixelAA::RecordedSetPermitSubpixelAA(S& aStream)
   3183    : RecordedEventDerived(SETPERMITSUBPIXELAA) {
   3184  ReadElement(aStream, mPermitSubpixelAA);
   3185 }
   3186 
   3187 inline void RecordedSetPermitSubpixelAA::OutputSimpleEventInfo(
   3188    std::stringstream& aStringStream) const {
   3189  aStringStream << "SetPermitSubpixelAA (" << mPermitSubpixelAA << ")";
   3190 }
   3191 
   3192 inline bool RecordedSetTransform::PlayEvent(Translator* aTranslator) const {
   3193  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3194  if (!dt) {
   3195    return false;
   3196  }
   3197 
   3198  // If we're drawing to the reference DT, then we need to manually apply
   3199  // its initial transform, otherwise we'll just clobber it with only the
   3200  // the transform that was visible to the code doing the recording.
   3201  if (dt == aTranslator->GetReferenceDrawTarget()) {
   3202    dt->SetTransform(mTransform *
   3203                     aTranslator->GetReferenceDrawTargetTransform());
   3204  } else {
   3205    dt->SetTransform(mTransform);
   3206  }
   3207 
   3208  return true;
   3209 }
   3210 
   3211 template <class S>
   3212 void RecordedSetTransform::Record(S& aStream) const {
   3213  WriteElement(aStream, mTransform);
   3214 }
   3215 
   3216 template <class S>
   3217 RecordedSetTransform::RecordedSetTransform(S& aStream)
   3218    : RecordedEventDerived(SETTRANSFORM) {
   3219  ReadElement(aStream, mTransform);
   3220 }
   3221 
   3222 inline void RecordedSetTransform::OutputSimpleEventInfo(
   3223    std::stringstream& aStringStream) const {
   3224  aStringStream << "SetTransform [ " << mTransform._11 << " " << mTransform._12
   3225                << " ; " << mTransform._21 << " " << mTransform._22 << " ; "
   3226                << mTransform._31 << " " << mTransform._32 << " ]";
   3227 }
   3228 
   3229 inline bool RecordedDrawSurface::PlayEvent(Translator* aTranslator) const {
   3230  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3231  if (!dt) {
   3232    return false;
   3233  }
   3234 
   3235  SourceSurface* surface = aTranslator->LookupSourceSurface(mRefSource);
   3236  if (!surface) {
   3237    return false;
   3238  }
   3239 
   3240  dt->DrawSurface(surface, mDest, mSource, mDSOptions, mOptions);
   3241  return true;
   3242 }
   3243 
   3244 template <class S>
   3245 void RecordedDrawSurface::Record(S& aStream) const {
   3246  WriteElement(aStream, mRefSource);
   3247  WriteElement(aStream, mDest);
   3248  WriteElement(aStream, mSource);
   3249  WriteElement(aStream, mDSOptions);
   3250  WriteElement(aStream, mOptions);
   3251 }
   3252 
   3253 template <class S>
   3254 RecordedDrawSurface::RecordedDrawSurface(S& aStream)
   3255    : RecordedEventDerived(DRAWSURFACE) {
   3256  ReadElement(aStream, mRefSource);
   3257  ReadElement(aStream, mDest);
   3258  ReadElement(aStream, mSource);
   3259  ReadDrawSurfaceOptions(aStream, mDSOptions);
   3260  ReadDrawOptions(aStream, mOptions);
   3261 }
   3262 
   3263 inline void RecordedDrawSurface::OutputSimpleEventInfo(
   3264    std::stringstream& aStringStream) const {
   3265  aStringStream << "DrawSurface (" << mRefSource << ")";
   3266 }
   3267 
   3268 inline bool RecordedDrawSurfaceDescriptor::PlayEvent(
   3269    Translator* aTranslator) const {
   3270  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3271  if (!dt) {
   3272    return false;
   3273  }
   3274 
   3275  RefPtr<SourceSurface> surface =
   3276      aTranslator->LookupSourceSurfaceFromSurfaceDescriptor(mDesc);
   3277  if (!surface) {
   3278    return false;
   3279  }
   3280 
   3281  RefPtr<SourceSurface> opt = dt->OptimizeSourceSurface(surface);
   3282  if (opt) {
   3283    surface = opt;
   3284  }
   3285 
   3286  dt->DrawSurface(surface, mDest, mSource, mDSOptions, mOptions);
   3287  return true;
   3288 }
   3289 
   3290 template <class S>
   3291 struct ElementStreamFormat<S, layers::SurfaceDescriptor> {
   3292  using T = layers::SurfaceDescriptor;
   3293 
   3294  static void Write(S& s, const T& t) {
   3295    Maybe<T> valid;
   3296    if (!dom::ValidSurfaceDescriptorForRemoteCanvas2d(t, &valid)) {
   3297      MOZ_CRASH("Invalid surface descriptor for write");
   3298    }
   3299    MOZ_RELEASE_ASSERT(valid && *valid == t);
   3300 
   3301    nsTArray<char> buffer;
   3302    mozilla::ipc::SerializeToBytesUtil(*valid, buffer);
   3303 
   3304    uint32_t size = buffer.Length();
   3305    s.write(reinterpret_cast<const char*>(&size), sizeof(size));
   3306    if (size > 0) {
   3307      s.write(buffer.Elements(), size);
   3308    }
   3309  }
   3310 
   3311  static void Read(S& s, T& t) {
   3312    uint32_t size = 0;
   3313    s.read(reinterpret_cast<char*>(&size), sizeof(size));
   3314 
   3315    if (!s.good() || size == 0 || size > 1024 * 16) {
   3316      s.SetIsBad();
   3317      return;
   3318    }
   3319 
   3320    // TODO: We should revise/extend the API to avoid copying here.
   3321    nsTArray<char> buffer;
   3322    buffer.SetLength(size);
   3323    s.read(buffer.Elements(), size);
   3324 
   3325    if (!s.good()) {
   3326      return;
   3327    }
   3328 
   3329    auto result = mozilla::ipc::DeserializeFromBytesUtil<T>(buffer);
   3330    if (!result) {
   3331      s.SetIsBad();
   3332      return;
   3333    }
   3334 
   3335    t = std::move(*result);
   3336 
   3337    if (!dom::ValidSurfaceDescriptorForRemoteCanvas2d(t)) {
   3338      s.SetIsBad();
   3339      return;
   3340    }
   3341  }
   3342 };
   3343 
   3344 template <class S>
   3345 void RecordedDrawSurfaceDescriptor::Record(S& aStream) const {
   3346  WriteElement(aStream, mDesc);
   3347  WriteElement(aStream, mDest);
   3348  WriteElement(aStream, mSource);
   3349  WriteElement(aStream, mDSOptions);
   3350  WriteElement(aStream, mOptions);
   3351 }
   3352 
   3353 template <class S>
   3354 RecordedDrawSurfaceDescriptor::RecordedDrawSurfaceDescriptor(S& aStream)
   3355    : RecordedEventDerived(DRAWSURFACEDESCRIPTOR) {
   3356  ReadElement(aStream, mDesc);
   3357  ReadElement(aStream, mDest);
   3358  ReadElement(aStream, mSource);
   3359  ReadDrawSurfaceOptions(aStream, mDSOptions);
   3360  ReadDrawOptions(aStream, mOptions);
   3361 }
   3362 
   3363 inline void RecordedDrawSurfaceDescriptor::OutputSimpleEventInfo(
   3364    std::stringstream& aStringStream) const {
   3365  aStringStream << "DrawSurfaceDescriptor (" << mDesc.type() << ")";
   3366 }
   3367 
   3368 inline bool RecordedDrawDependentSurface::PlayEvent(
   3369    Translator* aTranslator) const {
   3370  aTranslator->DrawDependentSurface(mId, mDest);
   3371  return true;
   3372 }
   3373 
   3374 template <class S>
   3375 void RecordedDrawDependentSurface::Record(S& aStream) const {
   3376  WriteElement(aStream, mId);
   3377  WriteElement(aStream, mDest);
   3378 }
   3379 
   3380 template <class S>
   3381 RecordedDrawDependentSurface::RecordedDrawDependentSurface(S& aStream)
   3382    : RecordedEventDerived(DRAWDEPENDENTSURFACE) {
   3383  ReadElement(aStream, mId);
   3384  ReadElement(aStream, mDest);
   3385 }
   3386 
   3387 inline void RecordedDrawDependentSurface::OutputSimpleEventInfo(
   3388    std::stringstream& aStringStream) const {
   3389  aStringStream << "DrawDependentSurface (" << mId << ")";
   3390 }
   3391 
   3392 inline bool RecordedDrawFilter::PlayEvent(Translator* aTranslator) const {
   3393  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3394  if (!dt) {
   3395    return false;
   3396  }
   3397 
   3398  FilterNode* filter = aTranslator->LookupFilterNode(mNode);
   3399  if (!filter) {
   3400    return false;
   3401  }
   3402 
   3403  dt->DrawFilter(filter, mSourceRect, mDestPoint, mOptions);
   3404  return true;
   3405 }
   3406 
   3407 template <class S>
   3408 void RecordedDrawFilter::Record(S& aStream) const {
   3409  WriteElement(aStream, mNode);
   3410  WriteElement(aStream, mSourceRect);
   3411  WriteElement(aStream, mDestPoint);
   3412  WriteElement(aStream, mOptions);
   3413 }
   3414 
   3415 template <class S>
   3416 RecordedDrawFilter::RecordedDrawFilter(S& aStream)
   3417    : RecordedEventDerived(DRAWFILTER) {
   3418  ReadElement(aStream, mNode);
   3419  ReadElement(aStream, mSourceRect);
   3420  ReadElement(aStream, mDestPoint);
   3421  ReadDrawOptions(aStream, mOptions);
   3422 }
   3423 
   3424 inline void RecordedDrawFilter::OutputSimpleEventInfo(
   3425    std::stringstream& aStringStream) const {
   3426  aStringStream << "DrawFilter (" << mNode << ")";
   3427 }
   3428 
   3429 inline bool RecordedDrawSurfaceWithShadow::PlayEvent(
   3430    Translator* aTranslator) const {
   3431  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3432  if (!dt) {
   3433    return false;
   3434  }
   3435 
   3436  SourceSurface* surface = aTranslator->LookupSourceSurface(mRefSource);
   3437  if (!surface) {
   3438    return false;
   3439  }
   3440 
   3441  dt->DrawSurfaceWithShadow(surface, mDest, mShadow, mOp);
   3442  return true;
   3443 }
   3444 
   3445 template <class S>
   3446 void RecordedDrawSurfaceWithShadow::Record(S& aStream) const {
   3447  WriteElement(aStream, mRefSource);
   3448  WriteElement(aStream, mDest);
   3449  WriteElement(aStream, mShadow);
   3450  WriteElement(aStream, mOp);
   3451 }
   3452 
   3453 template <class S>
   3454 RecordedDrawSurfaceWithShadow::RecordedDrawSurfaceWithShadow(S& aStream)
   3455    : RecordedEventDerived(DRAWSURFACEWITHSHADOW) {
   3456  ReadElement(aStream, mRefSource);
   3457  ReadElement(aStream, mDest);
   3458  ReadElement(aStream, mShadow);
   3459  ReadElementConstrained(aStream, mOp, CompositionOp::OP_OVER,
   3460                         CompositionOp::OP_COUNT);
   3461 }
   3462 
   3463 inline void RecordedDrawSurfaceWithShadow::OutputSimpleEventInfo(
   3464    std::stringstream& aStringStream) const {
   3465  aStringStream << "DrawSurfaceWithShadow (" << mRefSource << ") DeviceColor: ("
   3466                << mShadow.mColor.r << ", " << mShadow.mColor.g << ", "
   3467                << mShadow.mColor.b << ", " << mShadow.mColor.a << ")";
   3468 }
   3469 
   3470 inline bool RecordedDrawShadow::PlayEvent(Translator* aTranslator) const {
   3471  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3472  if (!dt) {
   3473    return false;
   3474  }
   3475 
   3476  Path* path = aTranslator->LookupPath(mPath);
   3477  if (!path) {
   3478    return false;
   3479  }
   3480 
   3481  dt->DrawShadow(path, *GenericPattern(mPattern, aTranslator), mShadow,
   3482                 mOptions, mHasStrokeOptions ? &mStrokeOptions : nullptr);
   3483  return true;
   3484 }
   3485 
   3486 template <class S>
   3487 void RecordedDrawShadow::Record(S& aStream) const {
   3488  WriteElement(aStream, mPath);
   3489  RecordPatternData(aStream, mPattern);
   3490  WriteElement(aStream, mShadow);
   3491  WriteElement(aStream, mOptions);
   3492  WriteElement(aStream, mHasStrokeOptions);
   3493  if (mHasStrokeOptions) {
   3494    RecordStrokeOptions(aStream, mStrokeOptions);
   3495  }
   3496 }
   3497 
   3498 template <class S>
   3499 RecordedDrawShadow::RecordedDrawShadow(S& aStream)
   3500    : RecordedEventDerived(DRAWSHADOW) {
   3501  ReadElement(aStream, mPath);
   3502  ReadPatternData(aStream, mPattern);
   3503  ReadElement(aStream, mShadow);
   3504  ReadDrawOptions(aStream, mOptions);
   3505  ReadElement(aStream, mHasStrokeOptions);
   3506  if (mHasStrokeOptions) {
   3507    ReadStrokeOptions(aStream, mStrokeOptions);
   3508  }
   3509 }
   3510 
   3511 inline void RecordedDrawShadow::OutputSimpleEventInfo(
   3512    std::stringstream& aStringStream) const {
   3513  aStringStream << "DrawShadow (" << mPath << ") DeviceColor: ("
   3514                << mShadow.mColor.r << ", " << mShadow.mColor.g << ", "
   3515                << mShadow.mColor.b << ", " << mShadow.mColor.a << ")";
   3516 }
   3517 
   3518 inline RecordedPathCreation::RecordedPathCreation(PathRecording* aPath)
   3519    : RecordedEventDerived(PATHCREATION),
   3520      mRefPtr(aPath),
   3521      mFillRule(aPath->mFillRule),
   3522      mPath(aPath) {}
   3523 
   3524 inline bool RecordedPathCreation::PlayEvent(Translator* aTranslator) const {
   3525  DrawTarget* drawTarget = aTranslator->GetCurrentDrawTarget();
   3526  if (!drawTarget) {
   3527    return false;
   3528  }
   3529 
   3530  RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder(mFillRule);
   3531  if (!mPathOps->CheckedStreamToSink(*builder)) {
   3532    return false;
   3533  }
   3534 
   3535  RefPtr<Path> path = builder->Finish();
   3536  aTranslator->AddPath(mRefPtr, path);
   3537  return true;
   3538 }
   3539 
   3540 template <class S>
   3541 void RecordedPathCreation::Record(S& aStream) const {
   3542  WriteElement(aStream, mRefPtr);
   3543  WriteElement(aStream, mFillRule);
   3544  mPath->mPathOps.Record(aStream);
   3545 }
   3546 
   3547 template <class S>
   3548 RecordedPathCreation::RecordedPathCreation(S& aStream)
   3549    : RecordedEventDerived(PATHCREATION) {
   3550  ReadElement(aStream, mRefPtr);
   3551  ReadElementConstrained(aStream, mFillRule, FillRule::FILL_WINDING,
   3552                         FillRule::FILL_EVEN_ODD);
   3553  mPathOps = MakeUnique<PathOps>(aStream);
   3554 }
   3555 
   3556 inline void RecordedPathCreation::OutputSimpleEventInfo(
   3557    std::stringstream& aStringStream) const {
   3558  size_t numberOfOps =
   3559      mPath ? mPath->mPathOps.NumberOfOps() : mPathOps->NumberOfOps();
   3560  aStringStream << "[" << mRefPtr << "] Path created (OpCount: " << numberOfOps
   3561                << ")";
   3562 }
   3563 inline bool RecordedPathDestruction::PlayEvent(Translator* aTranslator) const {
   3564  aTranslator->RemovePath(mRefPtr);
   3565  return true;
   3566 }
   3567 
   3568 template <class S>
   3569 void RecordedPathDestruction::Record(S& aStream) const {
   3570  WriteElement(aStream, mRefPtr);
   3571 }
   3572 
   3573 template <class S>
   3574 RecordedPathDestruction::RecordedPathDestruction(S& aStream)
   3575    : RecordedEventDerived(PATHDESTRUCTION) {
   3576  ReadElement(aStream, mRefPtr);
   3577 }
   3578 
   3579 inline void RecordedPathDestruction::OutputSimpleEventInfo(
   3580    std::stringstream& aStringStream) const {
   3581  aStringStream << "[" << mRefPtr << "] Path Destroyed";
   3582 }
   3583 
   3584 inline bool RecordedSourceSurfaceCreation::PlayEvent(
   3585    Translator* aTranslator) const {
   3586  if (!mDataSurface) {
   3587    return false;
   3588  }
   3589 
   3590  aTranslator->AddSourceSurface(mRefPtr, mDataSurface);
   3591  return true;
   3592 }
   3593 
   3594 template <class S>
   3595 void RecordedSourceSurfaceCreation::Record(S& aStream) const {
   3596  MOZ_ASSERT(mDataSurface);
   3597  IntSize size = mDataSurface->GetSize();
   3598  SurfaceFormat format = mDataSurface->GetFormat();
   3599  WriteElement(aStream, mRefPtr);
   3600  DataSourceSurface::ScopedMap map(mDataSurface, DataSourceSurface::READ);
   3601  if (map.IsMapped()) {
   3602    WriteElement(aStream, size);
   3603    WriteElement(aStream, format);
   3604 
   3605    size_t dataFormatWidth = BytesPerPixel(format) * size.width;
   3606    size_t stride = map.GetStride();
   3607    const char* src = (const char*)map.GetData();
   3608    const char* endSrc = src + stride * size.height;
   3609    while (src < endSrc) {
   3610      aStream.write(src, dataFormatWidth);
   3611      src += stride;
   3612    }
   3613  } else {
   3614    gfxWarning()
   3615        << "RecordedSourceSurfaceCreation::Record failed to map surface";
   3616    WriteElement(aStream, IntSize(1, 1));
   3617    int bpp = BytesPerPixel(format);
   3618    WriteElement(aStream, bpp <= 4 ? format : SurfaceFormat::B8G8R8A8);
   3619    static const char zeroData[4] = {0, 0, 0, 0};
   3620    aStream.write(zeroData, BytesPerPixel(format));
   3621  }
   3622 }
   3623 
   3624 template <class S>
   3625 RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(S& aStream)
   3626    : RecordedEventDerived(SOURCESURFACECREATION) {
   3627  ReadElement(aStream, mRefPtr);
   3628  IntSize size;
   3629  ReadElement(aStream, size);
   3630  SurfaceFormat format = SurfaceFormat::UNKNOWN;
   3631  ReadElementConstrained(aStream, format, SurfaceFormat::B8G8R8A8,
   3632                         SurfaceFormat::UNKNOWN);
   3633 
   3634  if (!Factory::AllowedSurfaceSize(size)) {
   3635    gfxCriticalNote << "RecordedSourceSurfaceCreation read invalid size "
   3636                    << size;
   3637    aStream.SetIsBad();
   3638  }
   3639 
   3640  if (!aStream.good()) {
   3641    return;
   3642  }
   3643 
   3644  mDataSurface = Factory::CreateDataSourceSurface(size, format);
   3645  if (mDataSurface) {
   3646    DataSourceSurface::ScopedMap map(mDataSurface, DataSourceSurface::WRITE);
   3647    if (!map.IsMapped()) {
   3648      mDataSurface = nullptr;
   3649    } else {
   3650      char* data = (char*)map.GetData();
   3651      size_t stride = map.GetStride();
   3652      size_t dataFormatWidth = BytesPerPixel(format) * size.width;
   3653      if (stride == dataFormatWidth) {
   3654        aStream.read(data, stride * size.height);
   3655      } else {
   3656        for (int y = 0; y < size.height; y++) {
   3657          aStream.read(data, dataFormatWidth);
   3658          data += stride;
   3659        }
   3660      }
   3661    }
   3662  }
   3663  if (!mDataSurface) {
   3664    gfxCriticalNote
   3665        << "RecordedSourceSurfaceCreation failed to allocate data of size "
   3666        << size.width << " x " << size.height;
   3667    aStream.SetIsBad();
   3668  }
   3669 }
   3670 
   3671 inline void RecordedSourceSurfaceCreation::OutputSimpleEventInfo(
   3672    std::stringstream& aStringStream) const {
   3673  if (mDataSurface) {
   3674    IntSize size = mDataSurface->GetSize();
   3675    aStringStream << "[" << mRefPtr
   3676                  << "] SourceSurface created (Size: " << size.width << "x"
   3677                  << size.height << ")";
   3678  } else {
   3679    aStringStream << "[" << mRefPtr << "] SourceSurface created (no data)";
   3680  }
   3681 }
   3682 
   3683 inline bool RecordedSourceSurfaceDestruction::PlayEvent(
   3684    Translator* aTranslator) const {
   3685  aTranslator->RemoveSourceSurface(mRefPtr);
   3686  return true;
   3687 }
   3688 
   3689 template <class S>
   3690 void RecordedSourceSurfaceDestruction::Record(S& aStream) const {
   3691  WriteElement(aStream, mRefPtr);
   3692 }
   3693 
   3694 template <class S>
   3695 RecordedSourceSurfaceDestruction::RecordedSourceSurfaceDestruction(S& aStream)
   3696    : RecordedEventDerived(SOURCESURFACEDESTRUCTION) {
   3697  ReadElement(aStream, mRefPtr);
   3698 }
   3699 
   3700 inline void RecordedSourceSurfaceDestruction::OutputSimpleEventInfo(
   3701    std::stringstream& aStringStream) const {
   3702  aStringStream << "[" << mRefPtr << "] SourceSurface Destroyed";
   3703 }
   3704 
   3705 inline bool RecordedOptimizeSourceSurface::PlayEvent(
   3706    Translator* aTranslator) const {
   3707  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3708  if (!dt) {
   3709    return false;
   3710  }
   3711 
   3712  SourceSurface* surface = aTranslator->LookupSourceSurface(mSurface);
   3713  if (!surface) {
   3714    return false;
   3715  }
   3716 
   3717  RefPtr<SourceSurface> optimizedSurface = dt->OptimizeSourceSurface(surface);
   3718  aTranslator->AddSourceSurface(mOptimizedSurface, optimizedSurface);
   3719  return true;
   3720 }
   3721 
   3722 template <class S>
   3723 void RecordedOptimizeSourceSurface::Record(S& aStream) const {
   3724  WriteElement(aStream, mSurface);
   3725  WriteElement(aStream, mOptimizedSurface);
   3726 }
   3727 
   3728 template <class S>
   3729 RecordedOptimizeSourceSurface::RecordedOptimizeSourceSurface(S& aStream)
   3730    : RecordedEventDerived(OPTIMIZESOURCESURFACE) {
   3731  ReadElement(aStream, mSurface);
   3732  ReadElement(aStream, mOptimizedSurface);
   3733 }
   3734 
   3735 inline void RecordedOptimizeSourceSurface::OutputSimpleEventInfo(
   3736    std::stringstream& aStringStream) const {
   3737  aStringStream << "[" << mSurface << "] Surface Optimized";
   3738 }
   3739 
   3740 inline bool RecordedExternalSurfaceCreation::PlayEvent(
   3741    Translator* aTranslator) const {
   3742  RefPtr<SourceSurface> surface = aTranslator->LookupExternalSurface(mKey);
   3743  if (!surface) {
   3744    return false;
   3745  }
   3746 
   3747  aTranslator->AddSourceSurface(mRefPtr, surface);
   3748  return true;
   3749 }
   3750 
   3751 template <class S>
   3752 void RecordedExternalSurfaceCreation::Record(S& aStream) const {
   3753  WriteElement(aStream, mRefPtr);
   3754  WriteElement(aStream, mKey);
   3755 }
   3756 
   3757 template <class S>
   3758 RecordedExternalSurfaceCreation::RecordedExternalSurfaceCreation(S& aStream)
   3759    : RecordedEventDerived(EXTERNALSURFACECREATION) {
   3760  ReadElement(aStream, mRefPtr);
   3761  ReadElement(aStream, mKey);
   3762 }
   3763 
   3764 inline void RecordedExternalSurfaceCreation::OutputSimpleEventInfo(
   3765    std::stringstream& aStringStream) const {
   3766  aStringStream << "[" << mRefPtr
   3767                << "] SourceSurfaceSharedData created (Key: " << mKey << ")";
   3768 }
   3769 
   3770 inline RecordedFilterNodeCreation::~RecordedFilterNodeCreation() = default;
   3771 
   3772 inline bool RecordedFilterNodeCreation::PlayEvent(
   3773    Translator* aTranslator) const {
   3774  DrawTarget* drawTarget = aTranslator->GetCurrentDrawTarget();
   3775  if (!drawTarget) {
   3776    return false;
   3777  }
   3778 
   3779  RefPtr<FilterNode> node = drawTarget->CreateFilter(mType);
   3780  aTranslator->AddFilterNode(mRefPtr, node);
   3781  return true;
   3782 }
   3783 
   3784 template <class S>
   3785 void RecordedFilterNodeCreation::Record(S& aStream) const {
   3786  WriteElement(aStream, mRefPtr);
   3787  WriteElement(aStream, mType);
   3788 }
   3789 
   3790 template <class S>
   3791 RecordedFilterNodeCreation::RecordedFilterNodeCreation(S& aStream)
   3792    : RecordedEventDerived(FILTERNODECREATION) {
   3793  ReadElement(aStream, mRefPtr);
   3794  ReadElementConstrained(aStream, mType, FilterType::BLEND,
   3795                         FilterType::OPACITY);
   3796 }
   3797 
   3798 inline void RecordedFilterNodeCreation::OutputSimpleEventInfo(
   3799    std::stringstream& aStringStream) const {
   3800  aStringStream << "CreateFilter [" << mRefPtr
   3801                << "] FilterNode created (Type: " << int(mType) << ")";
   3802 }
   3803 
   3804 inline bool RecordedDeferFilterInput::PlayEvent(Translator* aTranslator) const {
   3805  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3806  if (!dt) {
   3807    return false;
   3808  }
   3809 
   3810  Path* path = aTranslator->LookupPath(mPath);
   3811  if (!path) {
   3812    return false;
   3813  }
   3814 
   3815  RefPtr<FilterNode> node = dt->DeferFilterInput(
   3816      path, *GenericPattern(mPattern, aTranslator), mSourceRect, mDestOffset,
   3817      mOptions, mHasStrokeOptions ? &mStrokeOptions : nullptr);
   3818  aTranslator->AddFilterNode(mRefPtr, node);
   3819  return true;
   3820 }
   3821 
   3822 template <class S>
   3823 void RecordedDeferFilterInput::Record(S& aStream) const {
   3824  WriteElement(aStream, mRefPtr);
   3825  WriteElement(aStream, mPath);
   3826  RecordPatternData(aStream, mPattern);
   3827  WriteElement(aStream, mSourceRect);
   3828  WriteElement(aStream, mDestOffset);
   3829  WriteElement(aStream, mOptions);
   3830  WriteElement(aStream, mHasStrokeOptions);
   3831  if (mHasStrokeOptions) {
   3832    RecordStrokeOptions(aStream, mStrokeOptions);
   3833  }
   3834 }
   3835 
   3836 template <class S>
   3837 RecordedDeferFilterInput::RecordedDeferFilterInput(S& aStream)
   3838    : RecordedEventDerived(DEFERFILTERINPUT) {
   3839  ReadElement(aStream, mRefPtr);
   3840  ReadElement(aStream, mPath);
   3841  ReadPatternData(aStream, mPattern);
   3842  ReadElement(aStream, mSourceRect);
   3843  ReadElement(aStream, mDestOffset);
   3844  ReadDrawOptions(aStream, mOptions);
   3845  ReadElement(aStream, mHasStrokeOptions);
   3846  if (mHasStrokeOptions) {
   3847    ReadStrokeOptions(aStream, mStrokeOptions);
   3848  }
   3849 }
   3850 
   3851 inline void RecordedDeferFilterInput::OutputSimpleEventInfo(
   3852    std::stringstream& aStringStream) const {
   3853  aStringStream << "DeferFilterInput[" << mRefPtr << "] (" << mPath << ") ";
   3854  OutputSimplePatternInfo(mPattern, aStringStream);
   3855 }
   3856 
   3857 inline bool RecordedFilterNodeDestruction::PlayEvent(
   3858    Translator* aTranslator) const {
   3859  aTranslator->RemoveFilterNode(mRefPtr);
   3860  return true;
   3861 }
   3862 
   3863 template <class S>
   3864 void RecordedFilterNodeDestruction::Record(S& aStream) const {
   3865  WriteElement(aStream, mRefPtr);
   3866 }
   3867 
   3868 template <class S>
   3869 RecordedFilterNodeDestruction::RecordedFilterNodeDestruction(S& aStream)
   3870    : RecordedEventDerived(FILTERNODEDESTRUCTION) {
   3871  ReadElement(aStream, mRefPtr);
   3872 }
   3873 
   3874 inline void RecordedFilterNodeDestruction::OutputSimpleEventInfo(
   3875    std::stringstream& aStringStream) const {
   3876  aStringStream << "[" << mRefPtr << "] FilterNode Destroyed";
   3877 }
   3878 
   3879 inline RecordedGradientStopsCreation::~RecordedGradientStopsCreation() {
   3880  if (mDataOwned) {
   3881    delete[] mStops;
   3882  }
   3883 }
   3884 
   3885 inline bool RecordedGradientStopsCreation::PlayEvent(
   3886    Translator* aTranslator) const {
   3887  if (mNumStops > 0 && !mStops) {
   3888    // Stops allocation failed
   3889    return false;
   3890  }
   3891 
   3892  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3893  if (!dt) {
   3894    return false;
   3895  }
   3896 
   3897  RefPtr<GradientStops> src =
   3898      aTranslator->GetOrCreateGradientStops(dt, mStops, mNumStops, mExtendMode);
   3899  aTranslator->AddGradientStops(mRefPtr, src);
   3900  return true;
   3901 }
   3902 
   3903 template <class S>
   3904 void RecordedGradientStopsCreation::Record(S& aStream) const {
   3905  WriteElement(aStream, mRefPtr);
   3906  WriteElement(aStream, mExtendMode);
   3907  WriteElement(aStream, mNumStops);
   3908  aStream.write((const char*)mStops, mNumStops * sizeof(GradientStop));
   3909 }
   3910 
   3911 template <class S>
   3912 RecordedGradientStopsCreation::RecordedGradientStopsCreation(S& aStream)
   3913    : RecordedEventDerived(GRADIENTSTOPSCREATION), mDataOwned(true) {
   3914  ReadElement(aStream, mRefPtr);
   3915  ReadElementConstrained(aStream, mExtendMode, ExtendMode::CLAMP,
   3916                         ExtendMode::REFLECT);
   3917  ReadElement(aStream, mNumStops);
   3918  if (!aStream.good() || mNumStops <= 0) {
   3919    return;
   3920  }
   3921 
   3922  mStops = new (fallible) GradientStop[mNumStops];
   3923  if (!mStops) {
   3924    gfxCriticalNote
   3925        << "RecordedGradientStopsCreation failed to allocate stops of size "
   3926        << mNumStops;
   3927    aStream.SetIsBad();
   3928  } else {
   3929    aStream.read((char*)mStops, mNumStops * sizeof(GradientStop));
   3930  }
   3931 }
   3932 
   3933 inline void RecordedGradientStopsCreation::OutputSimpleEventInfo(
   3934    std::stringstream& aStringStream) const {
   3935  aStringStream << "[" << mRefPtr
   3936                << "] GradientStops created (Stops: " << mNumStops << ")";
   3937 }
   3938 
   3939 inline bool RecordedGradientStopsDestruction::PlayEvent(
   3940    Translator* aTranslator) const {
   3941  aTranslator->RemoveGradientStops(mRefPtr);
   3942  return true;
   3943 }
   3944 
   3945 template <class S>
   3946 void RecordedGradientStopsDestruction::Record(S& aStream) const {
   3947  WriteElement(aStream, mRefPtr);
   3948 }
   3949 
   3950 template <class S>
   3951 RecordedGradientStopsDestruction::RecordedGradientStopsDestruction(S& aStream)
   3952    : RecordedEventDerived(GRADIENTSTOPSDESTRUCTION) {
   3953  ReadElement(aStream, mRefPtr);
   3954 }
   3955 
   3956 inline void RecordedGradientStopsDestruction::OutputSimpleEventInfo(
   3957    std::stringstream& aStringStream) const {
   3958  aStringStream << "[" << mRefPtr << "] GradientStops Destroyed";
   3959 }
   3960 
   3961 inline bool RecordedIntoLuminanceSource::PlayEvent(
   3962    Translator* aTranslator) const {
   3963  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   3964  if (!dt) {
   3965    return false;
   3966  }
   3967 
   3968  RefPtr<SourceSurface> src = dt->IntoLuminanceSource(mLuminanceType, mOpacity);
   3969  aTranslator->AddSourceSurface(mRefPtr, src);
   3970  return true;
   3971 }
   3972 
   3973 template <class S>
   3974 void RecordedIntoLuminanceSource::Record(S& aStream) const {
   3975  WriteElement(aStream, mRefPtr);
   3976  WriteElement(aStream, mLuminanceType);
   3977  WriteElement(aStream, mOpacity);
   3978 }
   3979 
   3980 template <class S>
   3981 RecordedIntoLuminanceSource::RecordedIntoLuminanceSource(S& aStream)
   3982    : RecordedEventDerived(INTOLUMINANCE) {
   3983  ReadElement(aStream, mRefPtr);
   3984  ReadElementConstrained(aStream, mLuminanceType, LuminanceType::LUMINANCE,
   3985                         LuminanceType::LINEARRGB);
   3986  ReadElement(aStream, mOpacity);
   3987 }
   3988 
   3989 inline void RecordedIntoLuminanceSource::OutputSimpleEventInfo(
   3990    std::stringstream& aStringStream) const {
   3991  aStringStream << "[" << mRefPtr << "] Into Luminance Source";
   3992 }
   3993 
   3994 inline bool RecordedExtractSubrect::PlayEvent(Translator* aTranslator) const {
   3995  SourceSurface* sourceSurf = aTranslator->LookupSourceSurface(mSourceSurface);
   3996  if (!sourceSurf) {
   3997    return false;
   3998  }
   3999 
   4000  RefPtr<SourceSurface> subSurf = sourceSurf->ExtractSubrect(mSubrect);
   4001  if (!subSurf) {
   4002    RefPtr<DrawTarget> dt =
   4003        aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(
   4004            mSubrect.Size(), sourceSurf->GetFormat());
   4005    if (dt) {
   4006      dt->CopySurface(sourceSurf, mSubrect, IntPoint());
   4007      subSurf = dt->Snapshot();
   4008    }
   4009  }
   4010  if (!subSurf) {
   4011    return false;
   4012  }
   4013 
   4014  aTranslator->AddSourceSurface(mRefPtr, subSurf);
   4015  return true;
   4016 }
   4017 
   4018 template <class S>
   4019 void RecordedExtractSubrect::Record(S& aStream) const {
   4020  WriteElement(aStream, mRefPtr);
   4021  WriteElement(aStream, mSourceSurface);
   4022  WriteElement(aStream, mSubrect);
   4023 }
   4024 
   4025 template <class S>
   4026 RecordedExtractSubrect::RecordedExtractSubrect(S& aStream)
   4027    : RecordedEventDerived(EXTRACTSUBRECT) {
   4028  ReadElement(aStream, mRefPtr);
   4029  ReadElement(aStream, mSourceSurface);
   4030  ReadElement(aStream, mSubrect);
   4031 }
   4032 
   4033 inline void RecordedExtractSubrect::OutputSimpleEventInfo(
   4034    std::stringstream& aStringStream) const {
   4035  aStringStream << "[" << mRefPtr << "] Exract Subrect";
   4036 }
   4037 
   4038 inline bool RecordedFlush::PlayEvent(Translator* aTranslator) const {
   4039  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   4040  if (!dt) {
   4041    return false;
   4042  }
   4043 
   4044  dt->Flush();
   4045  return true;
   4046 }
   4047 
   4048 template <class S>
   4049 void RecordedFlush::Record(S& aStream) const {}
   4050 
   4051 template <class S>
   4052 RecordedFlush::RecordedFlush(S& aStream) : RecordedEventDerived(FLUSH) {}
   4053 
   4054 inline void RecordedFlush::OutputSimpleEventInfo(
   4055    std::stringstream& aStringStream) const {
   4056  aStringStream << "Flush";
   4057 }
   4058 
   4059 inline bool RecordedDetachAllSnapshots::PlayEvent(
   4060    Translator* aTranslator) const {
   4061  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   4062  if (!dt) {
   4063    return false;
   4064  }
   4065 
   4066  dt->DetachAllSnapshots();
   4067  return true;
   4068 }
   4069 
   4070 template <class S>
   4071 void RecordedDetachAllSnapshots::Record(S& aStream) const {}
   4072 
   4073 template <class S>
   4074 RecordedDetachAllSnapshots::RecordedDetachAllSnapshots(S& aStream)
   4075    : RecordedEventDerived(DETACHALLSNAPSHOTS) {}
   4076 
   4077 inline void RecordedDetachAllSnapshots::OutputSimpleEventInfo(
   4078    std::stringstream& aStringStream) const {
   4079  aStringStream << "DetachAllSnapshots";
   4080 }
   4081 
   4082 inline bool RecordedSnapshot::PlayEvent(Translator* aTranslator) const {
   4083  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   4084  if (!dt) {
   4085    return false;
   4086  }
   4087 
   4088  RefPtr<SourceSurface> src = dt->Snapshot();
   4089  aTranslator->AddSourceSurface(mRefPtr, src);
   4090  return true;
   4091 }
   4092 
   4093 template <class S>
   4094 void RecordedSnapshot::Record(S& aStream) const {
   4095  WriteElement(aStream, mRefPtr);
   4096 }
   4097 
   4098 template <class S>
   4099 RecordedSnapshot::RecordedSnapshot(S& aStream)
   4100    : RecordedEventDerived(SNAPSHOT) {
   4101  ReadElement(aStream, mRefPtr);
   4102 }
   4103 
   4104 inline void RecordedSnapshot::OutputSimpleEventInfo(
   4105    std::stringstream& aStringStream) const {
   4106  aStringStream << "[" << mRefPtr << "] Snapshot Created";
   4107 }
   4108 
   4109 inline bool RecordedFontData::PlayEvent(Translator* aTranslator) const {
   4110  if (mData.empty()) {
   4111    return false;
   4112  }
   4113 
   4114  RefPtr<NativeFontResource> fontResource = Factory::CreateNativeFontResource(
   4115      mData.data(), mData.size(), mType, aTranslator->GetFontContext());
   4116  if (!fontResource) {
   4117    return false;
   4118  }
   4119 
   4120  aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource);
   4121  return true;
   4122 }
   4123 
   4124 template <class S>
   4125 void RecordedFontData::Record(S& aStream) const {
   4126  MOZ_ASSERT(mGetFontFileDataSucceeded);
   4127 
   4128  WriteElement(aStream, mType);
   4129  WriteElement(aStream, mFontDetails.fontDataKey);
   4130  WriteElement(aStream, mData.size());
   4131  mData.Write(aStream);
   4132 }
   4133 
   4134 inline void RecordedFontData::OutputSimpleEventInfo(
   4135    std::stringstream& aStringStream) const {
   4136  aStringStream << "Font Data of size " << mData.size();
   4137 }
   4138 
   4139 inline void RecordedFontData::SetFontData(const uint8_t* aData, uint32_t aSize,
   4140                                          uint32_t aIndex) {
   4141  if (!mData.TryAssign(aData, aSize)) {
   4142    mGetFontFileDataSucceeded = false;
   4143    gfxCriticalNote
   4144        << "RecordedFontData failed to allocate data for recording of size "
   4145        << aSize;
   4146  }
   4147  mFontDetails.fontDataKey = SFNTData::GetUniqueKey(aData, aSize, 0, nullptr);
   4148  mFontDetails.index = aIndex;
   4149 }
   4150 
   4151 inline bool RecordedFontData::GetFontDetails(RecordedFontDetails& fontDetails) {
   4152  if (!mGetFontFileDataSucceeded) {
   4153    return false;
   4154  }
   4155 
   4156  fontDetails.fontDataKey = mFontDetails.fontDataKey;
   4157  fontDetails.index = mFontDetails.index;
   4158  return true;
   4159 }
   4160 
   4161 template <class S>
   4162 RecordedFontData::RecordedFontData(S& aStream)
   4163    : RecordedEventDerived(FONTDATA), mType(FontType::UNKNOWN) {
   4164  ReadElementConstrained(aStream, mType, FontType::DWRITE, FontType::UNKNOWN);
   4165  ReadElement(aStream, mFontDetails.fontDataKey);
   4166  uint32_t dataSize = 0;
   4167  ReadElement(aStream, dataSize);
   4168  if (!dataSize || !aStream.good()) {
   4169    return;
   4170  }
   4171 
   4172  if (!mData.Read(aStream, dataSize)) {
   4173    gfxCriticalNote
   4174        << "RecordedFontData failed to allocate data for playback of size "
   4175        << dataSize;
   4176    aStream.SetIsBad();
   4177  }
   4178 }
   4179 
   4180 inline RecordedFontDescriptor::~RecordedFontDescriptor() = default;
   4181 
   4182 inline bool RecordedFontDescriptor::PlayEvent(Translator* aTranslator) const {
   4183  RefPtr<UnscaledFont> font = Factory::CreateUnscaledFontFromFontDescriptor(
   4184      mType, mData.data(), mData.size(), mIndex);
   4185  if (!font) {
   4186    gfxDevCrash(LogReason::InvalidFont)
   4187        << "Failed creating UnscaledFont of type " << int(mType)
   4188        << " from font descriptor";
   4189    return false;
   4190  }
   4191 
   4192  aTranslator->AddUnscaledFont(mRefPtr, font);
   4193  return true;
   4194 }
   4195 
   4196 template <class S>
   4197 void RecordedFontDescriptor::Record(S& aStream) const {
   4198  MOZ_ASSERT(mHasDesc);
   4199  WriteElement(aStream, mType);
   4200  WriteElement(aStream, mRefPtr);
   4201  WriteElement(aStream, mIndex);
   4202  WriteElement(aStream, mData.size());
   4203  mData.Write(aStream);
   4204 }
   4205 
   4206 inline void RecordedFontDescriptor::OutputSimpleEventInfo(
   4207    std::stringstream& aStringStream) const {
   4208  aStringStream << "[" << mRefPtr << "] Font Descriptor";
   4209 }
   4210 
   4211 inline void RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData,
   4212                                                      uint32_t aSize,
   4213                                                      uint32_t aIndex) {
   4214  mData.Assign(aData, aSize);
   4215  mIndex = aIndex;
   4216 }
   4217 
   4218 template <class S>
   4219 RecordedFontDescriptor::RecordedFontDescriptor(S& aStream)
   4220    : RecordedEventDerived(FONTDESC) {
   4221  ReadElementConstrained(aStream, mType, FontType::DWRITE, FontType::UNKNOWN);
   4222  ReadElement(aStream, mRefPtr);
   4223  ReadElement(aStream, mIndex);
   4224 
   4225  size_t size = 0;
   4226  ReadElement(aStream, size);
   4227  if (!aStream.good()) {
   4228    return;
   4229  }
   4230  if (size && !mData.Read(aStream, size)) {
   4231    aStream.SetIsBad();
   4232    return;
   4233  }
   4234 }
   4235 
   4236 inline bool RecordedUnscaledFontCreation::PlayEvent(
   4237    Translator* aTranslator) const {
   4238  NativeFontResource* fontResource =
   4239      aTranslator->LookupNativeFontResource(mFontDataKey);
   4240  if (!fontResource) {
   4241    gfxDevCrash(LogReason::NativeFontResourceNotFound)
   4242        << "NativeFontResource lookup failed for key |" << hexa(mFontDataKey)
   4243        << "|.";
   4244    return false;
   4245  }
   4246 
   4247  RefPtr<UnscaledFont> unscaledFont = fontResource->CreateUnscaledFont(
   4248      mIndex, mInstanceData.data(), mInstanceData.size());
   4249  aTranslator->AddUnscaledFont(mRefPtr, unscaledFont);
   4250  return true;
   4251 }
   4252 
   4253 template <class S>
   4254 void RecordedUnscaledFontCreation::Record(S& aStream) const {
   4255  WriteElement(aStream, mRefPtr);
   4256  WriteElement(aStream, mFontDataKey);
   4257  WriteElement(aStream, mIndex);
   4258  WriteElement(aStream, mInstanceData.size());
   4259  mInstanceData.Write(aStream);
   4260 }
   4261 
   4262 inline void RecordedUnscaledFontCreation::OutputSimpleEventInfo(
   4263    std::stringstream& aStringStream) const {
   4264  aStringStream << "[" << mRefPtr << "] UnscaledFont Created";
   4265 }
   4266 
   4267 inline void RecordedUnscaledFontCreation::SetFontInstanceData(
   4268    const uint8_t* aData, uint32_t aSize) {
   4269  if (aSize) {
   4270    mInstanceData.Assign(aData, aSize);
   4271  }
   4272 }
   4273 
   4274 template <class S>
   4275 RecordedUnscaledFontCreation::RecordedUnscaledFontCreation(S& aStream)
   4276    : RecordedEventDerived(UNSCALEDFONTCREATION) {
   4277  ReadElement(aStream, mRefPtr);
   4278  ReadElement(aStream, mFontDataKey);
   4279  ReadElement(aStream, mIndex);
   4280 
   4281  size_t size = 0;
   4282  ReadElement(aStream, size);
   4283  if (!aStream.good()) {
   4284    return;
   4285  }
   4286  if (size && !mInstanceData.Read(aStream, size)) {
   4287    aStream.SetIsBad();
   4288    return;
   4289  }
   4290 }
   4291 
   4292 inline bool RecordedUnscaledFontDestruction::PlayEvent(
   4293    Translator* aTranslator) const {
   4294  aTranslator->RemoveUnscaledFont(mRefPtr);
   4295  return true;
   4296 }
   4297 
   4298 template <class S>
   4299 void RecordedUnscaledFontDestruction::Record(S& aStream) const {
   4300  WriteElement(aStream, mRefPtr);
   4301 }
   4302 
   4303 template <class S>
   4304 RecordedUnscaledFontDestruction::RecordedUnscaledFontDestruction(S& aStream)
   4305    : RecordedEventDerived(UNSCALEDFONTDESTRUCTION) {
   4306  ReadElement(aStream, mRefPtr);
   4307 }
   4308 
   4309 inline void RecordedUnscaledFontDestruction::OutputSimpleEventInfo(
   4310    std::stringstream& aStringStream) const {
   4311  aStringStream << "[" << mRefPtr << "] UnscaledFont Destroyed";
   4312 }
   4313 
   4314 inline bool RecordedScaledFontCreation::PlayEvent(
   4315    Translator* aTranslator) const {
   4316  UnscaledFont* unscaledFont = aTranslator->LookupUnscaledFont(mUnscaledFont);
   4317  if (!unscaledFont) {
   4318    gfxDevCrash(LogReason::UnscaledFontNotFound)
   4319        << "UnscaledFont lookup failed for key |" << hexa(mUnscaledFont)
   4320        << "|.";
   4321    return false;
   4322  }
   4323 
   4324  RefPtr<ScaledFont> scaledFont = unscaledFont->CreateScaledFont(
   4325      mGlyphSize, mInstanceData.data(), mInstanceData.size(),
   4326      mVariations.data(), mVariations.size());
   4327 
   4328  aTranslator->AddScaledFont(mRefPtr, scaledFont);
   4329  return true;
   4330 }
   4331 
   4332 template <class S>
   4333 void RecordedScaledFontCreation::Record(S& aStream) const {
   4334  WriteElement(aStream, mRefPtr);
   4335  WriteElement(aStream, mUnscaledFont);
   4336  WriteElement(aStream, mGlyphSize);
   4337  WriteElement(aStream, mInstanceData.size());
   4338  mInstanceData.Write(aStream);
   4339  WriteElement(aStream, mVariations.size());
   4340  mVariations.Write(aStream);
   4341 }
   4342 
   4343 inline void RecordedScaledFontCreation::OutputSimpleEventInfo(
   4344    std::stringstream& aStringStream) const {
   4345  aStringStream << "[" << mRefPtr << "] ScaledFont Created";
   4346 }
   4347 
   4348 inline void RecordedScaledFontCreation::SetFontInstanceData(
   4349    const uint8_t* aData, uint32_t aSize, const FontVariation* aVariations,
   4350    uint32_t aNumVariations) {
   4351  if (aSize) {
   4352    mInstanceData.Assign(aData, aSize);
   4353  }
   4354  if (aNumVariations) {
   4355    mVariations.Assign(aVariations, aNumVariations);
   4356  }
   4357 }
   4358 
   4359 template <class S>
   4360 RecordedScaledFontCreation::RecordedScaledFontCreation(S& aStream)
   4361    : RecordedEventDerived(SCALEDFONTCREATION) {
   4362  ReadElement(aStream, mRefPtr);
   4363  ReadElement(aStream, mUnscaledFont);
   4364  ReadElement(aStream, mGlyphSize);
   4365 
   4366  size_t size = 0;
   4367  ReadElement(aStream, size);
   4368  if (!aStream.good()) {
   4369    return;
   4370  }
   4371  if (size && !mInstanceData.Read(aStream, size)) {
   4372    aStream.SetIsBad();
   4373    return;
   4374  }
   4375 
   4376  size_t numVariations = 0;
   4377  ReadElement(aStream, numVariations);
   4378  if (!aStream.good()) {
   4379    return;
   4380  }
   4381  if (numVariations && !mVariations.Read(aStream, numVariations)) {
   4382    aStream.SetIsBad();
   4383    return;
   4384  }
   4385 }
   4386 
   4387 inline bool RecordedScaledFontDestruction::PlayEvent(
   4388    Translator* aTranslator) const {
   4389  aTranslator->RemoveScaledFont(mRefPtr);
   4390  return true;
   4391 }
   4392 
   4393 template <class S>
   4394 void RecordedScaledFontDestruction::Record(S& aStream) const {
   4395  WriteElement(aStream, mRefPtr);
   4396 }
   4397 
   4398 template <class S>
   4399 RecordedScaledFontDestruction::RecordedScaledFontDestruction(S& aStream)
   4400    : RecordedEventDerived(SCALEDFONTDESTRUCTION) {
   4401  ReadElement(aStream, mRefPtr);
   4402 }
   4403 
   4404 inline void RecordedScaledFontDestruction::OutputSimpleEventInfo(
   4405    std::stringstream& aStringStream) const {
   4406  aStringStream << "[" << mRefPtr << "] ScaledFont Destroyed";
   4407 }
   4408 
   4409 inline bool RecordedMaskSurface::PlayEvent(Translator* aTranslator) const {
   4410  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   4411  if (!dt) {
   4412    return false;
   4413  }
   4414 
   4415  SourceSurface* surface = aTranslator->LookupSourceSurface(mRefMask);
   4416  if (!surface) {
   4417    return false;
   4418  }
   4419 
   4420  dt->MaskSurface(*GenericPattern(mPattern, aTranslator), surface, mOffset,
   4421                  mOptions);
   4422  return true;
   4423 }
   4424 
   4425 template <class S>
   4426 void RecordedMaskSurface::Record(S& aStream) const {
   4427  RecordPatternData(aStream, mPattern);
   4428  WriteElement(aStream, mRefMask);
   4429  WriteElement(aStream, mOffset);
   4430  WriteElement(aStream, mOptions);
   4431 }
   4432 
   4433 template <class S>
   4434 RecordedMaskSurface::RecordedMaskSurface(S& aStream)
   4435    : RecordedEventDerived(MASKSURFACE) {
   4436  ReadPatternData(aStream, mPattern);
   4437  ReadElement(aStream, mRefMask);
   4438  ReadElement(aStream, mOffset);
   4439  ReadDrawOptions(aStream, mOptions);
   4440 }
   4441 
   4442 inline void RecordedMaskSurface::OutputSimpleEventInfo(
   4443    std::stringstream& aStringStream) const {
   4444  aStringStream << "MaskSurface (" << mRefMask << ")  Offset: (" << mOffset.x
   4445                << "x" << mOffset.y << ") Pattern: ";
   4446  OutputSimplePatternInfo(mPattern, aStringStream);
   4447 }
   4448 
   4449 inline bool RecordedFilterNodeSetAttribute::PlayEvent(
   4450    Translator* aTranslator) const {
   4451  FilterNode* node = aTranslator->LookupFilterNode(mNode);
   4452  if (!node) {
   4453    return false;
   4454  }
   4455 
   4456 #define REPLAY_SET_ATTRIBUTE_CAST(type, cast, argtype)         \
   4457  case ARGTYPE_##argtype:                                      \
   4458    if (mPayload.size() < sizeof(type)) {                      \
   4459      return false;                                            \
   4460    }                                                          \
   4461    node->SetAttribute(mIndex, cast(*(type*)mPayload.data())); \
   4462    break
   4463 #define REPLAY_SET_ATTRIBUTE(type, argtype) \
   4464  REPLAY_SET_ATTRIBUTE_CAST(type, , argtype)
   4465 
   4466  switch (mArgType) {
   4467    REPLAY_SET_ATTRIBUTE_CAST(uint8_t, bool, BOOL);
   4468    REPLAY_SET_ATTRIBUTE(uint32_t, UINT32);
   4469    REPLAY_SET_ATTRIBUTE(Float, FLOAT);
   4470    REPLAY_SET_ATTRIBUTE(Size, SIZE);
   4471    REPLAY_SET_ATTRIBUTE(IntSize, INTSIZE);
   4472    REPLAY_SET_ATTRIBUTE(IntPoint, INTPOINT);
   4473    REPLAY_SET_ATTRIBUTE(Rect, RECT);
   4474    REPLAY_SET_ATTRIBUTE(IntRect, INTRECT);
   4475    REPLAY_SET_ATTRIBUTE(Point, POINT);
   4476    REPLAY_SET_ATTRIBUTE(Matrix, MATRIX);
   4477    REPLAY_SET_ATTRIBUTE(Matrix5x4, MATRIX5X4);
   4478    REPLAY_SET_ATTRIBUTE(Point3D, POINT3D);
   4479    REPLAY_SET_ATTRIBUTE(DeviceColor, COLOR);
   4480    case ARGTYPE_FLOAT_ARRAY:
   4481      node->SetAttribute(mIndex,
   4482                         reinterpret_cast<const Float*>(mPayload.data()),
   4483                         mPayload.size() / sizeof(Float));
   4484      break;
   4485  }
   4486 
   4487  return true;
   4488 }
   4489 
   4490 template <class S>
   4491 void RecordedFilterNodeSetAttribute::Record(S& aStream) const {
   4492  WriteElement(aStream, mNode);
   4493  WriteElement(aStream, mIndex);
   4494  WriteElement(aStream, mArgType);
   4495  WriteElement(aStream, mPayload.size());
   4496  mPayload.Write(aStream);
   4497 }
   4498 
   4499 template <class S>
   4500 RecordedFilterNodeSetAttribute::RecordedFilterNodeSetAttribute(S& aStream)
   4501    : RecordedEventDerived(FILTERNODESETATTRIBUTE) {
   4502  ReadElement(aStream, mNode);
   4503  ReadElement(aStream, mIndex);
   4504  ReadElementConstrained(aStream, mArgType, ArgType::ARGTYPE_UINT32,
   4505                         ArgType::ARGTYPE_FLOAT_ARRAY);
   4506  size_t size = 0;
   4507  ReadElement(aStream, size);
   4508  if (!aStream.good()) {
   4509    return;
   4510  }
   4511 
   4512  if (size && !mPayload.Read(aStream, size)) {
   4513    aStream.SetIsBad();
   4514    return;
   4515  }
   4516 }
   4517 
   4518 inline void RecordedFilterNodeSetAttribute::OutputSimpleEventInfo(
   4519    std::stringstream& aStringStream) const {
   4520  aStringStream << "[" << mNode << "] SetAttribute (" << mIndex << ")";
   4521 }
   4522 
   4523 inline bool RecordedFilterNodeSetInput::PlayEvent(
   4524    Translator* aTranslator) const {
   4525  FilterNode* node = aTranslator->LookupFilterNode(mNode);
   4526  if (!node) {
   4527    return false;
   4528  }
   4529 
   4530  if (mInputFilter) {
   4531    node->SetInput(mIndex, aTranslator->LookupFilterNode(mInputFilter));
   4532  } else {
   4533    node->SetInput(mIndex, aTranslator->LookupSourceSurface(mInputSurface));
   4534  }
   4535 
   4536  return true;
   4537 }
   4538 
   4539 template <class S>
   4540 void RecordedFilterNodeSetInput::Record(S& aStream) const {
   4541  WriteElement(aStream, mNode);
   4542  WriteElement(aStream, mIndex);
   4543  WriteElement(aStream, mInputFilter);
   4544  WriteElement(aStream, mInputSurface);
   4545 }
   4546 
   4547 template <class S>
   4548 RecordedFilterNodeSetInput::RecordedFilterNodeSetInput(S& aStream)
   4549    : RecordedEventDerived(FILTERNODESETINPUT) {
   4550  ReadElement(aStream, mNode);
   4551  ReadElement(aStream, mIndex);
   4552  ReadElement(aStream, mInputFilter);
   4553  ReadElement(aStream, mInputSurface);
   4554 }
   4555 
   4556 inline void RecordedFilterNodeSetInput::OutputSimpleEventInfo(
   4557    std::stringstream& aStringStream) const {
   4558  aStringStream << "[" << mNode << "] SetAttribute (" << mIndex << ", ";
   4559 
   4560  if (mInputFilter) {
   4561    aStringStream << "Filter: " << mInputFilter;
   4562  } else {
   4563    aStringStream << "Surface: " << mInputSurface;
   4564  }
   4565 
   4566  aStringStream << ")";
   4567 }
   4568 
   4569 inline bool RecordedLink::PlayEvent(Translator* aTranslator) const {
   4570  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   4571  if (!dt) {
   4572    return false;
   4573  }
   4574  dt->Link(mLocalDest.data(), mURI.data(), mRect);
   4575  return true;
   4576 }
   4577 
   4578 template <class S>
   4579 void RecordedLink::Record(S& aStream) const {
   4580  WriteElement(aStream, mRect);
   4581  WriteElement(aStream, mLocalDest.size());
   4582  mLocalDest.Write(aStream);
   4583  WriteElement(aStream, mURI.size());
   4584  mURI.Write(aStream);
   4585 }
   4586 
   4587 template <class S>
   4588 RecordedLink::RecordedLink(S& aStream) : RecordedEventDerived(LINK) {
   4589  ReadElement(aStream, mRect);
   4590  size_t localDestLen = 0;
   4591  ReadElement(aStream, localDestLen);
   4592  if (!aStream.good() ||
   4593      (localDestLen && !mLocalDest.Read(aStream, localDestLen))) {
   4594    aStream.SetIsBad();
   4595    return;
   4596  }
   4597  size_t uriLen = 0;
   4598  ReadElement(aStream, uriLen);
   4599  if (!aStream.good() || (uriLen && !mURI.Read(aStream, uriLen))) {
   4600    aStream.SetIsBad();
   4601    return;
   4602  }
   4603 }
   4604 
   4605 inline void RecordedLink::OutputSimpleEventInfo(
   4606    std::stringstream& aStringStream) const {
   4607  if (mLocalDest.empty()) {
   4608    aStringStream << "Link [" << mURI.data() << " @ " << mRect << "]";
   4609  } else {
   4610    aStringStream << "Link [" << mLocalDest.data() << " / " << mURI.data()
   4611                  << " @ " << mRect << "]";
   4612  }
   4613 }
   4614 
   4615 inline bool RecordedDestination::PlayEvent(Translator* aTranslator) const {
   4616  DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
   4617  if (!dt) {
   4618    return false;
   4619  }
   4620  dt->Destination(mDestination.data(), mPoint);
   4621  return true;
   4622 }
   4623 
   4624 template <class S>
   4625 void RecordedDestination::Record(S& aStream) const {
   4626  WriteElement(aStream, mPoint);
   4627  WriteElement(aStream, mDestination.size());
   4628  mDestination.Write(aStream);
   4629 }
   4630 
   4631 template <class S>
   4632 RecordedDestination::RecordedDestination(S& aStream)
   4633    : RecordedEventDerived(DESTINATION) {
   4634  ReadElement(aStream, mPoint);
   4635  size_t len = 0;
   4636  ReadElement(aStream, len);
   4637  if (!aStream.good() || (len && !mDestination.Read(aStream, len))) {
   4638    aStream.SetIsBad();
   4639    return;
   4640  }
   4641 }
   4642 
   4643 inline void RecordedDestination::OutputSimpleEventInfo(
   4644    std::stringstream& aStringStream) const {
   4645  aStringStream << "Destination [" << mDestination.data() << " @ " << mPoint
   4646                << "]";
   4647 }
   4648 
   4649 #define FOR_EACH_EVENT(f)                                          \
   4650  f(DRAWTARGETCREATION, RecordedDrawTargetCreation);               \
   4651  f(DRAWTARGETDESTRUCTION, RecordedDrawTargetDestruction);         \
   4652  f(SETCURRENTDRAWTARGET, RecordedSetCurrentDrawTarget);           \
   4653  f(FILLRECT, RecordedFillRect);                                   \
   4654  f(STROKERECT, RecordedStrokeRect);                               \
   4655  f(STROKELINE, RecordedStrokeLine);                               \
   4656  f(STROKECIRCLE, RecordedStrokeCircle);                           \
   4657  f(CLEARRECT, RecordedClearRect);                                 \
   4658  f(COPYSURFACE, RecordedCopySurface);                             \
   4659  f(SETPERMITSUBPIXELAA, RecordedSetPermitSubpixelAA);             \
   4660  f(SETTRANSFORM, RecordedSetTransform);                           \
   4661  f(PUSHCLIPRECT, RecordedPushClipRect);                           \
   4662  f(PUSHCLIP, RecordedPushClip);                                   \
   4663  f(POPCLIP, RecordedPopClip);                                     \
   4664  f(REMOVEALLCLIPS, RecordedRemoveAllClips);                       \
   4665  f(FILL, RecordedFill);                                           \
   4666  f(FILLCIRCLE, RecordedFillCircle);                               \
   4667  f(FILLGLYPHS, RecordedFillGlyphs);                               \
   4668  f(STROKEGLYPHS, RecordedStrokeGlyphs);                           \
   4669  f(MASK, RecordedMask);                                           \
   4670  f(STROKE, RecordedStroke);                                       \
   4671  f(DRAWSURFACE, RecordedDrawSurface);                             \
   4672  f(DRAWSURFACEDESCRIPTOR, RecordedDrawSurfaceDescriptor);         \
   4673  f(DRAWDEPENDENTSURFACE, RecordedDrawDependentSurface);           \
   4674  f(DRAWSURFACEWITHSHADOW, RecordedDrawSurfaceWithShadow);         \
   4675  f(DRAWSHADOW, RecordedDrawShadow);                               \
   4676  f(DRAWFILTER, RecordedDrawFilter);                               \
   4677  f(PATHCREATION, RecordedPathCreation);                           \
   4678  f(PATHDESTRUCTION, RecordedPathDestruction);                     \
   4679  f(SOURCESURFACECREATION, RecordedSourceSurfaceCreation);         \
   4680  f(SOURCESURFACEDESTRUCTION, RecordedSourceSurfaceDestruction);   \
   4681  f(FILTERNODECREATION, RecordedFilterNodeCreation);               \
   4682  f(DEFERFILTERINPUT, RecordedDeferFilterInput);                   \
   4683  f(FILTERNODEDESTRUCTION, RecordedFilterNodeDestruction);         \
   4684  f(GRADIENTSTOPSCREATION, RecordedGradientStopsCreation);         \
   4685  f(GRADIENTSTOPSDESTRUCTION, RecordedGradientStopsDestruction);   \
   4686  f(SNAPSHOT, RecordedSnapshot);                                   \
   4687  f(SCALEDFONTCREATION, RecordedScaledFontCreation);               \
   4688  f(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction);         \
   4689  f(MASKSURFACE, RecordedMaskSurface);                             \
   4690  f(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute);       \
   4691  f(FILTERNODESETINPUT, RecordedFilterNodeSetInput);               \
   4692  f(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget);     \
   4693  f(CREATECLIPPEDDRAWTARGET, RecordedCreateClippedDrawTarget);     \
   4694  f(CREATEDRAWTARGETFORFILTER, RecordedCreateDrawTargetForFilter); \
   4695  f(FONTDATA, RecordedFontData);                                   \
   4696  f(FONTDESC, RecordedFontDescriptor);                             \
   4697  f(PUSHLAYER, RecordedPushLayer);                                 \
   4698  f(PUSHLAYERWITHBLEND, RecordedPushLayerWithBlend);               \
   4699  f(POPLAYER, RecordedPopLayer);                                   \
   4700  f(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation);           \
   4701  f(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction);     \
   4702  f(INTOLUMINANCE, RecordedIntoLuminanceSource);                   \
   4703  f(EXTRACTSUBRECT, RecordedExtractSubrect);                       \
   4704  f(EXTERNALSURFACECREATION, RecordedExternalSurfaceCreation);     \
   4705  f(FLUSH, RecordedFlush);                                         \
   4706  f(DETACHALLSNAPSHOTS, RecordedDetachAllSnapshots);               \
   4707  f(OPTIMIZESOURCESURFACE, RecordedOptimizeSourceSurface);         \
   4708  f(LINK, RecordedLink);                                           \
   4709  f(DESTINATION, RecordedDestination);
   4710 
   4711 #define DO_WITH_EVENT_TYPE(_typeenum, _class) \
   4712  case _typeenum: {                           \
   4713    auto e = _class(aStream);                 \
   4714    return aAction(&e);                       \
   4715  }
   4716 
   4717 template <class S>
   4718 bool RecordedEvent::DoWithEvent(
   4719    S& aStream, EventType aType,
   4720    const std::function<bool(RecordedEvent*)>& aAction) {
   4721  switch (aType) {
   4722    FOR_EACH_EVENT(DO_WITH_EVENT_TYPE)
   4723    default:
   4724      return false;
   4725  }
   4726 }
   4727 
   4728 }  // namespace gfx
   4729 }  // namespace mozilla
   4730 
   4731 #endif