• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkCanvas.h"
9 #include "SkDeduper.h"
10 #include "SkImageDeserializer.h"
11 #include "SkPicture.h"
12 #include "SkPictureRecorder.h"
13 #include "SkPipe.h"
14 #include "SkPipeFormat.h"
15 #include "SkReadBuffer.h"
16 #include "SkRefSet.h"
17 #include "SkRSXform.h"
18 #include "SkTextBlob.h"
19 #include "SkTypeface.h"
20 #include "SkVertices.h"
21 
22 class SkPipeReader;
23 
24 static bool do_playback(SkPipeReader& reader, SkCanvas* canvas, int* endPictureIndex = nullptr);
25 
26 ///////////////////////////////////////////////////////////////////////////////////////////////////
27 
28 class SkPipeInflator : public SkInflator {
29 public:
SkPipeInflator(SkRefSet<SkImage> * images,SkRefSet<SkPicture> * pictures,SkRefSet<SkTypeface> * typefaces,SkTDArray<SkFlattenable::Factory> * factories,SkTypefaceDeserializer * tfd,SkImageDeserializer * imd)30     SkPipeInflator(SkRefSet<SkImage>* images, SkRefSet<SkPicture>* pictures,
31                    SkRefSet<SkTypeface>* typefaces, SkTDArray<SkFlattenable::Factory>* factories,
32                    SkTypefaceDeserializer* tfd, SkImageDeserializer* imd)
33         : fImages(images)
34         , fPictures(pictures)
35         , fTypefaces(typefaces)
36         , fFactories(factories)
37         , fTFDeserializer(tfd)
38         , fIMDeserializer(imd)
39     {}
40 
getImage(int index)41     SkImage* getImage(int index) override {
42         return index ? fImages->get(index - 1) : nullptr;
43     }
getPicture(int index)44     SkPicture* getPicture(int index) override {
45         return index ? fPictures->get(index - 1) : nullptr;
46     }
getTypeface(int index)47     SkTypeface* getTypeface(int index) override {
48         return fTypefaces->get(index - 1);
49     }
getFactory(int index)50     SkFlattenable::Factory getFactory(int index) override {
51         return index ? fFactories->getAt(index - 1) : nullptr;
52     }
53 
setImage(int index,SkImage * img)54     bool setImage(int index, SkImage* img) {
55         return fImages->set(index - 1, img);
56     }
setPicture(int index,SkPicture * pic)57     bool setPicture(int index, SkPicture* pic) {
58         return fPictures->set(index - 1, pic);
59     }
setTypeface(int index,SkTypeface * face)60     bool setTypeface(int index, SkTypeface* face) {
61         return fTypefaces->set(index - 1, face);
62     }
setFactory(int index,SkFlattenable::Factory factory)63     bool setFactory(int index, SkFlattenable::Factory factory) {
64         SkASSERT(index > 0);
65         SkASSERT(factory);
66         index -= 1;
67         if ((unsigned)index < (unsigned)fFactories->count()) {
68             (*fFactories)[index] = factory;
69             return true;
70         }
71         if (fFactories->count() == index) {
72             *fFactories->append() = factory;
73             return true;
74         }
75         SkDebugf("setFactory: index [%d] out of range %d\n", index, fFactories->count());
76         return false;
77     }
78 
setTypefaceDeserializer(SkTypefaceDeserializer * tfd)79     void setTypefaceDeserializer(SkTypefaceDeserializer* tfd) {
80         fTFDeserializer = tfd;
81     }
82 
setImageDeserializer(SkImageDeserializer * imd)83     void setImageDeserializer(SkImageDeserializer* imd) {
84         fIMDeserializer = imd;
85     }
86 
87     sk_sp<SkTypeface> makeTypeface(const void* data, size_t size);
88     sk_sp<SkImage> makeImage(const sk_sp<SkData>&);
89 
90 private:
91     SkRefSet<SkImage>*                  fImages;
92     SkRefSet<SkPicture>*                fPictures;
93     SkRefSet<SkTypeface>*               fTypefaces;
94     SkTDArray<SkFlattenable::Factory>*  fFactories;
95 
96     SkTypefaceDeserializer*             fTFDeserializer;
97     SkImageDeserializer*                fIMDeserializer;
98 };
99 
100 ///////////////////////////////////////////////////////////////////////////////////////////////////
101 
skip(SkReadBuffer & reader,int count=1)102 template <typename T> const T* skip(SkReadBuffer& reader, int count = 1) {
103     return (const T*)reader.skip(count * sizeof(T));
104 }
105 
read_rrect(SkReadBuffer & reader)106 static SkRRect read_rrect(SkReadBuffer& reader) {
107     SkRRect rrect;
108     rrect.readFromMemory(reader.skip(SkRRect::kSizeInMemory), SkRRect::kSizeInMemory);
109     return rrect;
110 }
111 
read_sparse_matrix(SkReadBuffer & reader,SkMatrix::TypeMask tm)112 static SkMatrix read_sparse_matrix(SkReadBuffer& reader, SkMatrix::TypeMask tm) {
113     SkMatrix matrix;
114     matrix.reset();
115 
116     if (tm & SkMatrix::kPerspective_Mask) {
117         matrix.set9(skip<SkScalar>(reader, 9));
118     } else if (tm & SkMatrix::kAffine_Mask) {
119         const SkScalar* tmp = skip<SkScalar>(reader, 6);
120         matrix[SkMatrix::kMScaleX] = tmp[0];
121         matrix[SkMatrix::kMSkewX]  = tmp[1];
122         matrix[SkMatrix::kMTransX] = tmp[2];
123         matrix[SkMatrix::kMScaleY] = tmp[3];
124         matrix[SkMatrix::kMSkewY]  = tmp[4];
125         matrix[SkMatrix::kMTransY] = tmp[5];
126     } else if (tm & SkMatrix::kScale_Mask) {
127         const SkScalar* tmp = skip<SkScalar>(reader, 4);
128         matrix[SkMatrix::kMScaleX] = tmp[0];
129         matrix[SkMatrix::kMTransX] = tmp[1];
130         matrix[SkMatrix::kMScaleY] = tmp[2];
131         matrix[SkMatrix::kMTransY] = tmp[3];
132     } else if (tm & SkMatrix::kTranslate_Mask) {
133         const SkScalar* tmp = skip<SkScalar>(reader, 2);
134         matrix[SkMatrix::kMTransX] = tmp[0];
135         matrix[SkMatrix::kMTransY] = tmp[1];
136     }
137     // else read nothing for Identity
138     return matrix;
139 }
140 
141 ///////////////////////////////////////////////////////////////////////////////////////////////////
142 
143 #define CHECK_SET_SCALAR(Field)                 \
144     do { if (nondef & k##Field##_NonDef) {      \
145         paint.set##Field(reader.readScalar());  \
146     }} while (0)
147 
148 #define CHECK_SET_FLATTENABLE(Field)            \
149     do { if (nondef & k##Field##_NonDef) {      \
150         paint.set##Field(reader.read##Field()); \
151     }} while (0)
152 
153 /*
154  *  Header:
155  *      paint flags     : 32
156  *      non_def bits    : 16
157  *      xfermode enum   : 8
158  *      pad zeros       : 8
159  */
read_paint(SkReadBuffer & reader)160 static SkPaint read_paint(SkReadBuffer& reader) {
161     SkPaint paint;
162 
163     uint32_t packedFlags = reader.read32();
164     uint32_t extra = reader.read32();
165     unsigned nondef = extra >> 16;
166     paint.setBlendMode(SkBlendMode((extra >> 8) & 0xFF));
167     SkASSERT((extra & 0xFF) == 0);  // zero pad byte
168 
169     packedFlags >>= 2;  // currently unused
170     paint.setTextEncoding((SkPaint::TextEncoding)(packedFlags & 3));    packedFlags >>= 2;
171     paint.setTextAlign((SkPaint::Align)(packedFlags & 3));              packedFlags >>= 2;
172     paint.setHinting((SkPaint::Hinting)(packedFlags & 3));              packedFlags >>= 2;
173     paint.setStrokeJoin((SkPaint::Join)(packedFlags & 3));              packedFlags >>= 2;
174     paint.setStrokeCap((SkPaint::Cap)(packedFlags & 3));                packedFlags >>= 2;
175     paint.setStyle((SkPaint::Style)(packedFlags & 3));                  packedFlags >>= 2;
176     paint.setFilterQuality((SkFilterQuality)(packedFlags & 3));         packedFlags >>= 2;
177     paint.setFlags(packedFlags);
178 
179     CHECK_SET_SCALAR(TextSize);
180     CHECK_SET_SCALAR(TextScaleX);
181     CHECK_SET_SCALAR(TextSkewX);
182     CHECK_SET_SCALAR(StrokeWidth);
183     CHECK_SET_SCALAR(StrokeMiter);
184 
185     if (nondef & kColor_NonDef) {
186         paint.setColor(reader.read32());
187     }
188 
189     CHECK_SET_FLATTENABLE(Typeface);
190     CHECK_SET_FLATTENABLE(PathEffect);
191     CHECK_SET_FLATTENABLE(Shader);
192     CHECK_SET_FLATTENABLE(MaskFilter);
193     CHECK_SET_FLATTENABLE(ColorFilter);
194     CHECK_SET_FLATTENABLE(Rasterizer);
195     CHECK_SET_FLATTENABLE(ImageFilter);
196     CHECK_SET_FLATTENABLE(DrawLooper);
197 
198     return paint;
199 }
200 
201 class SkPipeReader : public SkReadBuffer {
202 public:
SkPipeReader(SkPipeDeserializer * sink,const void * data,size_t size)203     SkPipeReader(SkPipeDeserializer* sink, const void* data, size_t size)
204     : SkReadBuffer(data, size)
205     , fSink(sink)
206     {}
207 
208     SkPipeDeserializer* fSink;
209 
findFactory(const char name[])210     SkFlattenable::Factory findFactory(const char name[]) {
211         SkFlattenable::Factory factory;
212         // Check if a custom Factory has been specified for this flattenable.
213         if (!(factory = this->getCustomFactory(SkString(name)))) {
214             // If there is no custom Factory, check for a default.
215             factory = SkFlattenable::NameToFactory(name);
216         }
217         return factory;
218     }
219 
readPaint(SkPaint * paint)220     void readPaint(SkPaint* paint) override {
221         *paint = read_paint(*this);
222     }
223 };
224 
225 ///////////////////////////////////////////////////////////////////////////////////////////////////
226 
227 typedef void (*SkPipeHandler)(SkPipeReader&, uint32_t packedVerb, SkCanvas*);
228 
save_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)229 static void save_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
230     SkASSERT(SkPipeVerb::kSave == unpack_verb(packedVerb));
231     canvas->save();
232 }
233 
saveLayer_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)234 static void saveLayer_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
235     SkASSERT(SkPipeVerb::kSaveLayer == unpack_verb(packedVerb));
236     unsigned extra = unpack_verb_extra(packedVerb);
237     const SkRect* bounds = (extra & kHasBounds_SaveLayerMask) ? skip<SkRect>(reader) : nullptr;
238     SkPaint paintStorage, *paint = nullptr;
239     if (extra & kHasPaint_SaveLayerMask) {
240         paintStorage = read_paint(reader);
241         paint = &paintStorage;
242     }
243     sk_sp<SkImageFilter> backdrop;
244     if (extra & kHasBackdrop_SaveLayerMask) {
245         backdrop = reader.readImageFilter();
246     }
247     sk_sp<SkImage> clipMask;
248     if (extra & kHasClipMask_SaveLayerMask) {
249         clipMask = reader.readImage();
250     }
251     SkMatrix clipMatrix;
252     if (extra & kHasClipMatrix_SaveLayerMask) {
253         reader.readMatrix(&clipMatrix);
254     }
255     SkCanvas::SaveLayerFlags flags = (SkCanvas::SaveLayerFlags)(extra & kFlags_SaveLayerMask);
256 
257     // unremap this wacky flag
258     if (extra & kDontClipToLayer_SaveLayerMask) {
259         flags |= (1 << 31);//SkCanvas::kDontClipToLayer_PrivateSaveLayerFlag;
260     }
261 
262     canvas->saveLayer(SkCanvas::SaveLayerRec(bounds, paint, backdrop.get(), clipMask.get(),
263                       (extra & kHasClipMatrix_SaveLayerMask) ? &clipMatrix : nullptr, flags));
264 }
265 
restore_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)266 static void restore_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
267     SkASSERT(SkPipeVerb::kRestore == unpack_verb(packedVerb));
268     canvas->restore();
269 }
270 
concat_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)271 static void concat_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
272     SkASSERT(SkPipeVerb::kConcat == unpack_verb(packedVerb));
273     SkMatrix::TypeMask tm = (SkMatrix::TypeMask)(packedVerb & kTypeMask_ConcatMask);
274     const SkMatrix matrix = read_sparse_matrix(reader, tm);
275     if (packedVerb & kSetMatrix_ConcatMask) {
276         canvas->setMatrix(matrix);
277     } else {
278         canvas->concat(matrix);
279     }
280 }
281 
clipRect_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)282 static void clipRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
283     SkASSERT(SkPipeVerb::kClipRect == unpack_verb(packedVerb));
284     SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1);
285     bool isAA = unpack_verb_extra(packedVerb) & 1;
286     canvas->clipRect(*skip<SkRect>(reader), op, isAA);
287 }
288 
clipRRect_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)289 static void clipRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
290     SkASSERT(SkPipeVerb::kClipRRect == unpack_verb(packedVerb));
291     SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1);
292     bool isAA = unpack_verb_extra(packedVerb) & 1;
293     canvas->clipRRect(read_rrect(reader), op, isAA);
294 }
295 
clipPath_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)296 static void clipPath_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
297     SkASSERT(SkPipeVerb::kClipPath == unpack_verb(packedVerb));
298     SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1);
299     bool isAA = unpack_verb_extra(packedVerb) & 1;
300     SkPath path;
301     reader.readPath(&path);
302     canvas->clipPath(path, op, isAA);
303 }
304 
clipRegion_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)305 static void clipRegion_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
306     SkASSERT(SkPipeVerb::kClipRegion == unpack_verb(packedVerb));
307     SkClipOp op = (SkClipOp)(unpack_verb_extra(packedVerb) >> 1);
308     SkRegion region;
309     reader.readRegion(&region);
310     canvas->clipRegion(region, op);
311 }
312 
drawArc_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)313 static void drawArc_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
314     SkASSERT(SkPipeVerb::kDrawArc == unpack_verb(packedVerb));
315     const bool useCenter = (bool)(unpack_verb_extra(packedVerb) & 1);
316     const SkScalar* scalars = skip<SkScalar>(reader, 6);    // bounds[0..3], start[4], sweep[5]
317     const SkRect* bounds = (const SkRect*)scalars;
318     canvas->drawArc(*bounds, scalars[4], scalars[5], useCenter, read_paint(reader));
319 }
320 
drawAtlas_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)321 static void drawAtlas_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
322     SkASSERT(SkPipeVerb::kDrawAtlas == unpack_verb(packedVerb));
323     SkBlendMode mode = (SkBlendMode)(packedVerb & kMode_DrawAtlasMask);
324     sk_sp<SkImage> image(reader.readImage());
325     int count = reader.read32();
326     const SkRSXform* xform = skip<SkRSXform>(reader, count);
327     const SkRect* rect = skip<SkRect>(reader, count);
328     const SkColor* color = nullptr;
329     if (packedVerb & kHasColors_DrawAtlasMask) {
330         color = skip<SkColor>(reader, count);
331     }
332     const SkRect* cull = nullptr;
333     if (packedVerb & kHasCull_DrawAtlasMask) {
334         cull = skip<SkRect>(reader);
335     }
336     SkPaint paintStorage, *paint = nullptr;
337     if (packedVerb & kHasPaint_DrawAtlasMask) {
338         paintStorage = read_paint(reader);
339         paint = &paintStorage;
340     }
341     canvas->drawAtlas(image, xform, rect, color, count, mode, cull, paint);
342 }
343 
drawDRRect_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)344 static void drawDRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
345     SkASSERT(SkPipeVerb::kDrawDRRect == unpack_verb(packedVerb));
346     const SkRRect outer = read_rrect(reader);
347     const SkRRect inner = read_rrect(reader);
348     canvas->drawDRRect(outer, inner, read_paint(reader));
349 }
350 
drawText_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)351 static void drawText_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
352     SkASSERT(SkPipeVerb::kDrawText == unpack_verb(packedVerb));
353     uint32_t len = unpack_verb_extra(packedVerb);
354     if (0 == len) {
355         len = reader.read32();
356     }
357     const void* text = reader.skip(SkAlign4(len));
358     SkScalar x = reader.readScalar();
359     SkScalar y = reader.readScalar();
360     canvas->drawText(text, len, x, y, read_paint(reader));
361 }
362 
drawPosText_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)363 static void drawPosText_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
364     SkASSERT(SkPipeVerb::kDrawPosText == unpack_verb(packedVerb));
365     uint32_t len = unpack_verb_extra(packedVerb);
366     if (0 == len) {
367         len = reader.read32();
368     }
369     const void* text = reader.skip(SkAlign4(len));
370     int count = reader.read32();
371     const SkPoint* pos = skip<SkPoint>(reader, count);
372     SkPaint paint = read_paint(reader);
373     SkASSERT(paint.countText(text, len) == count);
374     canvas->drawPosText(text, len, pos, paint);
375 }
376 
drawPosTextH_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)377 static void drawPosTextH_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
378     SkASSERT(SkPipeVerb::kDrawPosTextH == unpack_verb(packedVerb));
379     uint32_t len = unpack_verb_extra(packedVerb);
380     if (0 == len) {
381         len = reader.read32();
382     }
383     const void* text = reader.skip(SkAlign4(len));
384     int count = reader.read32();
385     const SkScalar* xpos = skip<SkScalar>(reader, count);
386     SkScalar constY = reader.readScalar();
387     SkPaint paint = read_paint(reader);
388     SkASSERT(paint.countText(text, len) == count);
389     canvas->drawPosTextH(text, len, xpos, constY, paint);
390 }
391 
drawTextOnPath_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)392 static void drawTextOnPath_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
393     SkASSERT(SkPipeVerb::kDrawTextOnPath == unpack_verb(packedVerb));
394     uint32_t byteLength = packedVerb & kTextLength_DrawTextOnPathMask;
395     SkMatrix::TypeMask tm = (SkMatrix::TypeMask)
396             ((packedVerb & kMatrixType_DrawTextOnPathMask) >> kMatrixType_DrawTextOnPathShift);
397 
398     if (0 == byteLength) {
399         byteLength = reader.read32();
400     }
401     const void* text = reader.skip(SkAlign4(byteLength));
402     SkPath path;
403     reader.readPath(&path);
404     const SkMatrix* matrix = nullptr;
405     SkMatrix matrixStorage;
406     if (tm != SkMatrix::kIdentity_Mask) {
407         matrixStorage = read_sparse_matrix(reader, tm);
408         matrix = &matrixStorage;
409     }
410     canvas->drawTextOnPath(text, byteLength, path, matrix, read_paint(reader));
411 }
412 
drawTextBlob_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)413 static void drawTextBlob_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
414     sk_sp<SkTextBlob> tb = SkTextBlob::MakeFromBuffer(reader);
415     SkScalar x = reader.readScalar();
416     SkScalar y = reader.readScalar();
417     canvas->drawTextBlob(tb, x, y, read_paint(reader));
418 }
419 
drawTextRSXform_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)420 static void drawTextRSXform_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
421     SkASSERT(SkPipeVerb::kDrawTextRSXform == unpack_verb(packedVerb));
422     uint32_t len = unpack_verb_extra(packedVerb) >> 1;
423     if (0 == len) {
424         len = reader.read32();
425     }
426     const void* text = reader.skip(SkAlign4(len));
427     int count = reader.read32();
428     const SkRSXform* xform = skip<SkRSXform>(reader, count);
429     const SkRect* cull = (packedVerb & 1) ? skip<SkRect>(reader) : nullptr;
430     SkPaint paint = read_paint(reader);
431     SkASSERT(paint.countText(text, len) == count);
432     canvas->drawTextRSXform(text, len, xform, cull, paint);
433 }
434 
drawPatch_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)435 static void drawPatch_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
436     SkASSERT(SkPipeVerb::kDrawPatch == unpack_verb(packedVerb));
437     const SkColor* colors = nullptr;
438     const SkPoint* tex = nullptr;
439     const SkPoint* cubics = skip<SkPoint>(reader, 12);
440     if (packedVerb & kHasColors_DrawPatchExtraMask) {
441         colors = skip<SkColor>(reader, 4);
442     }
443     if (packedVerb & kHasTexture_DrawPatchExtraMask) {
444         tex = skip<SkPoint>(reader, 4);
445     }
446     SkBlendMode mode = (SkBlendMode)(packedVerb & kModeEnum_DrawPatchExtraMask);
447     canvas->drawPatch(cubics, colors, tex, mode, read_paint(reader));
448 }
449 
drawPaint_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)450 static void drawPaint_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
451     SkASSERT(SkPipeVerb::kDrawPaint == unpack_verb(packedVerb));
452     canvas->drawPaint(read_paint(reader));
453 }
454 
drawRect_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)455 static void drawRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
456     SkASSERT(SkPipeVerb::kDrawRect == unpack_verb(packedVerb));
457     const SkRect* rect = skip<SkRect>(reader);
458     canvas->drawRect(*rect, read_paint(reader));
459 }
460 
drawRegion_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)461 static void drawRegion_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
462     SkASSERT(SkPipeVerb::kDrawRegion == unpack_verb(packedVerb));
463     size_t size = unpack_verb_extra(packedVerb);
464     if (0 == size) {
465         size = reader.read32();
466     }
467     SkRegion region;
468     region.readFromMemory(skip<char>(reader, SkAlign4(size)), size);
469     canvas->drawRegion(region, read_paint(reader));
470 }
471 
drawOval_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)472 static void drawOval_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
473     SkASSERT(SkPipeVerb::kDrawOval == unpack_verb(packedVerb));
474     const SkRect* rect = skip<SkRect>(reader);
475     canvas->drawOval(*rect, read_paint(reader));
476 }
477 
drawRRect_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)478 static void drawRRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
479     SkASSERT(SkPipeVerb::kDrawRRect == unpack_verb(packedVerb));
480     SkRRect rrect = read_rrect(reader);
481     canvas->drawRRect(rrect, read_paint(reader));
482 }
483 
drawPath_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)484 static void drawPath_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
485     SkASSERT(SkPipeVerb::kDrawPath == unpack_verb(packedVerb));
486     SkPath path;
487     reader.readPath(&path);
488     canvas->drawPath(path, read_paint(reader));
489 }
490 
drawPoints_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)491 static void drawPoints_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
492     SkASSERT(SkPipeVerb::kDrawPoints == unpack_verb(packedVerb));
493     SkCanvas::PointMode mode = (SkCanvas::PointMode)unpack_verb_extra(packedVerb);
494     int count = reader.read32();
495     const SkPoint* points = skip<SkPoint>(reader, count);
496     canvas->drawPoints(mode, count, points, read_paint(reader));
497 }
498 
drawImage_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)499 static void drawImage_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
500     SkASSERT(SkPipeVerb::kDrawImage == unpack_verb(packedVerb));
501     sk_sp<SkImage> image(reader.readImage());
502     SkScalar x = reader.readScalar();
503     SkScalar y = reader.readScalar();
504     SkPaint paintStorage, *paint = nullptr;
505     if (packedVerb & kHasPaint_DrawImageMask) {
506         paintStorage = read_paint(reader);
507         paint = &paintStorage;
508     }
509     canvas->drawImage(image, x, y, paint);
510 }
511 
drawImageRect_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)512 static void drawImageRect_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
513     SkASSERT(SkPipeVerb::kDrawImageRect == unpack_verb(packedVerb));
514     sk_sp<SkImage> image(reader.readImage());
515     SkCanvas::SrcRectConstraint constraint =
516             (SkCanvas::SrcRectConstraint)(packedVerb & kConstraint_DrawImageRectMask);
517     const SkRect* src = (packedVerb & kHasSrcRect_DrawImageRectMask) ?
518                         skip<SkRect>(reader) : nullptr;
519     const SkRect* dst = skip<SkRect>(reader);
520     SkPaint paintStorage, *paint = nullptr;
521     if (packedVerb & kHasPaint_DrawImageRectMask) {
522         paintStorage = read_paint(reader);
523         paint = &paintStorage;
524     }
525     if (src) {
526         canvas->drawImageRect(image, *src, *dst, paint, constraint);
527     } else {
528         canvas->drawImageRect(image, *dst, paint);
529     }
530 }
531 
drawImageNine_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)532 static void drawImageNine_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
533     SkASSERT(SkPipeVerb::kDrawImageNine == unpack_verb(packedVerb));
534     sk_sp<SkImage> image(reader.readImage());
535     const SkIRect* center = skip<SkIRect>(reader);
536     const SkRect* dst = skip<SkRect>(reader);
537     SkPaint paintStorage, *paint = nullptr;
538     if (packedVerb & kHasPaint_DrawImageNineMask) {
539         paintStorage = read_paint(reader);
540         paint = &paintStorage;
541     }
542     canvas->drawImageNine(image, *center, *dst, paint);
543 }
544 
drawImageLattice_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)545 static void drawImageLattice_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
546     SkASSERT(SkPipeVerb::kDrawImageLattice == unpack_verb(packedVerb));
547     sk_sp<SkImage> image(reader.readImage());
548 
549     SkCanvas::Lattice lattice;
550     lattice.fXCount = (packedVerb >> kXCount_DrawImageLatticeShift) & kCount_DrawImageLatticeMask;
551     if (lattice.fXCount == kCount_DrawImageLatticeMask) {
552         lattice.fXCount = reader.read32();
553     }
554     lattice.fYCount = (packedVerb >> kXCount_DrawImageLatticeShift) & kCount_DrawImageLatticeMask;
555     if (lattice.fYCount == kCount_DrawImageLatticeMask) {
556         lattice.fYCount = reader.read32();
557     }
558     lattice.fXDivs = skip<int32_t>(reader, lattice.fXCount);
559     lattice.fYDivs = skip<int32_t>(reader, lattice.fYCount);
560     if (packedVerb & kHasFlags_DrawImageLatticeMask) {
561         int32_t count = (lattice.fXCount + 1) * (lattice.fYCount + 1);
562         SkASSERT(count > 0);
563         lattice.fFlags = skip<SkCanvas::Lattice::Flags>(reader, SkAlign4(count));
564     } else {
565         lattice.fFlags = nullptr;
566     }
567     lattice.fBounds = skip<SkIRect>(reader);
568     const SkRect* dst = skip<SkRect>(reader);
569 
570     SkPaint paintStorage, *paint = nullptr;
571     if (packedVerb & kHasPaint_DrawImageLatticeMask) {
572         paintStorage = read_paint(reader);
573         paint = &paintStorage;
574     }
575     canvas->drawImageLattice(image.get(), lattice, *dst, paint);
576 }
577 
drawVertices_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)578 static void drawVertices_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
579     SkASSERT(SkPipeVerb::kDrawVertices == unpack_verb(packedVerb));
580     SkBlendMode bmode = (SkBlendMode)unpack_verb_extra(packedVerb);
581     sk_sp<SkData> data = reader.readByteArrayAsData();
582     canvas->drawVertices(SkVertices::Decode(data->data(), data->size()), bmode, read_paint(reader));
583 }
584 
drawPicture_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)585 static void drawPicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
586     SkASSERT(SkPipeVerb::kDrawPicture == unpack_verb(packedVerb));
587     unsigned extra = unpack_verb_extra(packedVerb);
588     int index = extra & kIndex_ObjectDefinitionMask;
589     SkPicture* pic = reader.getInflator()->getPicture(index);
590     SkMatrix matrixStorage, *matrix = nullptr;
591     SkPaint paintStorage, *paint = nullptr;
592     if (extra & kHasMatrix_DrawPictureExtra) {
593         reader.readMatrix(&matrixStorage);
594         matrix = &matrixStorage;
595     }
596     if (extra & kHasPaint_DrawPictureExtra) {
597         paintStorage = read_paint(reader);
598         paint = &paintStorage;
599     }
600     canvas->drawPicture(pic, matrix, paint);
601 }
602 
drawAnnotation_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)603 static void drawAnnotation_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
604     SkASSERT(SkPipeVerb::kDrawAnnotation == unpack_verb(packedVerb));
605     const SkRect* rect = skip<SkRect>(reader);
606 
607     // len includes the key's trailing 0
608     uint32_t len = unpack_verb_extra(packedVerb) >> 1;
609     if (0 == len) {
610         len = reader.read32();
611     }
612     const char* key = skip<char>(reader, len);
613     sk_sp<SkData> data;
614     if (packedVerb & 1) {
615         uint32_t size = reader.read32();
616         data = SkData::MakeWithCopy(reader.skip(SkAlign4(size)), size);
617     }
618     canvas->drawAnnotation(*rect, key, data);
619 }
620 
621 #if 0
622         stream.write("skiacodc", 8);
623         stream.write32(pmap.width());
624         stream.write32(pmap.height());
625         stream.write16(pmap.colorType());
626         stream.write16(pmap.alphaType());
627         stream.write32(0);  // no colorspace for now
628         for (int y = 0; y < pmap.height(); ++y) {
629             stream.write(pmap.addr8(0, y), pmap.width());
630         }
631 #endif
632 
make_from_skiaimageformat(const void * encoded,size_t encodedSize)633 static sk_sp<SkImage> make_from_skiaimageformat(const void* encoded, size_t encodedSize) {
634     if (encodedSize < 24) {
635         return nullptr;
636     }
637 
638     SkMemoryStream stream(encoded, encodedSize);
639     char signature[8];
640     stream.read(signature, 8);
641     if (memcmp(signature, "skiaimgf", 8)) {
642         return nullptr;
643     }
644 
645     int width = stream.readU32();
646     int height = stream.readU32();
647     SkColorType ct = (SkColorType)stream.readU16();
648     SkAlphaType at = (SkAlphaType)stream.readU16();
649     SkASSERT(kAlpha_8_SkColorType == ct);
650 
651     SkDEBUGCODE(size_t colorSpaceSize =) stream.readU32();
652     SkASSERT(0 == colorSpaceSize);
653 
654     SkImageInfo info = SkImageInfo::Make(width, height, ct, at);
655     size_t size = width * height;
656     sk_sp<SkData> pixels = SkData::MakeUninitialized(size);
657     stream.read(pixels->writable_data(), size);
658     SkASSERT(encodedSize == SkAlign4(stream.getPosition()));
659     return SkImage::MakeRasterData(info, pixels, width);
660 }
661 
makeImage(const sk_sp<SkData> & data)662 sk_sp<SkImage> SkPipeInflator::makeImage(const sk_sp<SkData>& data) {
663     if (fIMDeserializer) {
664         return fIMDeserializer->makeFromData(data.get(), nullptr);
665     }
666     sk_sp<SkImage> image = make_from_skiaimageformat(data->data(), data->size());
667     if (!image) {
668         image = SkImage::MakeFromEncoded(data);
669     }
670     return image;
671 }
672 
673 
defineImage_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas *)674 static void defineImage_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas*) {
675     SkASSERT(SkPipeVerb::kDefineImage == unpack_verb(packedVerb));
676     SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator();
677     uint32_t extra = unpack_verb_extra(packedVerb);
678     int index = extra & kIndex_ObjectDefinitionMask;
679 
680     if (extra & kUndef_ObjectDefinitionMask) {
681         // zero-index means we are "forgetting" that cache entry
682         inflator->setImage(index, nullptr);
683     } else {
684         // we are defining a new image
685         sk_sp<SkData> data = reader.readByteArrayAsData();
686         sk_sp<SkImage> image = inflator->makeImage(data);
687         if (!image) {
688             SkDebugf("-- failed to decode\n");
689         }
690         inflator->setImage(index, image.get());
691     }
692 }
693 
makeTypeface(const void * data,size_t size)694 sk_sp<SkTypeface> SkPipeInflator::makeTypeface(const void* data, size_t size) {
695     if (fTFDeserializer) {
696         return fTFDeserializer->deserialize(data, size);
697     }
698     SkMemoryStream stream(data, size, false);
699     return SkTypeface::MakeDeserialize(&stream);
700 }
701 
defineTypeface_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)702 static void defineTypeface_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
703     SkASSERT(SkPipeVerb::kDefineTypeface == unpack_verb(packedVerb));
704     SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator();
705     uint32_t extra = unpack_verb_extra(packedVerb);
706     int index = extra & kIndex_ObjectDefinitionMask;
707 
708     if (extra & kUndef_ObjectDefinitionMask) {
709         // zero-index means we are "forgetting" that cache entry
710         inflator->setTypeface(index, nullptr);
711     } else {
712         // we are defining a new image
713         sk_sp<SkData> data = reader.readByteArrayAsData();
714         // TODO: seems like we could "peek" to see the array, and not need to copy it.
715         sk_sp<SkTypeface> tf = inflator->makeTypeface(data->data(), data->size());
716         inflator->setTypeface(index, tf.get());
717     }
718 }
719 
defineFactory_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)720 static void defineFactory_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
721     SkASSERT(SkPipeVerb::kDefineFactory == unpack_verb(packedVerb));
722     SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator();
723     uint32_t extra = unpack_verb_extra(packedVerb);
724     int index = extra >> kNameLength_DefineFactoryExtraBits;
725     size_t len = extra & kNameLength_DefineFactoryExtraMask;
726     // +1 for the trailing null char
727     const char* name = (const char*)reader.skip(SkAlign4(len + 1));
728     SkFlattenable::Factory factory = reader.findFactory(name);
729     if (factory) {
730         inflator->setFactory(index, factory);
731     }
732 }
733 
definePicture_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)734 static void definePicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
735     SkASSERT(SkPipeVerb::kDefinePicture == unpack_verb(packedVerb));
736     int deleteIndex = unpack_verb_extra(packedVerb);
737 
738     SkPipeInflator* inflator = (SkPipeInflator*)reader.getInflator();
739 
740     if (deleteIndex) {
741         inflator->setPicture(deleteIndex - 1, nullptr);
742     } else {
743         SkPictureRecorder recorder;
744         int pictureIndex = -1;  // invalid
745         const SkRect* cull = skip<SkRect>(reader);
746         do_playback(reader, recorder.beginRecording(*cull), &pictureIndex);
747         SkASSERT(pictureIndex > 0);
748         sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
749         inflator->setPicture(pictureIndex, picture.get());
750     }
751 }
752 
endPicture_handler(SkPipeReader & reader,uint32_t packedVerb,SkCanvas * canvas)753 static void endPicture_handler(SkPipeReader& reader, uint32_t packedVerb, SkCanvas* canvas) {
754     sk_throw();     // never call me
755 }
756 
757 ///////////////////////////////////////////////////////////////////////////////////////////////////
758 
759 struct HandlerRec {
760     SkPipeHandler   fProc;
761     const char*     fName;
762 };
763 
764 #define HANDLER(name)   { name##_handler, #name }
765 const HandlerRec gPipeHandlers[] = {
766     HANDLER(save),
767     HANDLER(saveLayer),
768     HANDLER(restore),
769     HANDLER(concat),
770 
771     HANDLER(clipRect),
772     HANDLER(clipRRect),
773     HANDLER(clipPath),
774     HANDLER(clipRegion),
775 
776     HANDLER(drawArc),
777     HANDLER(drawAtlas),
778     HANDLER(drawDRRect),
779     HANDLER(drawText),
780     HANDLER(drawPosText),
781     HANDLER(drawPosTextH),
782     HANDLER(drawRegion),
783     HANDLER(drawTextOnPath),
784     HANDLER(drawTextBlob),
785     HANDLER(drawTextRSXform),
786     HANDLER(drawPatch),
787     HANDLER(drawPaint),
788     HANDLER(drawPoints),
789     HANDLER(drawRect),
790     HANDLER(drawPath),
791     HANDLER(drawOval),
792     HANDLER(drawRRect),
793 
794     HANDLER(drawImage),
795     HANDLER(drawImageRect),
796     HANDLER(drawImageNine),
797     HANDLER(drawImageLattice),
798 
799     HANDLER(drawVertices),
800 
801     HANDLER(drawPicture),
802     HANDLER(drawAnnotation),
803 
804     HANDLER(defineImage),
805     HANDLER(defineTypeface),
806     HANDLER(defineFactory),
807     HANDLER(definePicture),
808     HANDLER(endPicture),        // handled special -- should never be called
809 };
810 #undef HANDLER
811 
812 ///////////////////////////////////////////////////////////////////////////////////////////////////
813 
814 class SkPipeDeserializer::Impl {
815 public:
816     SkRefSet<SkImage>                   fImages;
817     SkRefSet<SkPicture>                 fPictures;
818     SkRefSet<SkTypeface>                fTypefaces;
819     SkTDArray<SkFlattenable::Factory>   fFactories;
820 
821     SkTypefaceDeserializer*             fTFDeserializer = nullptr;
822     SkImageDeserializer*                fIMDeserializer = nullptr;
823 };
824 
SkPipeDeserializer()825 SkPipeDeserializer::SkPipeDeserializer() : fImpl(new Impl) {}
~SkPipeDeserializer()826 SkPipeDeserializer::~SkPipeDeserializer() {}
827 
setTypefaceDeserializer(SkTypefaceDeserializer * tfd)828 void SkPipeDeserializer::setTypefaceDeserializer(SkTypefaceDeserializer* tfd) {
829     fImpl->fTFDeserializer = tfd;
830 }
831 
setImageDeserializer(SkImageDeserializer * imd)832 void SkPipeDeserializer::setImageDeserializer(SkImageDeserializer* imd) {
833     fImpl->fIMDeserializer = imd;
834 }
835 
readImage(const void * data,size_t size)836 sk_sp<SkImage> SkPipeDeserializer::readImage(const void* data, size_t size) {
837     if (size < sizeof(uint32_t)) {
838         SkDebugf("-------- data length too short for readImage %d\n", size);
839         return nullptr;
840     }
841 
842     const uint32_t* ptr = (const uint32_t*)data;
843     uint32_t packedVerb = *ptr++;
844     size -= 4;
845 
846     if (SkPipeVerb::kDefineImage == unpack_verb(packedVerb)) {
847         SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures,
848                                 &fImpl->fTypefaces, &fImpl->fFactories,
849                                 fImpl->fTFDeserializer, fImpl->fIMDeserializer);
850         SkPipeReader reader(this, ptr, size);
851         reader.setInflator(&inflator);
852         defineImage_handler(reader, packedVerb, nullptr);
853         packedVerb = reader.read32();  // read the next verb
854     }
855     if (SkPipeVerb::kWriteImage != unpack_verb(packedVerb)) {
856         SkDebugf("-------- unexpected verb for readImage %d\n", unpack_verb(packedVerb));
857         return nullptr;
858     }
859     int index = unpack_verb_extra(packedVerb);
860     if (0 == index) {
861         return nullptr; // writer failed
862     }
863     return sk_ref_sp(fImpl->fImages.get(index - 1));
864 }
865 
readPicture(const void * data,size_t size)866 sk_sp<SkPicture> SkPipeDeserializer::readPicture(const void* data, size_t size) {
867     if (size < sizeof(uint32_t)) {
868         SkDebugf("-------- data length too short for readPicture %d\n", size);
869         return nullptr;
870     }
871 
872     const uint32_t* ptr = (const uint32_t*)data;
873     uint32_t packedVerb = *ptr++;
874     size -= 4;
875 
876     if (SkPipeVerb::kDefinePicture == unpack_verb(packedVerb)) {
877         SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures,
878                                 &fImpl->fTypefaces, &fImpl->fFactories,
879                                 fImpl->fTFDeserializer, fImpl->fIMDeserializer);
880         SkPipeReader reader(this, ptr, size);
881         reader.setInflator(&inflator);
882         definePicture_handler(reader, packedVerb, nullptr);
883         packedVerb = reader.read32();  // read the next verb
884     }
885     if (SkPipeVerb::kWritePicture != unpack_verb(packedVerb)) {
886         SkDebugf("-------- unexpected verb for readPicture %d\n", unpack_verb(packedVerb));
887         return nullptr;
888     }
889     int index = unpack_verb_extra(packedVerb);
890     if (0 == index) {
891         return nullptr; // writer failed
892     }
893     return sk_ref_sp(fImpl->fPictures.get(index - 1));
894 }
895 
do_playback(SkPipeReader & reader,SkCanvas * canvas,int * endPictureIndex)896 static bool do_playback(SkPipeReader& reader, SkCanvas* canvas, int* endPictureIndex) {
897     int indent = 0;
898 
899     const bool showEachVerb = false;
900     int counter = 0;
901     while (!reader.eof()) {
902         uint32_t prevOffset = reader.offset();
903         uint32_t packedVerb = reader.read32();
904         SkPipeVerb verb = unpack_verb(packedVerb);
905         if ((unsigned)verb >= SK_ARRAY_COUNT(gPipeHandlers)) {
906             SkDebugf("------- bad verb %d\n", verb);
907             return false;
908         }
909         if (SkPipeVerb::kRestore == verb) {
910             indent -= 1;
911             SkASSERT(indent >= 0);
912         }
913 
914         if (SkPipeVerb::kEndPicture == verb) {
915             if (endPictureIndex) {
916                 *endPictureIndex = unpack_verb_extra(packedVerb);
917             }
918             return true;
919         }
920         HandlerRec rec = gPipeHandlers[(unsigned)verb];
921         rec.fProc(reader, packedVerb, canvas);
922         if (showEachVerb) {
923             for (int i = 0; i < indent; ++i) {
924                 SkDebugf("    ");
925             }
926             SkDebugf("%d [%d] %s %d\n", prevOffset, counter++, rec.fName, reader.offset() - prevOffset);
927         }
928         if (!reader.isValid()) {
929             SkDebugf("-------- bad reader\n");
930             return false;
931         }
932 
933         switch (verb) {
934             case SkPipeVerb::kSave:
935             case SkPipeVerb::kSaveLayer:
936                 indent += 1;
937                 break;
938             default:
939                 break;
940         }
941     }
942     return true;
943 }
944 
playback(const void * data,size_t size,SkCanvas * canvas)945 bool SkPipeDeserializer::playback(const void* data, size_t size, SkCanvas* canvas) {
946     SkPipeInflator inflator(&fImpl->fImages, &fImpl->fPictures,
947                             &fImpl->fTypefaces, &fImpl->fFactories,
948                             fImpl->fTFDeserializer, fImpl->fIMDeserializer);
949     SkPipeReader reader(this, data, size);
950     reader.setInflator(&inflator);
951     return do_playback(reader, canvas);
952 }
953 
954