gfx/2d/DrawTargetRecording.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "DrawTargetRecording.h"
     7 #include "PathRecording.h"
     8 #include <stdio.h>
    10 #include "Logging.h"
    11 #include "Tools.h"
    12 #include "Filters.h"
    14 namespace mozilla {
    15 namespace gfx {
    17 class SourceSurfaceRecording : public SourceSurface
    18 {
    19 public:
    20   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording)
    21   SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder)
    22     : mFinalSurface(aFinalSurface), mRecorder(aRecorder)
    23   {
    24   }
    26   ~SourceSurfaceRecording()
    27   {
    28     mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
    29   }
    31   virtual SurfaceType GetType() const { return SurfaceType::RECORDING; }
    32   virtual IntSize GetSize() const { return mFinalSurface->GetSize(); }
    33   virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); }
    34   virtual TemporaryRef<DataSourceSurface> GetDataSurface() { return mFinalSurface->GetDataSurface(); }
    36   RefPtr<SourceSurface> mFinalSurface;
    37   RefPtr<DrawEventRecorderPrivate> mRecorder;
    38 };
    40 class GradientStopsRecording : public GradientStops
    41 {
    42 public:
    43   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording)
    44   GradientStopsRecording(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder)
    45     : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder)
    46   {
    47   }
    49   ~GradientStopsRecording()
    50   {
    51     mRecorder->RecordEvent(RecordedGradientStopsDestruction(this));
    52   }
    54   virtual BackendType GetBackendType() const { return BackendType::RECORDING; }
    56   RefPtr<GradientStops> mFinalGradientStops;
    57   RefPtr<DrawEventRecorderPrivate> mRecorder;
    58 };
    60 static SourceSurface *
    61 GetSourceSurface(SourceSurface *aSurface)
    62 {
    63   if (aSurface->GetType() != SurfaceType::RECORDING) {
    64     return aSurface;
    65   }
    67   return static_cast<SourceSurfaceRecording*>(aSurface)->mFinalSurface;
    68 }
    70 static GradientStops *
    71 GetGradientStops(GradientStops *aStops)
    72 {
    73   if (aStops->GetBackendType() != BackendType::RECORDING) {
    74     return aStops;
    75   }
    77   return static_cast<GradientStopsRecording*>(aStops)->mFinalGradientStops;
    78 }
    80 class FilterNodeRecording : public FilterNode
    81 {
    82 public:
    83   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording)
    84   using FilterNode::SetAttribute;
    86   FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder)
    87     : mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder)
    88   {
    89   }
    91   ~FilterNodeRecording()
    92   {
    93     mRecorder->RecordEvent(RecordedFilterNodeDestruction(this));
    94   }
    96   virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface)
    97   {
    98     mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface));
    99     mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface));
   100   }
   101   virtual void SetInput(uint32_t aIndex, FilterNode *aFilter)
   102   {
   103     FilterNode *finalNode = aFilter;
   104     if (aFilter->GetBackendType() != FILTER_BACKEND_RECORDING) {
   105       gfxWarning() << "Non recording filter node used with recording DrawTarget!";
   106     } else {
   107       finalNode = static_cast<FilterNodeRecording*>(aFilter)->mFinalFilterNode;
   108     }
   110     mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
   111     mFinalFilterNode->SetInput(aIndex, finalNode);
   112   }
   115 #define FORWARD_SET_ATTRIBUTE(type, argtype) \
   116   virtual void SetAttribute(uint32_t aIndex, type aValue) { \
   117     mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aValue, RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \
   118     mFinalFilterNode->SetAttribute(aIndex, aValue); \
   119   }
   121   FORWARD_SET_ATTRIBUTE(bool, BOOL);
   122   FORWARD_SET_ATTRIBUTE(uint32_t, UINT32);
   123   FORWARD_SET_ATTRIBUTE(Float, FLOAT);
   124   FORWARD_SET_ATTRIBUTE(const Size&, SIZE);
   125   FORWARD_SET_ATTRIBUTE(const IntSize&, INTSIZE);
   126   FORWARD_SET_ATTRIBUTE(const IntPoint&, INTPOINT);
   127   FORWARD_SET_ATTRIBUTE(const Rect&, RECT);
   128   FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT);
   129   FORWARD_SET_ATTRIBUTE(const Point&, POINT);
   130   FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4);
   131   FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D);
   132   FORWARD_SET_ATTRIBUTE(const Color&, COLOR);
   134 #undef FORWARD_SET_ATTRIBUTE
   136   virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) {
   137     mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize));
   138     mFinalFilterNode->SetAttribute(aIndex, aFloat, aSize);
   139   }
   141   virtual FilterBackend GetBackendType() MOZ_OVERRIDE { return FILTER_BACKEND_RECORDING; }
   143   RefPtr<FilterNode> mFinalFilterNode;
   144   RefPtr<DrawEventRecorderPrivate> mRecorder;
   145 };
   147 static FilterNode*
   148 GetFilterNode(FilterNode* aNode)
   149 {
   150   if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) {
   151     gfxWarning() << "Non recording filter node used with recording DrawTarget!";
   152     return aNode;
   153   }
   155   return static_cast<FilterNodeRecording*>(aNode)->mFinalFilterNode;
   156 }
   158 struct AdjustedPattern
   159 {
   160   AdjustedPattern(const Pattern &aPattern)
   161     : mPattern(nullptr)
   162   {
   163     mOrigPattern = const_cast<Pattern*>(&aPattern);
   164   }
   166   ~AdjustedPattern() {
   167     if (mPattern) {
   168       mPattern->~Pattern();
   169     }
   170   }
   172   operator Pattern*()
   173   {
   174     switch(mOrigPattern->GetType()) {
   175     case PatternType::COLOR:
   176       return mOrigPattern;
   177     case PatternType::SURFACE:
   178       {
   179         SurfacePattern *surfPat = static_cast<SurfacePattern*>(mOrigPattern);
   180         mPattern =
   181           new (mSurfPat) SurfacePattern(GetSourceSurface(surfPat->mSurface),
   182                                         surfPat->mExtendMode, surfPat->mMatrix,
   183                                         surfPat->mFilter);
   184         return mPattern;
   185       }
   186     case PatternType::LINEAR_GRADIENT:
   187       {
   188         LinearGradientPattern *linGradPat = static_cast<LinearGradientPattern*>(mOrigPattern);
   189         mPattern =
   190           new (mLinGradPat) LinearGradientPattern(linGradPat->mBegin, linGradPat->mEnd,
   191                                                   GetGradientStops(linGradPat->mStops),
   192                                                   linGradPat->mMatrix);
   193         return mPattern;
   194       }
   195     case PatternType::RADIAL_GRADIENT:
   196       {
   197         RadialGradientPattern *radGradPat = static_cast<RadialGradientPattern*>(mOrigPattern);
   198         mPattern =
   199           new (mRadGradPat) RadialGradientPattern(radGradPat->mCenter1, radGradPat->mCenter2,
   200                                                   radGradPat->mRadius1, radGradPat->mRadius2,
   201                                                   GetGradientStops(radGradPat->mStops),
   202                                                   radGradPat->mMatrix);
   203         return mPattern;
   204       }
   205     default:
   206       return new (mColPat) ColorPattern(Color());
   207     }
   209     return mPattern;
   210   }
   212   union {
   213     char mColPat[sizeof(ColorPattern)];
   214     char mLinGradPat[sizeof(LinearGradientPattern)];
   215     char mRadGradPat[sizeof(RadialGradientPattern)];
   216     char mSurfPat[sizeof(SurfacePattern)];
   217   };
   219   Pattern *mOrigPattern;
   220   Pattern *mPattern;
   221 };
   223 DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData)
   224   : mRecorder(static_cast<DrawEventRecorderPrivate*>(aRecorder))
   225   , mFinalDT(aDT)
   226 {
   227   RefPtr<SourceSurface> snapshot = aHasData ? mFinalDT->Snapshot() : nullptr;
   228   mRecorder->RecordEvent(RecordedDrawTargetCreation(this, mFinalDT->GetType(), mFinalDT->GetSize(), mFinalDT->GetFormat(),
   229                                                     aHasData, snapshot));
   230   mFormat = mFinalDT->GetFormat();
   231 }
   233 DrawTargetRecording::~DrawTargetRecording()
   234 {
   235   mRecorder->RecordEvent(RecordedDrawTargetDestruction(this));
   236 }
   238 void
   239 DrawTargetRecording::FillRect(const Rect &aRect,
   240                               const Pattern &aPattern,
   241                               const DrawOptions &aOptions)
   242 {
   243   mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions));
   244   mFinalDT->FillRect(aRect, *AdjustedPattern(aPattern), aOptions);
   245 }
   247 void
   248 DrawTargetRecording::StrokeRect(const Rect &aRect,
   249                                 const Pattern &aPattern,
   250                                 const StrokeOptions &aStrokeOptions,
   251                                 const DrawOptions &aOptions)
   252 {
   253   mRecorder->RecordEvent(RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions));
   254   mFinalDT->StrokeRect(aRect, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
   255 }
   257 void
   258 DrawTargetRecording::StrokeLine(const Point &aBegin,
   259                                 const Point &aEnd,
   260                                 const Pattern &aPattern,
   261                                 const StrokeOptions &aStrokeOptions,
   262                                 const DrawOptions &aOptions)
   263 {
   264   mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions));
   265   mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
   266 }
   268 Path*
   269 DrawTargetRecording::GetPathForPathRecording(const Path *aPath) const
   270 {
   271   if (aPath->GetBackendType() != BackendType::RECORDING) {
   272     return nullptr;
   273   }
   275   return static_cast<const PathRecording*>(aPath)->mPath;
   276 }
   278 void
   279 DrawTargetRecording::Fill(const Path *aPath,
   280                           const Pattern &aPattern,
   281                           const DrawOptions &aOptions)
   282 {
   283   EnsureStored(aPath);
   285   mRecorder->RecordEvent(RecordedFill(this, const_cast<Path*>(aPath), aPattern, aOptions));
   286   mFinalDT->Fill(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aOptions);
   287 }
   289 struct RecordingFontUserData
   290 {
   291   void *refPtr;
   292   RefPtr<DrawEventRecorderPrivate> recorder;
   293 };
   295 void RecordingFontUserDataDestroyFunc(void *aUserData)
   296 {
   297   RecordingFontUserData *userData =
   298     static_cast<RecordingFontUserData*>(aUserData);
   300   // TODO support font in b2g recordings
   301 #ifndef MOZ_WIDGET_GONK
   302   userData->recorder->RecordEvent(RecordedScaledFontDestruction(userData->refPtr));
   303 #endif
   305   delete userData;
   306 }
   308 void
   309 DrawTargetRecording::FillGlyphs(ScaledFont *aFont,
   310                                 const GlyphBuffer &aBuffer,
   311                                 const Pattern &aPattern,
   312                                 const DrawOptions &aOptions,
   313                                 const GlyphRenderingOptions *aRenderingOptions)
   314 {
   315   if (!aFont->GetUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()))) {
   316   // TODO support font in b2g recordings
   317 #ifndef MOZ_WIDGET_GONK
   318     mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, aFont));
   319 #endif
   320     RecordingFontUserData *userData = new RecordingFontUserData;
   321     userData->refPtr = aFont;
   322     userData->recorder = mRecorder;
   323     aFont->AddUserData(reinterpret_cast<UserDataKey*>(mRecorder.get()), userData, 
   324                        &RecordingFontUserDataDestroyFunc);
   325   }
   327   // TODO support font in b2g recordings
   328 #ifndef MOZ_WIDGET_GONK
   329   mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs));
   330 #endif
   331   mFinalDT->FillGlyphs(aFont, aBuffer, aPattern, aOptions, aRenderingOptions);
   332 }
   334 void
   335 DrawTargetRecording::Mask(const Pattern &aSource,
   336                           const Pattern &aMask,
   337                           const DrawOptions &aOptions)
   338 {
   339   mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions));
   340   mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions);
   341 }
   343 void
   344 DrawTargetRecording::MaskSurface(const Pattern &aSource,
   345                                  SourceSurface *aMask,
   346                                  Point aOffset,
   347                                  const DrawOptions &aOptions)
   348 {
   349   mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions));
   350   mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions);
   351 }
   353 void
   354 DrawTargetRecording::Stroke(const Path *aPath,
   355                             const Pattern &aPattern,
   356                             const StrokeOptions &aStrokeOptions,
   357                             const DrawOptions &aOptions)
   358 {
   359   EnsureStored(aPath);
   361   mRecorder->RecordEvent(RecordedStroke(this, const_cast<Path*>(aPath), aPattern, aStrokeOptions, aOptions));
   362   mFinalDT->Stroke(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
   363 }
   365 TemporaryRef<SourceSurface>
   366 DrawTargetRecording::Snapshot()
   367 {
   368   RefPtr<SourceSurface> surf = mFinalDT->Snapshot();
   370   RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
   372   mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
   374   return retSurf;
   375 }
   377 void
   378 DrawTargetRecording::DrawSurface(SourceSurface *aSurface,
   379                                  const Rect &aDest,
   380                                  const Rect &aSource,
   381                                  const DrawSurfaceOptions &aSurfOptions,
   382                                  const DrawOptions &aOptions)
   383 {
   384   mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions));
   385   mFinalDT->DrawSurface(GetSourceSurface(aSurface), aDest, aSource, aSurfOptions, aOptions);
   386 }
   388 void
   389 DrawTargetRecording::DrawSurfaceWithShadow(SourceSurface *aSurface,
   390                                            const Point &aDest,
   391                                            const Color &aColor,
   392                                            const Point &aOffset,
   393                                            Float aSigma,
   394                                            CompositionOp aOp)
   395 {
   396   mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(this, aSurface, aDest, aColor, aOffset, aSigma, aOp));
   397   mFinalDT->DrawSurfaceWithShadow(GetSourceSurface(aSurface), aDest, aColor, aOffset, aSigma, aOp);
   398 }
   400 void
   401 DrawTargetRecording::DrawFilter(FilterNode *aNode,
   402                                 const Rect &aSourceRect,
   403                                 const Point &aDestPoint,
   404                                 const DrawOptions &aOptions)
   405 {
   406   mRecorder->RecordEvent(RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions));
   407   mFinalDT->DrawFilter(GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions);
   408 }
   410 TemporaryRef<FilterNode>
   411 DrawTargetRecording::CreateFilter(FilterType aType)
   412 {
   413   RefPtr<FilterNode> node = mFinalDT->CreateFilter(aType);
   415   RefPtr<FilterNode> retNode = new FilterNodeRecording(node, mRecorder);
   417   mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
   419   return retNode;
   420 }
   422 void
   423 DrawTargetRecording::ClearRect(const Rect &aRect)
   424 {
   425   mRecorder->RecordEvent(RecordedClearRect(this, aRect));
   426   mFinalDT->ClearRect(aRect);
   427 }
   429 void
   430 DrawTargetRecording::CopySurface(SourceSurface *aSurface,
   431                                  const IntRect &aSourceRect,
   432                                  const IntPoint &aDestination)
   433 {
   434   mRecorder->RecordEvent(RecordedCopySurface(this, aSurface, aSourceRect, aDestination));
   435   mFinalDT->CopySurface(GetSourceSurface(aSurface), aSourceRect, aDestination);
   436 }
   438 void
   439 DrawTargetRecording::PushClip(const Path *aPath)
   440 {
   441   EnsureStored(aPath);
   443   mRecorder->RecordEvent(RecordedPushClip(this, const_cast<Path*>(aPath)));
   444   mFinalDT->PushClip(GetPathForPathRecording(aPath));
   445 }
   447 void
   448 DrawTargetRecording::PushClipRect(const Rect &aRect)
   449 {
   450   mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
   451   mFinalDT->PushClipRect(aRect);
   452 }
   454 void
   455 DrawTargetRecording::PopClip()
   456 {
   457   mRecorder->RecordEvent(RecordedPopClip(this));
   458   mFinalDT->PopClip();
   459 }
   461 TemporaryRef<SourceSurface>
   462 DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData,
   463                                                  const IntSize &aSize,
   464                                                  int32_t aStride,
   465                                                  SurfaceFormat aFormat) const
   466 {
   467   RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat);
   469   RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
   471   mRecorder->RecordEvent(RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
   473   return retSurf;
   474 }
   476 TemporaryRef<SourceSurface>
   477 DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const
   478 {
   479   RefPtr<SourceSurface> surf = mFinalDT->OptimizeSourceSurface(aSurface);
   481   RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
   483   RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
   485   if (!dataSurf) {
   486     // Let's try get it off the original surface.
   487     dataSurf = aSurface->GetDataSurface();
   488   }
   490   if (!dataSurf) {
   491     gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface";
   492     // Insert a bogus source surface.
   493     uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())];
   494     memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat()));
   495     mRecorder->RecordEvent(
   496       RecordedSourceSurfaceCreation(retSurf, sourceData,
   497                                     surf->GetSize().width * BytesPerPixel(surf->GetFormat()),
   498                                     surf->GetSize(), surf->GetFormat()));
   499     delete [] sourceData;
   500   } else {
   501     mRecorder->RecordEvent(
   502       RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(),
   503                                     dataSurf->GetSize(), dataSurf->GetFormat()));
   504   }
   506   return retSurf;
   507 }
   509 TemporaryRef<SourceSurface>
   510 DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
   511 {
   512   RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface);
   514   RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
   516   RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
   518   if (!dataSurf) {
   519     gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface";
   520     // Insert a bogus source surface.
   521     uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())];
   522     memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat()));
   523     mRecorder->RecordEvent(
   524       RecordedSourceSurfaceCreation(retSurf, sourceData,
   525                                     surf->GetSize().width * BytesPerPixel(surf->GetFormat()),
   526                                     surf->GetSize(), surf->GetFormat()));
   527     delete [] sourceData;
   528   } else {
   529     mRecorder->RecordEvent(
   530       RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(),
   531                                     dataSurf->GetSize(), dataSurf->GetFormat()));
   532   }
   534   return retSurf;
   535 }
   537 TemporaryRef<DrawTarget>
   538 DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
   539 {
   540   RefPtr<DrawTarget> dt = mFinalDT->CreateSimilarDrawTarget(aSize, aFormat);
   542   RefPtr<DrawTarget> retDT = new DrawTargetRecording(mRecorder.get(), dt);
   544   return retDT;
   545 }
   547 TemporaryRef<PathBuilder>
   548 DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const
   549 {
   550   RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
   551   return new PathBuilderRecording(builder, aFillRule);
   552 }
   554 TemporaryRef<GradientStops>
   555 DrawTargetRecording::CreateGradientStops(GradientStop *aStops,
   556                                          uint32_t aNumStops,
   557                                          ExtendMode aExtendMode) const
   558 {
   559   RefPtr<GradientStops> stops = mFinalDT->CreateGradientStops(aStops, aNumStops, aExtendMode);
   561   RefPtr<GradientStops> retStops = new GradientStopsRecording(stops, mRecorder);
   563   mRecorder->RecordEvent(RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
   565   return retStops;
   566 }
   568 void
   569 DrawTargetRecording::SetTransform(const Matrix &aTransform)
   570 {
   571   mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
   572   DrawTarget::SetTransform(aTransform);
   573   mFinalDT->SetTransform(aTransform);
   574 }
   576 void
   577 DrawTargetRecording::EnsureStored(const Path *aPath)
   578 {
   579   if (!mRecorder->HasStoredPath(aPath)) {
   580     if (aPath->GetBackendType() != BackendType::RECORDING) {
   581       gfxWarning() << "Cannot record this fill path properly!";
   582     } else {
   583       PathRecording *recPath = const_cast<PathRecording*>(static_cast<const PathRecording*>(aPath));
   584       mRecorder->RecordEvent(RecordedPathCreation(recPath));
   585       mRecorder->AddStoredPath(aPath);
   586       recPath->mStoredRecorders.push_back(mRecorder);
   587     }
   588   }
   589 }
   591 }
   592 }

mercurial