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