Chromium Code Reviews| OLD | NEW |
|---|---|
| (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 #include "SkPathEffect.h" | |
| 11 #include "SkShader.h" | |
| 12 #include "SkColorFilter.h" | |
| 13 #include "SkImageFilter.h" | |
| 14 #include "SkMaskFilter.h" | |
| 15 #include "SkRasterizer.h" | |
| 16 #include "SkRSXform.h" | |
| 17 #include "SkStream.h" | |
| 18 #include "SkTextBlob.h" | |
| 19 #include "SkTypeface.h" | |
| 20 | |
| 21 template <typename T> void write_rrect(T* writer, const SkRRect& rrect) { | |
| 22 char tmp[SkRRect::kSizeInMemory]; | |
| 23 rrect.writeToMemory(tmp); | |
| 24 writer->write(tmp, SkRRect::kSizeInMemory); | |
| 25 } | |
| 26 | |
| 27 template <typename T> void write_pad(T* writer, const void* buffer, size_t len) { | |
| 28 writer->write(buffer, len & ~3); | |
| 29 if (len & 3) { | |
| 30 const char* src = (const char*)buffer + (len & ~3); | |
| 31 len &= 3; | |
| 32 uint32_t tmp = 0; | |
| 33 memcpy(&tmp, src, len); | |
| 34 writer->write(&tmp, 4); | |
| 35 } | |
| 36 } | |
| 37 | |
| 38 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 39 | |
| 40 static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) { | |
| 41 const SkScalar kTextSize_Default = 12; | |
| 42 const SkScalar kTextScaleX_Default = 1; | |
| 43 const SkScalar kTextSkewX_Default = 0; | |
| 44 const SkScalar kStrokeWidth_Default = 0; | |
| 45 const SkScalar kStrokeMiter_Default = 4; | |
| 46 const SkColor kColor_Default = SK_ColorBLACK; | |
| 47 | |
| 48 unsigned bits = (paint.getColor() != kColor_Default) ? kColor_NonDef : 0; | |
| 49 | |
| 50 if (usage & kText_PaintUsage) { | |
| 51 bits |= (paint.getTextSize() != kTextSize_Default ? kTextSize_NonD ef : 0); | |
| 52 bits |= (paint.getTextScaleX() != kTextScaleX_Default ? kTextScaleX_No nDef : 0); | |
| 53 bits |= (paint.getTextSkewX() != kTextSkewX_Default ? kTextSkewX_Non Def : 0); | |
| 54 bits |= (paint.getTypeface() ? kTypeface_NonD ef : 0); | |
| 55 } | |
| 56 | |
| 57 if (usage & kVertices_PaintUsage) { | |
| 58 bits |= (paint.getShader() ? kShader_NonDef : 0); | |
| 59 } else if (usage & (kText_PaintUsage | kGeometry_PaintUsage | kTextBlob_Pain tUsage)) { | |
| 60 bits |= (paint.getPathEffect() ? kPathEffect_NonDef : 0); | |
| 61 bits |= (paint.getShader() ? kShader_NonDef : 0); | |
| 62 bits |= (paint.getRasterizer() ? kRasterizer_NonDef : 0); | |
| 63 | |
| 64 if (paint.getStyle() != SkPaint::kFill_Style) { | |
| 65 bits |= (paint.getStrokeWidth() != kStrokeWidth_Default ? kStrokeWid th_NonDef : 0); | |
| 66 bits |= (paint.getStrokeMiter() != kStrokeMiter_Default ? kStrokeMit er_NonDef : 0); | |
| 67 } | |
| 68 } | |
| 69 | |
| 70 bits |= (paint.getXfermode() ? kXfermode_NonDef : 0); | |
| 71 bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0); | |
| 72 bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0); | |
| 73 bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0); | |
| 74 | |
| 75 return SkToU16(bits); | |
| 76 } | |
| 77 | |
| 78 static uint32_t pack_paint_flags(unsigned flags, unsigned hint, unsigned align, | |
| 79 unsigned filter, unsigned style, unsigned caps, unsigned joins, | |
| 80 unsigned encoding) { | |
| 81 SkASSERT(kFlags_BPF + kHint_BPF + kAlign_BPF + kFilter_BPF <= 32); | |
| 82 | |
| 83 ASSERT_FITS_IN(flags, kFlags_BPF); | |
| 84 ASSERT_FITS_IN(filter, kFilter_BPF); | |
| 85 ASSERT_FITS_IN(style, kStyle_BPF); | |
| 86 ASSERT_FITS_IN(caps, kCaps_BPF); | |
| 87 ASSERT_FITS_IN(joins, kJoins_BPF); | |
| 88 ASSERT_FITS_IN(hint, kHint_BPF); | |
| 89 ASSERT_FITS_IN(align, kAlign_BPF); | |
| 90 ASSERT_FITS_IN(encoding, kEncoding_BPF); | |
| 91 | |
| 92 // left-align the fields of "known" size, and right-align the last (flatFlag s) so it can easly | |
| 93 // add more bits in the future. | |
| 94 | |
| 95 uint32_t packed = 0; | |
| 96 int shift = 32; | |
| 97 | |
| 98 shift -= kFlags_BPF; packed |= (flags << shift); | |
| 99 shift -= kFilter_BPF; packed |= (filter << shift); | |
| 100 shift -= kStyle_BPF; packed |= (style << shift); | |
| 101 // these are only needed for stroking (geometry or text) | |
| 102 shift -= kCaps_BPF; packed |= (caps << shift); | |
| 103 shift -= kJoins_BPF; packed |= (joins << shift); | |
| 104 // these are only needed for text | |
| 105 shift -= kHint_BPF; packed |= (hint << shift); | |
| 106 shift -= kAlign_BPF; packed |= (align << shift); | |
| 107 shift -= kEncoding_BPF; packed |= (encoding << shift); | |
| 108 | |
| 109 return packed; | |
| 110 } | |
| 111 | |
| 112 #define CHECK_WRITE_SCALAR(writer, nondef, paint, Field) \ | |
| 113 do { if (nondef & (k##Field##_NonDef)) { \ | |
| 114 writer.writeScalar(paint.get##Field()); \ | |
| 115 }} while (0) | |
| 116 | |
| 117 #define CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Field) \ | |
| 118 do { if (nondef & (k##Field##_NonDef)) { \ | |
| 119 SkFlattenable* f = paint.get##Field(); \ | |
| 120 SkASSERT(f != nullptr); \ | |
| 121 writer.writeFlattenable(f); \ | |
| 122 } } while (0) | |
| 123 | |
| 124 /* | |
| 125 * Header: | |
| 126 * paint flags : 32 | |
| 127 * non_def bits : 16 | |
| 128 * xfermode enum : 8 | |
| 129 * pad zeros : 8 | |
| 130 */ | |
| 131 static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, PaintUsage usage) { | |
| 132 uint32_t packedFlags = pack_paint_flags(paint.getFlags(), paint.getHinting() , | |
| 133 paint.getTextAlign(), paint.getFilte rQuality(), | |
| 134 paint.getStyle(), paint.getStrokeCap (), | |
| 135 paint.getStrokeJoin(), paint.getText Encoding()); | |
| 136 writer.write32(packedFlags); | |
| 137 | |
| 138 unsigned nondef = compute_nondef(paint, usage); | |
| 139 SkXfermode::Mode mode; | |
| 140 if (SkXfermode::AsMode(paint.getXfermode(), &mode)) { | |
| 141 nondef &= ~kXfermode_NonDef; // don't need to store a pointer since w e have an enum | |
| 142 } else { | |
| 143 SkASSERT(nondef & kXfermode_NonDef); | |
| 144 mode = (SkXfermode::Mode)0; | |
| 145 } | |
| 146 const uint8_t pad = 0; | |
| 147 writer.write32((nondef << 16) | ((unsigned)mode << 8) | pad); | |
| 148 | |
| 149 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize); | |
| 150 CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX); | |
| 151 CHECK_WRITE_SCALAR(writer, nondef, paint, TextSkewX); | |
| 152 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeWidth); | |
| 153 CHECK_WRITE_SCALAR(writer, nondef, paint, StrokeMiter); | |
| 154 | |
| 155 if (nondef & kColor_NonDef) { | |
| 156 writer.write32(paint.getColor()); | |
| 157 } | |
| 158 if (nondef & kTypeface_NonDef) { | |
| 159 } | |
| 160 | |
| 161 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect); | |
| 162 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader); | |
| 163 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Xfermode); | |
| 164 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter); | |
| 165 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter); | |
| 166 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Rasterizer); | |
| 167 CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ImageFilter); | |
| 168 } | |
| 169 | |
| 170 class SkPipeWriter : public SkBinaryWriteBuffer { | |
| 171 enum { | |
| 172 N = 1024/4, | |
| 173 }; | |
| 174 uint32_t fStorage[N]; | |
| 175 SkWStream* fStream; | |
| 176 | |
| 177 public: | |
| 178 SkPipeWriter(SkPipeCanvas* pc) | |
| 179 : SkBinaryWriteBuffer(fStorage, sizeof(fStorage)) | |
| 180 , fStream(pc->fStream) | |
| 181 { | |
| 182 this->setDeduper(pc->fDeduper); | |
| 183 } | |
| 184 | |
| 185 ~SkPipeWriter() override { | |
| 186 SkASSERT(SkIsAlign4(fStream->bytesWritten())); | |
| 187 this->writeToStream(fStream); | |
| 188 } | |
| 189 | |
| 190 void writePaint(const SkPaint& paint) override { | |
| 191 write_paint(*this, paint, kUnknown_PaintUsage); | |
| 192 } | |
| 193 }; | |
| 194 | |
| 195 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 196 | |
| 197 SkPipeCanvas::SkPipeCanvas(const SkRect& cull, SkPipeDeduper* deduper, SkWStream * stream) | |
| 198 : INHERITED(SkScalarCeilToInt(cull.width()), SkScalarCeilToInt(cull.height() )) | |
| 199 , fDeduper(deduper) | |
| 200 , fStream(stream) | |
| 201 {} | |
| 202 | |
| 203 SkPipeCanvas::~SkPipeCanvas() {} | |
| 204 | |
| 205 void SkPipeCanvas::willSave() { | |
| 206 fStream->write32(pack_verb(SkPipeVerb::kSave)); | |
| 207 this->INHERITED::willSave(); | |
| 208 } | |
| 209 | |
| 210 SkCanvas::SaveLayerStrategy SkPipeCanvas::getSaveLayerStrategy(const SaveLayerRe c& rec) { | |
| 211 SkPipeWriter writer(this); | |
| 212 uint32_t extra = rec.fSaveLayerFlags; | |
| 213 if (rec.fBounds) { | |
| 214 extra |= kHasBounds_SaveLayerMask; | |
| 215 } | |
| 216 if (rec.fPaint) { | |
| 217 extra |= kHasPaint_SaveLayerMask; | |
| 218 } | |
| 219 if (rec.fBackdrop) { | |
| 220 extra |= kHasBackdrop_SaveLayerMask; | |
| 221 } | |
| 222 | |
| 223 writer.write32(pack_verb(SkPipeVerb::kSaveLayer, extra)); | |
| 224 if (rec.fBounds) { | |
| 225 writer.writeRect(*rec.fBounds); | |
| 226 } | |
| 227 if (rec.fPaint) { | |
| 228 write_paint(writer, *rec.fPaint, kSaveLayer_PaintUsage); | |
| 229 } | |
| 230 if (rec.fBackdrop) { | |
| 231 writer.writeFlattenable(rec.fBackdrop); | |
| 232 } | |
| 233 return kNoLayer_SaveLayerStrategy; | |
| 234 } | |
| 235 | |
| 236 void SkPipeCanvas::willRestore() { | |
| 237 fStream->write32(pack_verb(SkPipeVerb::kRestore)); | |
| 238 this->INHERITED::willRestore(); | |
| 239 } | |
| 240 | |
| 241 template <typename T> void write_sparse_matrix(T* writer, const SkMatrix& matrix ) { | |
| 242 SkMatrix::TypeMask tm = matrix.getType(); | |
| 243 SkScalar tmp[9]; | |
| 244 if (tm & SkMatrix::kPerspective_Mask) { | |
| 245 matrix.get9(tmp); | |
| 246 writer->write(tmp, 9 * sizeof(SkScalar)); | |
| 247 } else if (tm & SkMatrix::kAffine_Mask) { | |
| 248 tmp[0] = matrix[SkMatrix::kMScaleX]; | |
| 249 tmp[1] = matrix[SkMatrix::kMSkewX]; | |
| 250 tmp[2] = matrix[SkMatrix::kMTransX]; | |
| 251 tmp[3] = matrix[SkMatrix::kMScaleY]; | |
| 252 tmp[4] = matrix[SkMatrix::kMSkewY]; | |
| 253 tmp[5] = matrix[SkMatrix::kMTransY]; | |
| 254 writer->write(tmp, 6 * sizeof(SkScalar)); | |
| 255 } else if (tm & SkMatrix::kScale_Mask) { | |
| 256 tmp[0] = matrix[SkMatrix::kMScaleX]; | |
| 257 tmp[1] = matrix[SkMatrix::kMTransX]; | |
| 258 tmp[2] = matrix[SkMatrix::kMScaleY]; | |
| 259 tmp[3] = matrix[SkMatrix::kMTransY]; | |
| 260 writer->write(tmp, 4 * sizeof(SkScalar)); | |
| 261 } else if (tm & SkMatrix::kTranslate_Mask) { | |
| 262 tmp[0] = matrix[SkMatrix::kMTransX]; | |
| 263 tmp[1] = matrix[SkMatrix::kMTransY]; | |
| 264 writer->write(tmp, 2 * sizeof(SkScalar)); | |
| 265 } | |
| 266 // else write nothing for Identity | |
| 267 } | |
| 268 | |
| 269 void SkPipeCanvas::didConcat(const SkMatrix& matrix) { | |
| 270 SkMatrix::TypeMask tm = matrix.getType(); | |
| 271 SkASSERT(tm != SkMatrix::kIdentity_Mask); | |
| 272 fStream->write32(pack_verb(SkPipeVerb::kConcat, tm)); | |
| 273 write_sparse_matrix(fStream, matrix); | |
| 274 | |
| 275 this->INHERITED::didConcat(matrix); | |
| 276 } | |
| 277 | |
| 278 void SkPipeCanvas::didSetMatrix(const SkMatrix& matrix) { | |
| 279 // Can we eliminate this? | |
|
mtklein
2016/08/26 18:43:23
Ah ha, was wondering how you handled this.
If we
| |
| 280 this->INHERITED::didSetMatrix(matrix); | |
| 281 } | |
| 282 | |
| 283 void SkPipeCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) { | |
| 284 fStream->write32(pack_verb(SkPipeVerb::kClipRect, ((unsigned)op << 1) | edge Style)); | |
| 285 fStream->write(&rect, 4 * sizeof(SkScalar)); | |
| 286 | |
| 287 this->INHERITED::onClipRect(rect, op, edgeStyle); | |
| 288 } | |
| 289 | |
| 290 void SkPipeCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeSt yle edgeStyle) { | |
| 291 fStream->write32(pack_verb(SkPipeVerb::kClipRRect, ((unsigned)op << 1) | edg eStyle)); | |
| 292 write_rrect(fStream, rrect); | |
| 293 | |
| 294 this->INHERITED::onClipRRect(rrect, op, edgeStyle); | |
| 295 } | |
| 296 | |
| 297 void SkPipeCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edgeStyle) { | |
| 298 SkPipeWriter writer(this); | |
| 299 writer.write32(pack_verb(SkPipeVerb::kClipPath, ((unsigned)op << 1) | edgeSt yle)); | |
| 300 writer.writePath(path); | |
| 301 | |
| 302 this->INHERITED::onClipPath(path, op, edgeStyle); | |
| 303 } | |
| 304 | |
| 305 void SkPipeCanvas::onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) { | |
| 306 SkPipeWriter writer(this); | |
| 307 writer.write32(pack_verb(SkPipeVerb::kClipRegion, (unsigned)op << 1)); | |
| 308 writer.writeRegion(deviceRgn); | |
| 309 | |
| 310 this->INHERITED::onClipRegion(deviceRgn, op); | |
| 311 } | |
| 312 | |
| 313 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 314 | |
| 315 void SkPipeCanvas::onDrawPaint(const SkPaint& paint) { | |
| 316 SkPipeWriter writer(this); | |
| 317 writer.write32(pack_verb(SkPipeVerb::kDrawPaint)); | |
| 318 write_paint(writer, paint, kDrawPaint_PaintUsage); | |
| 319 } | |
| 320 | |
| 321 void SkPipeCanvas::onDrawPoints(PointMode mode, size_t count, const SkPoint pts[ ], | |
| 322 const SkPaint& paint) { | |
| 323 SkPipeWriter writer(this); | |
| 324 writer.write32(pack_verb(SkPipeVerb::kDrawPoints, mode)); | |
| 325 writer.write32(SkToU32(count)); | |
| 326 writer.write(pts, count * sizeof(SkPoint)); | |
| 327 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 328 } | |
| 329 | |
| 330 void SkPipeCanvas::onDrawRect(const SkRect& rect, const SkPaint& paint) { | |
| 331 SkPipeWriter writer(this); | |
| 332 writer.write32(pack_verb(SkPipeVerb::kDrawRect)); | |
| 333 writer.write(&rect, sizeof(SkRect)); | |
| 334 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 335 } | |
| 336 | |
| 337 void SkPipeCanvas::onDrawOval(const SkRect& rect, const SkPaint& paint) { | |
| 338 SkPipeWriter writer(this); | |
| 339 writer.write32(pack_verb(SkPipeVerb::kDrawOval)); | |
| 340 writer.write(&rect, sizeof(SkRect)); | |
| 341 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 342 } | |
| 343 | |
| 344 void SkPipeCanvas::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) { | |
| 345 SkPipeWriter writer(this); | |
| 346 writer.write32(pack_verb(SkPipeVerb::kDrawRRect)); | |
| 347 write_rrect(&writer, rrect); | |
| 348 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 349 } | |
| 350 | |
| 351 void SkPipeCanvas::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, cons t SkPaint& paint) { | |
| 352 SkPipeWriter writer(this); | |
| 353 writer.write32(pack_verb(SkPipeVerb::kDrawDRRect)); | |
| 354 write_rrect(&writer, outer); | |
| 355 write_rrect(&writer, inner); | |
| 356 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 357 } | |
| 358 | |
| 359 void SkPipeCanvas::onDrawPath(const SkPath& path, const SkPaint& paint) { | |
| 360 SkPipeWriter writer(this); | |
| 361 writer.write32(pack_verb(SkPipeVerb::kDrawPath)); | |
| 362 writer.writePath(path); | |
| 363 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 364 } | |
| 365 | |
| 366 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 367 | |
| 368 static sk_sp<SkImage> make_from_bitmap(const SkBitmap& bitmap) { | |
| 369 // If we just "make" an image, it will force a CPU copy (if its mutable), on ly to have | |
| 370 // us then either find it in our cache, or compress and send it. | |
| 371 // | |
| 372 // Better could be to look it up in our cache first, and only create/compres s it if we have to. | |
| 373 // | |
| 374 // But for now, just do the dumb thing... | |
| 375 return SkImage::MakeFromBitmap(bitmap); | |
| 376 } | |
| 377 | |
| 378 void SkPipeCanvas::onDrawBitmap(const SkBitmap& bitmap, SkScalar x, SkScalar y, | |
| 379 const SkPaint* paint) { | |
| 380 sk_sp<SkImage> image = make_from_bitmap(bitmap); | |
| 381 if (image) { | |
| 382 this->onDrawImage(image.get(), x, y, paint); | |
| 383 } | |
| 384 } | |
| 385 | |
| 386 void SkPipeCanvas::onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, c onst SkRect& dst, | |
| 387 const SkPaint* paint, SrcRectConstraint cons traint) { | |
| 388 sk_sp<SkImage> image = make_from_bitmap(bitmap); | |
| 389 if (image) { | |
| 390 this->onDrawImageRect(image.get(), src, dst, paint, constraint); | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 void SkPipeCanvas::onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& cente r, | |
| 395 const SkRect& dst, const SkPaint* paint) { | |
| 396 sk_sp<SkImage> image = make_from_bitmap(bitmap); | |
| 397 if (image) { | |
| 398 this->onDrawImageNine(image.get(), center, dst, paint); | |
| 399 } | |
| 400 } | |
| 401 | |
| 402 void SkPipeCanvas::onDrawImage(const SkImage* image, SkScalar left, SkScalar top , | |
| 403 const SkPaint* paint) { | |
| 404 SkPipeWriter writer(this); | |
| 405 writer.write32(pack_verb(SkPipeVerb::kDrawImage, paint != nullptr)); | |
| 406 writer.writeImage(image); | |
| 407 writer.writeScalar(left); | |
| 408 writer.writeScalar(top); | |
| 409 if (paint) { | |
| 410 write_paint(writer, *paint, kImage_PaintUsage); | |
| 411 } | |
| 412 } | |
| 413 | |
| 414 void SkPipeCanvas::onDrawImageRect(const SkImage* image, const SkRect* src, cons t SkRect& dst, | |
| 415 const SkPaint* paint, SrcRectConstraint const raint) { | |
| 416 SkPipeWriter writer(this); | |
| 417 writer.write32(pack_verb(SkPipeVerb::kDrawImageRect, ((src != nullptr) << 1) | (paint != nullptr))); | |
| 418 writer.writeImage(image); | |
| 419 if (src) { | |
| 420 writer.write(src, sizeof(*src)); | |
| 421 } | |
| 422 writer.write(&dst, sizeof(dst)); | |
| 423 if (paint) { | |
| 424 write_paint(writer, *paint, kImage_PaintUsage); | |
| 425 } | |
| 426 } | |
| 427 | |
| 428 void SkPipeCanvas::onDrawImageNine(const SkImage* image, const SkIRect& center, const SkRect& dst, | |
| 429 const SkPaint* paint) { | |
| 430 SkPipeWriter writer(this); | |
| 431 writer.write32(pack_verb(SkPipeVerb::kDrawImageNine, paint != nullptr)); | |
| 432 writer.writeImage(image); | |
| 433 writer.write(¢er, sizeof(center)); | |
| 434 writer.write(&dst, sizeof(dst)); | |
| 435 if (paint) { | |
| 436 write_paint(writer, *paint, kImage_PaintUsage); | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 441 | |
| 442 void SkPipeCanvas::onDrawText(const void* text, size_t byteLength, SkScalar x, S kScalar y, | |
| 443 const SkPaint& paint) { | |
| 444 SkASSERT(byteLength); | |
| 445 | |
| 446 bool compact = fits_in(byteLength, 24); | |
| 447 | |
| 448 SkPipeWriter writer(this); | |
| 449 writer.write32(pack_verb(SkPipeVerb::kDrawText, compact ? (unsigned)byteLeng th : 0)); | |
| 450 if (!compact) { | |
| 451 writer.write32(SkToU32(byteLength)); | |
| 452 } | |
| 453 write_pad(&writer, text, byteLength); | |
| 454 writer.writeScalar(x); | |
| 455 writer.writeScalar(y); | |
| 456 write_paint(writer, paint, kText_PaintUsage); | |
| 457 } | |
| 458 | |
| 459 void SkPipeCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPo int pos[], | |
| 460 const SkPaint& paint) { | |
| 461 SkASSERT(byteLength); | |
| 462 | |
| 463 bool compact = fits_in(byteLength, 24); | |
| 464 | |
| 465 SkPipeWriter writer(this); | |
| 466 writer.write32(pack_verb(SkPipeVerb::kDrawPosText, compact ? (unsigned)byteL ength : 0)); | |
| 467 if (!compact) { | |
| 468 writer.write32(SkToU32(byteLength)); | |
| 469 } | |
| 470 write_pad(&writer, text, byteLength); | |
| 471 writer.writePointArray(pos, paint.countText(text, byteLength)); | |
| 472 write_paint(writer, paint, kText_PaintUsage); | |
| 473 } | |
| 474 | |
| 475 void SkPipeCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkS calar xpos[], | |
| 476 SkScalar constY, const SkPaint& paint) { | |
| 477 SkASSERT(byteLength); | |
| 478 | |
| 479 bool compact = fits_in(byteLength, 24); | |
| 480 | |
| 481 SkPipeWriter writer(this); | |
| 482 writer.write32(pack_verb(SkPipeVerb::kDrawPosTextH, compact ? (unsigned)byte Length : 0)); | |
| 483 if (!compact) { | |
| 484 writer.write32(SkToU32(byteLength)); | |
| 485 } | |
| 486 write_pad(&writer, text, byteLength); | |
| 487 writer.writeScalarArray(xpos, paint.countText(text, byteLength)); | |
| 488 writer.writeScalar(constY); | |
| 489 write_paint(writer, paint, kText_PaintUsage); | |
| 490 } | |
| 491 | |
| 492 void SkPipeCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const S kPath& path, | |
| 493 const SkMatrix* matrix, const SkPaint& paint ) { | |
| 494 SkASSERT(byteLength > 0); | |
| 495 | |
| 496 unsigned extra = 0; | |
| 497 if (byteLength <= kTextLength_DrawTextOnPathMask) { | |
| 498 extra |= byteLength; | |
| 499 } // else we will write the length after the packedverb | |
| 500 SkMatrix::TypeMask tm = matrix ? matrix->getType() : SkMatrix::kIdentity_Mas k; | |
| 501 extra |= (unsigned)tm << kMatrixType_DrawTextOnPathShift; | |
| 502 | |
| 503 SkPipeWriter writer(this); | |
| 504 writer.write32(pack_verb(SkPipeVerb::kDrawTextOnPath, extra)); | |
| 505 if (byteLength > kTextLength_DrawTextOnPathMask) { | |
| 506 writer.write32(byteLength); | |
| 507 } | |
| 508 write_pad(&writer, text, byteLength); | |
| 509 writer.writePath(path); | |
| 510 if (matrix) { | |
| 511 write_sparse_matrix(&writer, *matrix); | |
| 512 } | |
| 513 write_paint(writer, paint, kText_PaintUsage); | |
| 514 } | |
| 515 | |
| 516 void SkPipeCanvas::onDrawTextRSXform(const void* text, size_t byteLength, const SkRSXform xform[], | |
| 517 const SkRect* cull, const SkPaint& paint) { | |
| 518 SkASSERT(byteLength); | |
| 519 | |
| 520 bool compact = fits_in(byteLength, 23); | |
| 521 unsigned extra = compact ? (byteLength << 1) : 0; | |
| 522 if (cull) { | |
| 523 extra |= 1; | |
| 524 } | |
| 525 | |
| 526 SkPipeWriter writer(this); | |
| 527 writer.write32(pack_verb(SkPipeVerb::kDrawTextRSXform, extra)); | |
| 528 if (!compact) { | |
| 529 writer.write32(SkToU32(byteLength)); | |
| 530 } | |
| 531 write_pad(&writer, text, byteLength); | |
| 532 | |
| 533 int count = paint.countText(text, byteLength); | |
| 534 writer.write32(count); // maybe we can/should store this in extra as well? | |
| 535 writer.write(xform, count * sizeof(SkRSXform)); | |
| 536 if (cull) { | |
| 537 writer.writeRect(*cull); | |
| 538 } | |
| 539 write_paint(writer, paint, kText_PaintUsage); | |
| 540 } | |
| 541 | |
| 542 void SkPipeCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y , | |
| 543 const SkPaint &paint) { | |
| 544 SkPipeWriter writer(this); | |
| 545 writer.write32(pack_verb(SkPipeVerb::kDrawTextBlob, 0)); | |
| 546 blob->flatten(writer); | |
| 547 writer.writeScalar(x); | |
| 548 writer.writeScalar(y); | |
| 549 write_paint(writer, paint, kTextBlob_PaintUsage); | |
| 550 } | |
| 551 | |
| 552 void SkPipeCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matri x, | |
| 553 const SkPaint* paint) { | |
| 554 unsigned extra = fDeduper->findOrDefinePicture(const_cast<SkPicture*>(pictur e)); | |
| 555 if (matrix) { | |
| 556 extra |= kHasMatrix_DrawPictureExtra; | |
| 557 } | |
| 558 if (paint) { | |
| 559 extra |= kHasPaint_DrawPictureExtra; | |
| 560 } | |
| 561 SkPipeWriter writer(this); | |
| 562 writer.write32(pack_verb(SkPipeVerb::kDrawPicture, extra)); | |
| 563 if (matrix) { | |
| 564 writer.writeMatrix(*matrix); | |
| 565 } | |
| 566 if (paint) { | |
| 567 write_paint(writer, *paint, kSaveLayer_PaintUsage); | |
| 568 } | |
| 569 } | |
| 570 | |
| 571 void SkPipeCanvas::onDrawVertices(VertexMode vmode, int vertexCount, | |
| 572 const SkPoint vertices[], const SkPoint texs[] , | |
| 573 const SkColor colors[], SkXfermode* xmode, | |
| 574 const uint16_t indices[], int indexCount, | |
| 575 const SkPaint& paint) { | |
| 576 SkASSERT(vertexCount > 0); | |
| 577 | |
| 578 unsigned extra = 0; | |
| 579 if (vertexCount <= kVCount_DrawVerticesMask) { | |
| 580 extra |= vertexCount; | |
| 581 } | |
| 582 extra |= (unsigned)vmode << kVMode_DrawVerticesShift; | |
| 583 | |
| 584 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; | |
| 585 if (xmode && !SkXfermode::AsMode(xmode, &mode)) { | |
| 586 mode = (SkXfermode::Mode)0xFF; // sentinel for read the xfer later | |
| 587 } | |
| 588 extra |= (unsigned)mode << kXMode_DrawVerticesShift; | |
| 589 | |
| 590 if (texs) { | |
| 591 extra |= kHasTex_DrawVerticesMask; | |
| 592 } | |
| 593 if (colors) { | |
| 594 extra |= kHasColors_DrawVerticesMask; | |
| 595 } | |
| 596 if (indexCount > 0) { | |
| 597 extra |= kHasIndices_DrawVerticesMask; | |
| 598 } | |
| 599 | |
| 600 SkPipeWriter writer(this); | |
| 601 writer.write32(pack_verb(SkPipeVerb::kDrawVertices, extra)); | |
| 602 if (vertexCount > kVCount_DrawVerticesMask) { | |
| 603 writer.write32(vertexCount); | |
| 604 } | |
| 605 if (mode == (SkXfermode::Mode)0xFF) { | |
| 606 writer.writeFlattenable(xmode); | |
| 607 } | |
| 608 writer.write(vertices, vertexCount * sizeof(SkPoint)); | |
| 609 if (texs) { | |
| 610 writer.write(texs, vertexCount * sizeof(SkPoint)); | |
| 611 } | |
| 612 if (colors) { | |
| 613 writer.write(colors, vertexCount * sizeof(SkColor)); | |
| 614 } | |
| 615 if (indexCount > 0) { | |
| 616 writer.write32(indexCount); | |
| 617 SkASSERT(SkIsAlign2(indexCount)); | |
| 618 writer.write(indices, indexCount * sizeof(uint16_t)); | |
| 619 } | |
| 620 write_paint(writer, paint, kVertices_PaintUsage); | |
| 621 } | |
| 622 | |
| 623 void SkPipeCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4] , | |
| 624 const SkPoint texCoords[4], SkXfermode* xfer, | |
| 625 const SkPaint& paint) { | |
| 626 SkPipeWriter writer(this); | |
| 627 unsigned extra = 0; | |
| 628 SkXfermode::Mode mode = SkXfermode::kModulate_Mode; | |
| 629 if (xfer && !xfer->asMode(&mode)) { | |
| 630 mode = (SkXfermode::Mode)kExplicitXfer_DrawPatchExtraValue; | |
| 631 } else { | |
| 632 xfer = nullptr; // signal that we're using the mode enum | |
| 633 } | |
| 634 SkASSERT(0 == (mode & ~kModeEnum_DrawPatchExtraMask)); | |
| 635 extra = (unsigned)mode; | |
| 636 if (colors) { | |
| 637 extra |= kHasColors_DrawPatchExtraMask; | |
| 638 } | |
| 639 if (texCoords) { | |
| 640 extra |= kHasTexture_DrawPatchExtraMask; | |
| 641 } | |
| 642 writer.write32(pack_verb(SkPipeVerb::kDrawPatch, extra)); | |
| 643 writer.write(cubics, sizeof(SkPoint) * 12); | |
| 644 if (colors) { | |
| 645 writer.write(colors, sizeof(SkColor) * 4); | |
| 646 } | |
| 647 if (texCoords) { | |
| 648 writer.write(texCoords, sizeof(SkPoint) * 4); | |
| 649 } | |
| 650 if (xfer) { | |
| 651 xfer->flatten(writer); | |
| 652 } | |
| 653 write_paint(writer, paint, kGeometry_PaintUsage); | |
| 654 } | |
| 655 | |
| 656 void SkPipeCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData * data) { | |
| 657 const size_t len = strlen(key) + 1; // must write the trailing 0 | |
| 658 bool compact = fits_in(len, 23); | |
| 659 uint32_t extra = compact ? (unsigned)len : 0; | |
| 660 extra <<= 1; // make room for has_data_sentinel | |
| 661 if (data) { | |
| 662 extra |= 1; | |
| 663 } | |
| 664 | |
| 665 fStream->write32(pack_verb(SkPipeVerb::kDrawAnnotation, extra)); | |
| 666 fStream->write(&rect, sizeof(SkRect)); | |
| 667 if (!compact) { | |
| 668 fStream->write32(SkToU32(len)); | |
| 669 } | |
| 670 write_pad(fStream, key, len); | |
| 671 if (data) { | |
| 672 fStream->write32(SkToU32(data->size())); | |
| 673 write_pad(fStream, data->data(), data->size()); | |
| 674 } | |
| 675 } | |
| 676 | |
| 677 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 678 | |
| 679 static bool show_deduper_traffic = false; | |
| 680 | |
| 681 int SkPipeDeduper::findOrDefineImage(SkImage* image) { | |
| 682 int index = fImages.find(image->uniqueID()); | |
| 683 SkASSERT(index >= 0); | |
| 684 if (index) { | |
| 685 if (show_deduper_traffic) { | |
| 686 SkDebugf(" reuseImage(%d)\n", index - 1); | |
| 687 } | |
| 688 return index; | |
| 689 } | |
| 690 | |
| 691 sk_sp<SkData> data(image->encode()); | |
| 692 if (data) { | |
| 693 index = fImages.add(image->uniqueID()); | |
| 694 SkASSERT(index > 0); | |
| 695 SkASSERT(fits_in(index, 24)); | |
| 696 fStream->write32(pack_verb(SkPipeVerb::kDefineImage, index)); | |
| 697 | |
| 698 uint32_t len = SkToU32(data->size()); | |
| 699 fStream->write32(SkAlign4(len)); | |
| 700 write_pad(fStream, data->data(), len); | |
| 701 | |
| 702 if (show_deduper_traffic) { | |
| 703 int size = image->width() * image->height() << 2; | |
| 704 SkDebugf(" defineImage(%d) %d -> %d\n", index - 1, size, len); | |
| 705 } | |
| 706 return index; | |
| 707 } | |
| 708 SkDebugf("+++ failed to encode image [%d %d]\n", image->width(), image->heig ht()); | |
| 709 return 0; // failed to encode | |
| 710 } | |
| 711 | |
| 712 int SkPipeDeduper::findOrDefinePicture(SkPicture* picture) { | |
| 713 int index = fPictures.find(picture->uniqueID()); | |
| 714 SkASSERT(index >= 0); | |
| 715 if (index) { | |
| 716 if (show_deduper_traffic) { | |
| 717 SkDebugf(" reusePicture(%d)\n", index - 1); | |
| 718 } | |
| 719 return index; | |
| 720 } | |
| 721 | |
| 722 index = fPictures.add(picture->uniqueID()); | |
| 723 ASSERT_FITS_IN(index, kDefineObjectBits); | |
| 724 size_t prevWritten = fStream->bytesWritten(); | |
| 725 fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, index)); | |
| 726 picture->playback(fPipeCanvas); | |
| 727 fStream->write32(pack_verb(SkPipeVerb::kDefinePicture, kEnd_DefinePictureMas k)); | |
| 728 SkDebugf(" definePicture(%d) %d\n", | |
| 729 index - 1, SkToU32(fStream->bytesWritten() - prevWritten)); | |
| 730 return index; | |
| 731 } | |
| 732 | |
| 733 int SkPipeDeduper::findOrDefineTypeface(SkTypeface* typeface) { | |
| 734 return 0; | |
| 735 } | |
| 736 | |
| 737 int SkPipeDeduper::findOrDefineFactory(SkFlattenable* flattenable) { | |
| 738 if (!flattenable) { | |
| 739 return 0; | |
| 740 } | |
| 741 | |
| 742 int index = fFactories.find(flattenable->getFactory()); | |
| 743 SkASSERT(index >= 0); | |
| 744 if (index) { | |
| 745 if (show_deduper_traffic) { | |
| 746 SkDebugf(" reuseFactory(%d)\n", index - 1); | |
| 747 } | |
| 748 return index; | |
| 749 } | |
| 750 | |
| 751 index = fFactories.add(flattenable->getFactory()); | |
| 752 ASSERT_FITS_IN(index, kIndex_DefineFactoryExtraBits); | |
| 753 const char* name = flattenable->getTypeName(); | |
| 754 size_t len = strlen(name); | |
| 755 ASSERT_FITS_IN(len, kNameLength_DefineFactoryExtraBits); | |
| 756 unsigned extra = (index << kNameLength_DefineFactoryExtraBits) | len; | |
| 757 size_t prevWritten = fStream->bytesWritten(); | |
| 758 fStream->write32(pack_verb(SkPipeVerb::kDefineFactory, extra)); | |
| 759 write_pad(fStream, name, len + 1); | |
| 760 SkDebugf(" defineFactory(%d) %d %s\n", | |
| 761 index - 1, SkToU32(fStream->bytesWritten() - prevWritten), name); | |
| 762 return index; | |
| 763 } | |
| 764 | |
| 765 //////////////////////////////////////////////////////////////////////////////// /////////////////// | |
| 766 #include "SkPipe.h" | |
| 767 | |
| 768 class SkPipeSerializer::Impl { | |
| 769 public: | |
| 770 SkPipeDeduper fDeduper; | |
| 771 std::unique_ptr<SkPipeCanvas> fCanvas; | |
| 772 }; | |
| 773 | |
| 774 SkPipeSerializer::SkPipeSerializer() : fImpl(new Impl) {} | |
| 775 | |
| 776 SkPipeSerializer::~SkPipeSerializer() { delete fImpl; } | |
| 777 | |
| 778 void SkPipeSerializer::reset() { | |
| 779 fImpl->fDeduper.resetCaches(); | |
| 780 } | |
| 781 | |
| 782 void SkPipeSerializer::write(SkPicture* picture, SkWStream* stream) { | |
| 783 stream->write32(kDefinePicture_ExtPipeVerb); | |
| 784 SkRect cull = picture->cullRect(); | |
| 785 stream->write(&cull.fLeft, sizeof(SkRect)); | |
| 786 picture->playback(this->beginWrite(cull, stream)); | |
| 787 this->endWrite(); | |
| 788 } | |
| 789 | |
| 790 void SkPipeSerializer::write(SkImage*, SkWStream* stream) { | |
| 791 stream->write32(kDefineImage_ExtPipeVerb); | |
| 792 } | |
| 793 | |
| 794 SkCanvas* SkPipeSerializer::beginWrite(const SkRect& cull, SkWStream* stream) { | |
| 795 SkASSERT(nullptr == fImpl->fCanvas); | |
| 796 fImpl->fCanvas.reset(new SkPipeCanvas(cull, &fImpl->fDeduper, stream)); | |
| 797 fImpl->fDeduper.setStream(stream); | |
| 798 fImpl->fDeduper.setCanvas(fImpl->fCanvas.get()); | |
| 799 return fImpl->fCanvas.get(); | |
| 800 } | |
| 801 | |
| 802 void SkPipeSerializer::endWrite() { | |
| 803 fImpl->fCanvas.reset(nullptr); | |
| 804 } | |
| OLD | NEW |