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 #include "RecordedEventImpl.h"
8 
9 #include "PathRecording.h"
10 #include "RecordingTypes.h"
11 #include "Tools.h"
12 #include "Filters.h"
13 #include "Logging.h"
14 #include "ScaledFontBase.h"
15 #include "SFNTData.h"
16 #include "InlineTranslator.h"
17 
18 namespace mozilla {
19 namespace gfx {
20 
21 /* static */
DoWithEventFromStream(EventStream & aStream,EventType aType,const std::function<bool (RecordedEvent *)> & aAction)22 bool RecordedEvent::DoWithEventFromStream(
23     EventStream& aStream, EventType aType,
24     const std::function<bool(RecordedEvent*)>& aAction) {
25   return DoWithEvent(aStream, aType, aAction);
26 }
27 
28 /* static */
DoWithEventFromStream(EventRingBuffer & aStream,EventType aType,const std::function<bool (RecordedEvent *)> & aAction)29 bool RecordedEvent::DoWithEventFromStream(
30     EventRingBuffer& aStream, EventType aType,
31     const std::function<bool(RecordedEvent*)>& aAction) {
32   return DoWithEvent(aStream, aType, aAction);
33 }
34 
GetEventName(EventType aType)35 std::string RecordedEvent::GetEventName(EventType aType) {
36   switch (aType) {
37     case DRAWTARGETCREATION:
38       return "DrawTarget Creation";
39     case DRAWTARGETDESTRUCTION:
40       return "DrawTarget Destruction";
41     case FILLRECT:
42       return "FillRect";
43     case STROKERECT:
44       return "StrokeRect";
45     case STROKELINE:
46       return "StrokeLine";
47     case CLEARRECT:
48       return "ClearRect";
49     case COPYSURFACE:
50       return "CopySurface";
51     case SETTRANSFORM:
52       return "SetTransform";
53     case PUSHCLIP:
54       return "PushClip";
55     case PUSHCLIPRECT:
56       return "PushClipRect";
57     case POPCLIP:
58       return "PopClip";
59     case FILL:
60       return "Fill";
61     case FILLGLYPHS:
62       return "FillGlyphs";
63     case MASK:
64       return "Mask";
65     case STROKE:
66       return "Stroke";
67     case DRAWSURFACE:
68       return "DrawSurface";
69     case DRAWDEPENDENTSURFACE:
70       return "DrawDependentSurface";
71     case DRAWSURFACEWITHSHADOW:
72       return "DrawSurfaceWithShadow";
73     case DRAWFILTER:
74       return "DrawFilter";
75     case PATHCREATION:
76       return "PathCreation";
77     case PATHDESTRUCTION:
78       return "PathDestruction";
79     case SOURCESURFACECREATION:
80       return "SourceSurfaceCreation";
81     case SOURCESURFACEDESTRUCTION:
82       return "SourceSurfaceDestruction";
83     case FILTERNODECREATION:
84       return "FilterNodeCreation";
85     case FILTERNODEDESTRUCTION:
86       return "FilterNodeDestruction";
87     case GRADIENTSTOPSCREATION:
88       return "GradientStopsCreation";
89     case GRADIENTSTOPSDESTRUCTION:
90       return "GradientStopsDestruction";
91     case SNAPSHOT:
92       return "Snapshot";
93     case SCALEDFONTCREATION:
94       return "ScaledFontCreation";
95     case SCALEDFONTDESTRUCTION:
96       return "ScaledFontDestruction";
97     case MASKSURFACE:
98       return "MaskSurface";
99     case FILTERNODESETATTRIBUTE:
100       return "SetAttribute";
101     case FILTERNODESETINPUT:
102       return "SetInput";
103     case CREATESIMILARDRAWTARGET:
104       return "CreateSimilarDrawTarget";
105     case FONTDATA:
106       return "FontData";
107     case FONTDESC:
108       return "FontDescriptor";
109     case PUSHLAYER:
110       return "PushLayer";
111     case POPLAYER:
112       return "PopLayer";
113     case UNSCALEDFONTCREATION:
114       return "UnscaledFontCreation";
115     case UNSCALEDFONTDESTRUCTION:
116       return "UnscaledFontDestruction";
117     case EXTERNALSURFACECREATION:
118       return "ExternalSourceSurfaceCreation";
119     case LINK:
120       return "Link";
121     case DESTINATION:
122       return "Destination";
123     default:
124       return "Unknown";
125   }
126 }
127 
128 template <class S>
RecordUnscaledFontImpl(UnscaledFont * aUnscaledFont,S & aOutput)129 void RecordedEvent::RecordUnscaledFontImpl(UnscaledFont* aUnscaledFont,
130                                            S& aOutput) {
131   RecordedFontData fontData(aUnscaledFont);
132   RecordedFontDetails fontDetails;
133   if (fontData.GetFontDetails(fontDetails)) {
134     // Try to serialise the whole font, just in case this is a web font that
135     // is not present on the system.
136     WriteElement(aOutput, fontData.mType);
137     fontData.RecordToStream(aOutput);
138 
139     auto r = RecordedUnscaledFontCreation(aUnscaledFont, fontDetails);
140     WriteElement(aOutput, r.mType);
141     r.RecordToStream(aOutput);
142   } else {
143     // If that fails, record just the font description and try to load it from
144     // the system on the other side.
145     RecordedFontDescriptor fontDesc(aUnscaledFont);
146     if (fontDesc.IsValid()) {
147       WriteElement(aOutput, fontDesc.RecordedEvent::mType);
148       fontDesc.RecordToStream(aOutput);
149     } else {
150       gfxWarning()
151           << "DrawTargetRecording::FillGlyphs failed to serialise UnscaledFont";
152     }
153   }
154 }
155 
RecordUnscaledFont(UnscaledFont * aUnscaledFont,std::ostream * aOutput)156 void RecordedEvent::RecordUnscaledFont(UnscaledFont* aUnscaledFont,
157                                        std::ostream* aOutput) {
158   RecordUnscaledFontImpl(aUnscaledFont, *aOutput);
159 }
160 
RecordUnscaledFont(UnscaledFont * aUnscaledFont,MemStream & aOutput)161 void RecordedEvent::RecordUnscaledFont(UnscaledFont* aUnscaledFont,
162                                        MemStream& aOutput) {
163   RecordUnscaledFontImpl(aUnscaledFont, aOutput);
164 }
165 
CreateDrawTarget(ReferencePtr aRefPtr,const IntSize & aSize,SurfaceFormat aFormat)166 already_AddRefed<DrawTarget> Translator::CreateDrawTarget(
167     ReferencePtr aRefPtr, const IntSize& aSize, SurfaceFormat aFormat) {
168   RefPtr<DrawTarget> newDT =
169       GetReferenceDrawTarget()->CreateSimilarDrawTarget(aSize, aFormat);
170   AddDrawTarget(aRefPtr, newDT);
171   return newDT.forget();
172 }
173 
DrawDependentSurface(ReferencePtr aDrawTarget,uint64_t aKey,const Rect & aRect)174 void Translator::DrawDependentSurface(ReferencePtr aDrawTarget, uint64_t aKey,
175                                       const Rect& aRect) {
176   if (!mDependentSurfaces) {
177     return;
178   }
179 
180   DrawTarget* dt = LookupDrawTarget(aDrawTarget);
181   if (!dt) {
182     return;
183   }
184 
185   RefPtr<RecordedDependentSurface> recordedSurface =
186       mDependentSurfaces->Get(aKey);
187   if (!recordedSurface) {
188     return;
189   }
190 
191   dt->PushClipRect(aRect);
192 
193   // Construct a new translator, so we can recurse into translating this
194   // sub-recording into the same DT. Set an initial transform for the
195   // translator, so that all commands get moved into the rect we want to draw.
196   Matrix transform = dt->GetTransform();
197   transform.PreTranslate(aRect.TopLeft());
198   InlineTranslator translator(dt, nullptr);
199   translator.SetReferenceDrawTargetTransform(transform);
200 
201   translator.SetDependentSurfaces(mDependentSurfaces);
202   translator.TranslateRecording((char*)recordedSurface->mRecording.mData,
203                                 recordedSurface->mRecording.mLen);
204 
205   dt->PopClip();
206 }
207 
208 }  // namespace gfx
209 }  // namespace mozilla
210