Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: src/pipe/SkPipeCanvas.cpp

Issue 2201323003: add pipecanvas (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: initial reader Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "SkPipeCanvas.h"
9 #include "SkPipeFormat.h"
10
11 #include "SkPathEffect.h"
12 #include "SkShader.h"
13 #include "SkColorFilter.h"
14 #include "SkImageFilter.h"
15 #include "SkMaskFilter.h"
16 #include "SkRasterizer.h"
17 #include "SkStream.h"
18
19 template <typename T> void write_rrect(T* writer, const SkRRect& rrect) {
20 char tmp[SkRRect::kSizeInMemory];
21 rrect.writeToMemory(tmp);
22 writer->write(tmp, SkRRect::kSizeInMemory);
23 }
24
25 template <typename T> void write_pad(T* writer, const void* buffer, size_t len) {
26 writer->write(buffer, len & ~3);
27 if (len & 3) {
28 const char* src = (const char*)buffer + (len & ~3);
29 len &= 3;
30
31 char tmp[4];
mtklein 2016/08/04 12:50:37 Or, uint32_t tmp = 0; memcpy(&tmp, src, len); wri
reed1 2016/08/04 13:18:41 Nice. Considered that, but got temporarily confuse
32 for (size_t i = 0; i < len; ++i) {
33 tmp[i] = src[i];
34 }
35 for (size_t i = len; i < 4; ++i) {
36 tmp[i] = 0;
37 }
38 writer->write(tmp, 4);
39 }
40 }
41
42 //////////////////////////////////////////////////////////////////////////////// ///////////////////
43
44 class ScopedWriter : public SkBinaryWriteBuffer {
45 public:
46 ScopedWriter(SkPipeCanvas*) : SkBinaryWriteBuffer(0) {}
mtklein 2016/08/04 12:50:37 This probably doesn't need to inherit from SkBinar
reed1 2016/08/04 13:18:41 Correct, just wanted a quickie so that syntactical
47 };
48
49 static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) {
50 const SkScalar kTextSize_Default = 12;
51 const SkScalar kTextScaleX_Default = 1;
52 const SkScalar kTextSkewX_Default = 0;
53 const SkScalar kStrokeWidth_Default = 0;
54 const SkScalar kStrokeMiter_Default = 4;
55 const SkColor kColor_Default = SK_ColorBLACK;
56
57 unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0;
58
59 if (kText_PaintUsage == usage) {
60 bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonD ef : 0);
61 bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextSize_NonD ef : 0);
mtklein 2016/08/04 12:50:37 I bet scale and skew stay default with a non-defau
reed1 2016/08/04 13:18:41 That's a typo, fixed.
62 bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSize_NonD ef : 0);
63 bits |= (paint.getTypeface() ? kTypeface_NonD ef : 0);
64 }
65
66 if (usage & (kText_PaintUsage | kGeometry_PaintUsage)) {
67 bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0);
68 bits |= (paint.getShader() ? kShader_NonDef : 0);
69 bits |= (paint.getRasterizer() ? kRasterizer_NonDef : 0);
70
71 if (paint.getStyle() != SkPaint::kFill_Style) {
72 bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWid th_NonDef : 0);
73 bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMit er_NonDef : 0);
74 }
75 }
76
77 bits |= (paint.getXfermode() ? kXfermode_NonDef : 0);
78 bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0);
79 bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0);
80 bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0);
81
82 return SkToU16(bits);
83 }
84
85 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align,
86 unsigned filter, unsigned caps, unsigned joins) {
87 SkASSERT(kFlags_BPF + kHint_BPF + kAlign_BPF + kFilter_BPF <= 32);
88
89 ASSERT_FITS_IN(flags, kFlags_BPF);
90 ASSERT_FITS_IN(hint, kHint_BPF);
91 ASSERT_FITS_IN(align, kAlign_BPF);
92 ASSERT_FITS_IN(filter, kFilter_BPF);
93 ASSERT_FITS_IN(caps, kCaps_BPF);
94 ASSERT_FITS_IN(joins, kJoins_BPF);
95
96 // left-align the fields of "known" size, and right-align the last (flatFlag s) so it can easly
97 // add more bits in the future.
98
99 uint32_t packed = 0;
100 int shift = 32;
101
102 shift -= kFlags_BPF; packed |= (flags << shift);
103 shift -= kHint_BPF; packed |= (hint << shift);
104 shift -= kAlign_BPF; packed |= (align << shift);
105 shift -= kFilter_BPF; packed |= (filter << shift);
106 shift -= kCaps_BPF; packed |= (caps << shift);
107 shift -= kJoins_BPF; packed |= (joins << shift);
108
109 return packed;
110 }
111
112 #define CHECK_WRITE_SCALAR(bit, code) \
mtklein 2016/08/04 12:50:37 Might help readability to pass nondef in too.
reed1 2016/08/04 13:18:41 ... and writer? I was sort of modeling other macro
mtklein 2016/08/04 15:13:23 The rule of thumb I try to stick to is that implic
113 do { if (nondef & (bit)) { writer.writeScalar(code); } } while (0)
114
115 #define CHECK_WRITE_FLATTENABLE(bit, code) \
116 do { if (nondef & (bit)) { \
117 SkFlattenable* f = code; \
118 SkASSERT(f != nullptr); \
119 writer.writeFlattenable(f); \
120 } } while (0)
121
122 /*
123 * Header:
124 * paint flags : 32
125 * non_def bits : 16
126 * xfermode enum : 8
127 * pad zeros : 8
128 */
129 static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, PaintUsage usage) {
130 uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting() ,
131 paint.getTextAlign(), paint.getFilte rQuality(),
132 paint.getStrokeCap(), paint.getStrok eJoin());
133 writer.write32(packedFlags);
134
135 unsigned nondef = compute_nondef(paint, usage);
136 SkXfermode::Mode mode;
137 if (SkXfermode::AsMode(paint.getXfermode(), &mode)) {
138 nondef &= ~kXfermode_NonDef; // don't need to store a pointer since w e have an enum
139 } else {
140 SkASSERT(nondef & kXfermode_NonDef);
141 mode = (SkXfermode::Mode)0;
142 }
143 const uint8_t pad = 0;
144 writer.write32((nondef << 16) | ((unsigned)mode << 8) | pad);
145
146 CHECK_WRITE_SCALAR(kTextSize_NonDef, paint.getTextSize());
147 CHECK_WRITE_SCALAR(kTextScaleX_NonDef, paint.getTextScaleX());
148 CHECK_WRITE_SCALAR(kTextSkewX_NonDef, paint.getTextSkewX());
149 CHECK_WRITE_SCALAR(kStrokeWidth_NonDef, paint.getStrokeWidth());
150 CHECK_WRITE_SCALAR(kStrokeMiter_NonDef, paint.getStrokeMiter());
151
152 if (nondef & kColor_NonDef) {
153 writer.write32(paint.getColor());
154 }
155 if (nondef & kTypeface_NonDef) {
156 }
157
158 CHECK_WRITE_FLATTENABLE(kPathEffect_NonDef, paint.getPathEffect());
159 CHECK_WRITE_FLATTENABLE(kShader_NonDef, paint.getShader());
160 CHECK_WRITE_FLATTENABLE(kXfermode_NonDef, paint.getXfermode());
161 CHECK_WRITE_FLATTENABLE(kMaskFilter_NonDef, paint.getMaskFilter());
162 CHECK_WRITE_FLATTENABLE(kColorFilter_NonDef, paint.getColorFilter());
163 CHECK_WRITE_FLATTENABLE(kRasterizer_NonDef, paint.getRasterizer());
164 CHECK_WRITE_FLATTENABLE(kImageFilter_NonDef, paint.getImageFilter());
165 }
166
167 //////////////////////////////////////////////////////////////////////////////// ///////////////////
168
169 SkPipeCanvas::SkPipeCanvas(int width, int height, SkWStream* stream)
170 : INHERITED(width, height)
171 , fStream(stream)
172 {}
173
174 SkPipeCanvas::~SkPipeCanvas() {}
175
176 void SkPipeCanvas::willSave() {
177 this->writeVerb(kSave_Verb);
mtklein 2016/08/04 12:50:37 We should probably funnel all verbs through the sa
reed1 2016/08/04 13:18:41 Done
178
179 this->INHERITED::willSave();
180 }
181
182 SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRe c& rec) {
183 this->INHERITED::getSaveLayerStrategy(rec);
184
185 return kNoLayer_SaveLayerStrategy;
186 }
187
188 void SkPipeCanvas::willRestore() {
189 this->writeVerb(kRestore_Verb);
190
191 this->INHERITED::willRestore();
192 }
193
194 void SkPipeCanvas::didConcat(const SkMatrix& matrix) {
195 SkMatrix::TypeMask tm = matrix.getType();
196 SkASSERT(tm != SkMatrix::kIdentity_Mask);
197 fStream->write32(pack_verb(kConcat_Verb, tm));
198
199 SkScalar tmp[9];
200 if (tm & SkMatrix::kPerspective_Mask) {
201 matrix.get9(tmp);
202 fStream->write(tmp, 9 * sizeof(SkScalar));
203 } else if (tm & SkMatrix::kAffine_Mask) {
204 tmp[0] = matrix[SkMatrix::kMScaleX];
205 tmp[1] = matrix[SkMatrix::kMSkewX];
206 tmp[2] = matrix[SkMatrix::kMTransX];
207 tmp[3] = matrix[SkMatrix::kMScaleY];
208 tmp[4] = matrix[SkMatrix::kMSkewY];
209 tmp[5] = matrix[SkMatrix::kMTransY];
210 fStream->write(tmp, 6 * sizeof(SkScalar));
211 } else if (tm & SkMatrix::kScale_Mask) {
212 tmp[0] = matrix[SkMatrix::kMScaleX];
213 tmp[1] = matrix[SkMatrix::kMTransX];
214 tmp[2] = matrix[SkMatrix::kMScaleY];
215 tmp[3] = matrix[SkMatrix::kMTransY];
216 fStream->write(tmp, 4 * sizeof(SkScalar));
217 } else if (tm & SkMatrix::kTranslate_Mask) {
218 tmp[0] = matrix[SkMatrix::kMTransX];
219 tmp[1] = matrix[SkMatrix::kMTransY];
220 fStream->write(tmp, 2 * sizeof(SkScalar));
221 }
222
223 this->INHERITED::didConcat(matrix);
224 }
225
226 void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) {
227 // Can we eliminate this?
228 this->INHERITED::didSetMatrix(matrix);
229 }
230
231 void SkPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
232 fStream->write32(pack_verb(kClipRect_Verb, ((unsigned)op << 1) | edgeStyle)) ;
mtklein 2016/08/04 12:50:37 static inline pack_clip(SkRegion::Op, ClipEdgeStyl
reed1 2016/08/04 13:18:41 Yea, there are lots of helpers like this I will wr
233 fStream->write(&rect, 4 * sizeof(SkScalar));
234
235 this->INHERITED::onClipRect(rect, op, edgeStyle);
236 }
237
238 void SkPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeSt yle edgeStyle) {
239 fStream->write32(pack_verb(kClipRRect_Verb, ((unsigned)op << 1) | edgeStyle) );
240 write_rrect(fStream, rrect);
241
242 this->INHERITED::onClipRRect(rrect, op, edgeStyle);
243 }
244
245 void SkPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
246 ScopedWriter writer(this);
247 writer.write32(pack_verb(kClipPath_Verb, ((unsigned)op << 1) | edgeStyle));
248 writer.writePath(path);
249
250 this->INHERITED::onClipPath(path, op, edgeStyle);
251 }
252
253 void SkPipeCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) {
254 ScopedWriter writer(this);
255 writer.write32(pack_verb(kClipRegion_Verb, (unsigned)op << 1));
256 writer.writeRegion(deviceRgn);
257
258 this->INHERITED::onClipRegion(deviceRgn, op);
259 }
260
261 //////////////////////////////////////////////////////////////////////////////// ///////////////////
262
263 void SkPipeCanvas::onDrawPaint(const SkPaint& paint) {
264 ScopedWriter writer(this);
265 writer.write32(pack_verb(kDrawPaint_Verb));
266 write_paint(writer, paint, kDrawPaint_PaintUsage);
267 }
268
269 void SkPipeCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[ ],
270 const SkPaint& paint) {
271 ScopedWriter writer(this);
272 writer.write32(pack_verb(kDrawPoints_Verb, mode));
273 writer.write32(SkToU32(count));
274 writer.write(pts, count * sizeof(SkPoint));
275 write_paint(writer, paint, kGeometry_PaintUsage);
276 }
277
278 void SkPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) {
279 ScopedWriter writer(this);
280 writer.write32(pack_verb(kDrawRect_Verb));
281 writer.write(&rect, sizeof(SkRect));
282 write_paint(writer, paint, kGeometry_PaintUsage);
283 }
284
285 void SkPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) {
286 ScopedWriter writer(this);
287 writer.write32(pack_verb(kDrawOval_Verb));
288 writer.write(&rect, sizeof(SkRect));
289 write_paint(writer, paint, kGeometry_PaintUsage);
290 }
291
292 void SkPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
293 ScopedWriter writer(this);
294 writer.write32(pack_verb(kDrawRRect_Verb));
295 write_rrect(&writer, rrect);
296 write_paint(writer, paint, kGeometry_PaintUsage);
297 }
298
299 void SkPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, cons t SkPaint& paint) {
300 ScopedWriter writer(this);
301 writer.write32(pack_verb(kDrawDRRect_Verb));
302 write_rrect(&writer, outer);
303 write_rrect(&writer, inner);
304 write_paint(writer, paint, kGeometry_PaintUsage);
305 }
306
307 void SkPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) {
308 ScopedWriter writer(this);
309 writer.write32(pack_verb(kDrawPath_Verb));
310 writer.writePath(path);
311 write_paint(writer, paint, kGeometry_PaintUsage);
312 }
313
314 //////////////////////////////////////////////////////////////////////////////// ///////////////////
315
316 static sk_sp<SkImage> make_from_bitmap(const SkBitmap& bitmap) {
317 // If we just "make" an image, it will force a CPU copy (if its mutable), on ly to have
318 // us then either find it in our cache, or compress and send it.
319 //
320 // Better could be to look it up in our cache first, and only create/compres s it if we have to.
321 //
322 // But for now, just do the dumb thing...
323 return SkImage::MakeFromBitmap(bitmap);
324 }
325
326 void SkPipeCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y,
327 const SkPaint* paint) {
328 sk_sp<SkImage> image = make_from_bitmap(bitmap);
329 if (image) {
330 this->onDrawImage(image.get(), x, y, paint);
331 }
332 }
333
334 void SkPipeCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, c onst SkRect& dst,
335 const SkPaint* paint, SrcRectConstraint cons traint) {
336 sk_sp<SkImage> image = make_from_bitmap(bitmap);
337 if (image) {
338 this->onDrawImageRect(image.get(), src, dst, paint, constraint);
339 }
340 }
341
342 void SkPipeCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& cente r,
343 const SkRect& dst, const SkPaint* paint) {
344 sk_sp<SkImage> image = make_from_bitmap(bitmap);
345 if (image) {
346 this->onDrawImageNine(image.get(), center, dst, paint);
347 }
348 }
349
350 void SkPipeCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top ,
351 const SkPaint* paint) {
352 ScopedWriter writer(this);
353 writer.write32(pack_verb(kDrawImage_Verb, paint != nullptr));
354 writer.writeImage(image);
355 writer.writeScalar(left);
356 writer.writeScalar(top);
357 if (paint) {
358 write_paint(writer, *paint, kImage_PaintUsage);
359 }
360 }
361
362 void SkPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, cons t SkRect& dst,
363 const SkPaint* paint, SrcRectConstraint const raint) {
364 ScopedWriter writer(this);
365 writer.write32(pack_verb(kDrawImageRect_Verb, ((src != nullptr) << 1) | (pai nt != nullptr)));
366 writer.writeImage(image);
367 if (src) {
368 writer.write(src, sizeof(*src));
369 }
370 writer.write(&dst, sizeof(dst));
371 if (paint) {
372 write_paint(writer, *paint, kImage_PaintUsage);
373 }
374 }
375
376 void SkPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst,
377 const SkPaint* paint) {
378 ScopedWriter writer(this);
379 writer.write32(pack_verb(kDrawImageNine_Verb, paint != nullptr));
380 writer.writeImage(image);
381 writer.write(&center, sizeof(center));
382 writer.write(&dst, sizeof(dst));
383 if (paint) {
384 write_paint(writer, *paint, kImage_PaintUsage);
385 }
386 }
387
388 //////////////////////////////////////////////////////////////////////////////// ///////////////////
389
390 void SkPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, S kScalar y,
391 const SkPaint& paint) {
392 SkASSERT(byteLength);
393
394 bool compact = fits_in(byteLength, 24);
395
396 ScopedWriter writer(this);
397 writer.write32(pack_verb(kDrawText_Verb, compact ? (unsigned)byteLength : 0) );
398 if (!compact) {
399 writer.write32(SkToU32(byteLength));
400 }
401 write_pad(&writer, text, byteLength);
402 writer.writeScalar(x);
403 writer.writeScalar(y);
404 write_paint(writer, paint, kText_PaintUsage);
405 }
406
407 void SkPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPo int pos[],
408 const SkPaint& paint) {
409 SkASSERT(byteLength);
410
411 bool compact = fits_in(byteLength, 24);
412
413 ScopedWriter writer(this);
414 writer.write32(pack_verb(kDrawText_Verb, compact ? (unsigned)byteLength : 0) );
415 if (!compact) {
416 writer.write32(SkToU32(byteLength));
417 }
418 write_pad(&writer, text, byteLength);
419 writer.writePointArray(pos, paint.countText(text, byteLength));
420 write_paint(writer, paint, kText_PaintUsage);
421 }
422
423 void SkPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkS calar xpos[],
424 SkScalar constY, const SkPaint& paint) {
425 SkASSERT(byteLength);
426
427 bool compact = fits_in(byteLength, 24);
428
429 ScopedWriter writer(this);
430 writer.write32(pack_verb(kDrawText_Verb, compact ? (unsigned)byteLength : 0) );
431 if (!compact) {
432 writer.write32(SkToU32(byteLength));
433 }
434 write_pad(&writer, text, byteLength);
435 writer.writeScalarArray(xpos, paint.countText(text, byteLength));
436 writer.writeScalar(constY);
437 write_paint(writer, paint, kText_PaintUsage);
438 }
439
440 void SkPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const S kPath& path,
441 const SkMatrix* matrix, const SkPaint& paint ) {
442 sk_throw();
443 }
444
445 void SkPipeCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[],
446 const SkRect* cull, const SkPaint& paint) {
447 sk_throw();
448 }
449
450 void SkPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y ,
451 const SkPaint &paint) {
452 sk_throw();
453 }
454
455 void SkPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matri x,
456 const SkPaint* paint) {
457 sk_throw();
458 }
459
460 void SkPipeCanvas::onDrawVertices(VertexMode vmode, int vertexCount,
461 const SkPoint vertices[], const SkPoint texs[] ,
462 const SkColor colors[], SkXfermode* xmode,
463 const uint16_t indices[], int indexCount,
464 const SkPaint& paint) {
465 sk_throw();
466 }
467
468 void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4] ,
469 const SkPoint texCoords[4], SkXfermode* xmode,
470 const SkPaint& paint) {
471 sk_throw();
472 }
473
474 void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData * data) {
475 const size_t len = strlen(key);
476 bool compact = fits_in(len, 24);
477 fStream->write32(pack_verb(kDrawAnnotation_Verb, compact ? (unsigned)len : 0 ));
478 if (!compact) {
479 fStream->write32(SkToU32(len));
480 }
481 write_pad(fStream, key, len);
482 if (data) {
483 fStream->write32(SkToU32(data->size()));
484 write_pad(fStream, data->data(), data->size());
485 } else {
486 fStream->write32(0);
487 }
488 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698