gfx/2d/DrawTargetRecording.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:92150172e354
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/. */
5
6 #include "DrawTargetRecording.h"
7 #include "PathRecording.h"
8 #include <stdio.h>
9
10 #include "Logging.h"
11 #include "Tools.h"
12 #include "Filters.h"
13
14 namespace mozilla {
15 namespace gfx {
16
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 }
25
26 ~SourceSurfaceRecording()
27 {
28 mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this));
29 }
30
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(); }
35
36 RefPtr<SourceSurface> mFinalSurface;
37 RefPtr<DrawEventRecorderPrivate> mRecorder;
38 };
39
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 }
48
49 ~GradientStopsRecording()
50 {
51 mRecorder->RecordEvent(RecordedGradientStopsDestruction(this));
52 }
53
54 virtual BackendType GetBackendType() const { return BackendType::RECORDING; }
55
56 RefPtr<GradientStops> mFinalGradientStops;
57 RefPtr<DrawEventRecorderPrivate> mRecorder;
58 };
59
60 static SourceSurface *
61 GetSourceSurface(SourceSurface *aSurface)
62 {
63 if (aSurface->GetType() != SurfaceType::RECORDING) {
64 return aSurface;
65 }
66
67 return static_cast<SourceSurfaceRecording*>(aSurface)->mFinalSurface;
68 }
69
70 static GradientStops *
71 GetGradientStops(GradientStops *aStops)
72 {
73 if (aStops->GetBackendType() != BackendType::RECORDING) {
74 return aStops;
75 }
76
77 return static_cast<GradientStopsRecording*>(aStops)->mFinalGradientStops;
78 }
79
80 class FilterNodeRecording : public FilterNode
81 {
82 public:
83 MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording)
84 using FilterNode::SetAttribute;
85
86 FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder)
87 : mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder)
88 {
89 }
90
91 ~FilterNodeRecording()
92 {
93 mRecorder->RecordEvent(RecordedFilterNodeDestruction(this));
94 }
95
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 }
109
110 mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter));
111 mFinalFilterNode->SetInput(aIndex, finalNode);
112 }
113
114
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 }
120
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);
133
134 #undef FORWARD_SET_ATTRIBUTE
135
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 }
140
141 virtual FilterBackend GetBackendType() MOZ_OVERRIDE { return FILTER_BACKEND_RECORDING; }
142
143 RefPtr<FilterNode> mFinalFilterNode;
144 RefPtr<DrawEventRecorderPrivate> mRecorder;
145 };
146
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 }
154
155 return static_cast<FilterNodeRecording*>(aNode)->mFinalFilterNode;
156 }
157
158 struct AdjustedPattern
159 {
160 AdjustedPattern(const Pattern &aPattern)
161 : mPattern(nullptr)
162 {
163 mOrigPattern = const_cast<Pattern*>(&aPattern);
164 }
165
166 ~AdjustedPattern() {
167 if (mPattern) {
168 mPattern->~Pattern();
169 }
170 }
171
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 }
208
209 return mPattern;
210 }
211
212 union {
213 char mColPat[sizeof(ColorPattern)];
214 char mLinGradPat[sizeof(LinearGradientPattern)];
215 char mRadGradPat[sizeof(RadialGradientPattern)];
216 char mSurfPat[sizeof(SurfacePattern)];
217 };
218
219 Pattern *mOrigPattern;
220 Pattern *mPattern;
221 };
222
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 }
232
233 DrawTargetRecording::~DrawTargetRecording()
234 {
235 mRecorder->RecordEvent(RecordedDrawTargetDestruction(this));
236 }
237
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 }
246
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 }
256
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 }
267
268 Path*
269 DrawTargetRecording::GetPathForPathRecording(const Path *aPath) const
270 {
271 if (aPath->GetBackendType() != BackendType::RECORDING) {
272 return nullptr;
273 }
274
275 return static_cast<const PathRecording*>(aPath)->mPath;
276 }
277
278 void
279 DrawTargetRecording::Fill(const Path *aPath,
280 const Pattern &aPattern,
281 const DrawOptions &aOptions)
282 {
283 EnsureStored(aPath);
284
285 mRecorder->RecordEvent(RecordedFill(this, const_cast<Path*>(aPath), aPattern, aOptions));
286 mFinalDT->Fill(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aOptions);
287 }
288
289 struct RecordingFontUserData
290 {
291 void *refPtr;
292 RefPtr<DrawEventRecorderPrivate> recorder;
293 };
294
295 void RecordingFontUserDataDestroyFunc(void *aUserData)
296 {
297 RecordingFontUserData *userData =
298 static_cast<RecordingFontUserData*>(aUserData);
299
300 // TODO support font in b2g recordings
301 #ifndef MOZ_WIDGET_GONK
302 userData->recorder->RecordEvent(RecordedScaledFontDestruction(userData->refPtr));
303 #endif
304
305 delete userData;
306 }
307
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 }
326
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 }
333
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 }
342
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 }
352
353 void
354 DrawTargetRecording::Stroke(const Path *aPath,
355 const Pattern &aPattern,
356 const StrokeOptions &aStrokeOptions,
357 const DrawOptions &aOptions)
358 {
359 EnsureStored(aPath);
360
361 mRecorder->RecordEvent(RecordedStroke(this, const_cast<Path*>(aPath), aPattern, aStrokeOptions, aOptions));
362 mFinalDT->Stroke(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aStrokeOptions, aOptions);
363 }
364
365 TemporaryRef<SourceSurface>
366 DrawTargetRecording::Snapshot()
367 {
368 RefPtr<SourceSurface> surf = mFinalDT->Snapshot();
369
370 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
371
372 mRecorder->RecordEvent(RecordedSnapshot(retSurf, this));
373
374 return retSurf;
375 }
376
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 }
387
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 }
399
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 }
409
410 TemporaryRef<FilterNode>
411 DrawTargetRecording::CreateFilter(FilterType aType)
412 {
413 RefPtr<FilterNode> node = mFinalDT->CreateFilter(aType);
414
415 RefPtr<FilterNode> retNode = new FilterNodeRecording(node, mRecorder);
416
417 mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType));
418
419 return retNode;
420 }
421
422 void
423 DrawTargetRecording::ClearRect(const Rect &aRect)
424 {
425 mRecorder->RecordEvent(RecordedClearRect(this, aRect));
426 mFinalDT->ClearRect(aRect);
427 }
428
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 }
437
438 void
439 DrawTargetRecording::PushClip(const Path *aPath)
440 {
441 EnsureStored(aPath);
442
443 mRecorder->RecordEvent(RecordedPushClip(this, const_cast<Path*>(aPath)));
444 mFinalDT->PushClip(GetPathForPathRecording(aPath));
445 }
446
447 void
448 DrawTargetRecording::PushClipRect(const Rect &aRect)
449 {
450 mRecorder->RecordEvent(RecordedPushClipRect(this, aRect));
451 mFinalDT->PushClipRect(aRect);
452 }
453
454 void
455 DrawTargetRecording::PopClip()
456 {
457 mRecorder->RecordEvent(RecordedPopClip(this));
458 mFinalDT->PopClip();
459 }
460
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);
468
469 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
470
471 mRecorder->RecordEvent(RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat));
472
473 return retSurf;
474 }
475
476 TemporaryRef<SourceSurface>
477 DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const
478 {
479 RefPtr<SourceSurface> surf = mFinalDT->OptimizeSourceSurface(aSurface);
480
481 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
482
483 RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
484
485 if (!dataSurf) {
486 // Let's try get it off the original surface.
487 dataSurf = aSurface->GetDataSurface();
488 }
489
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 }
505
506 return retSurf;
507 }
508
509 TemporaryRef<SourceSurface>
510 DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
511 {
512 RefPtr<SourceSurface> surf = mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface);
513
514 RefPtr<SourceSurface> retSurf = new SourceSurfaceRecording(surf, mRecorder);
515
516 RefPtr<DataSourceSurface> dataSurf = surf->GetDataSurface();
517
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 }
533
534 return retSurf;
535 }
536
537 TemporaryRef<DrawTarget>
538 DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
539 {
540 RefPtr<DrawTarget> dt = mFinalDT->CreateSimilarDrawTarget(aSize, aFormat);
541
542 RefPtr<DrawTarget> retDT = new DrawTargetRecording(mRecorder.get(), dt);
543
544 return retDT;
545 }
546
547 TemporaryRef<PathBuilder>
548 DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const
549 {
550 RefPtr<PathBuilder> builder = mFinalDT->CreatePathBuilder(aFillRule);
551 return new PathBuilderRecording(builder, aFillRule);
552 }
553
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);
560
561 RefPtr<GradientStops> retStops = new GradientStopsRecording(stops, mRecorder);
562
563 mRecorder->RecordEvent(RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode));
564
565 return retStops;
566 }
567
568 void
569 DrawTargetRecording::SetTransform(const Matrix &aTransform)
570 {
571 mRecorder->RecordEvent(RecordedSetTransform(this, aTransform));
572 DrawTarget::SetTransform(aTransform);
573 mFinalDT->SetTransform(aTransform);
574 }
575
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 }
590
591 }
592 }

mercurial