1 /* 2 * Copyright 2014 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 #ifndef SkCanvasPriv_DEFINED 9 #define SkCanvasPriv_DEFINED 10 11 #include "include/core/SkCanvas.h" 12 #include "include/core/SkPaint.h" 13 #include "include/core/SkRefCnt.h" 14 #include "include/core/SkScalar.h" 15 #include "include/core/SkTileMode.h" 16 #include "include/private/base/SkDebug.h" 17 #include "include/private/base/SkNoncopyable.h" 18 19 #include <cstddef> 20 21 class SkDevice; 22 class SkImageFilter; 23 class SkMatrix; 24 class SkReadBuffer; 25 struct SkRect; 26 class SkWriteBuffer; 27 28 class SkAutoCanvasMatrixPaint : SkNoncopyable { 29 public: 30 SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, const SkRect& bounds); 31 ~SkAutoCanvasMatrixPaint(); 32 33 private: 34 SkCanvas* fCanvas; 35 int fSaveCount; 36 }; 37 38 class SkCanvasPriv { 39 public: 40 // The lattice has pointers directly into the readbuffer 41 static bool ReadLattice(SkReadBuffer&, SkCanvas::Lattice*); 42 43 static void WriteLattice(SkWriteBuffer&, const SkCanvas::Lattice&); 44 45 // return the byte-size of the lattice, even if the buffer is null 46 // storage must be 4-byte aligned 47 static size_t WriteLattice(void* storage, const SkCanvas::Lattice&); 48 SaveBehind(SkCanvas * canvas,const SkRect * subset)49 static int SaveBehind(SkCanvas* canvas, const SkRect* subset) { 50 return canvas->only_axis_aligned_saveBehind(subset); 51 } DrawBehind(SkCanvas * canvas,const SkPaint & paint)52 static void DrawBehind(SkCanvas* canvas, const SkPaint& paint) { 53 canvas->drawClippedToSaveBehind(paint); 54 } 55 56 // Exposed for testing on non-Android framework builds ResetClip(SkCanvas * canvas)57 static void ResetClip(SkCanvas* canvas) { 58 canvas->internal_private_resetClip(); 59 } 60 TopDevice(const SkCanvas * canvas)61 static SkDevice* TopDevice(const SkCanvas* canvas) { 62 return canvas->topDevice(); 63 } 64 65 // The experimental_DrawEdgeAAImageSet API accepts separate dstClips and preViewMatrices arrays, 66 // where entries refer into them, but no explicit size is provided. Given a set of entries, 67 // computes the minimum length for these arrays that would provide index access errors. 68 static void GetDstClipAndMatrixCounts(const SkCanvas::ImageSetEntry set[], int count, 69 int* totalDstClipCount, int* totalMatrixCount); 70 71 static SkCanvas::SaveLayerRec ScaledBackdropLayer(const SkRect* bounds, 72 const SkPaint* paint, 73 const SkImageFilter* backdrop, 74 SkScalar backdropScale, 75 SkTileMode backdropTileMode, 76 SkCanvas::SaveLayerFlags saveLayerFlags, 77 SkCanvas::FilterSpan filters = {}) { 78 return SkCanvas::SaveLayerRec(bounds, paint, backdrop, nullptr, backdropScale, 79 backdropTileMode, saveLayerFlags, filters); 80 } 81 82 static SkCanvas::SaveLayerRec ScaledBackdropLayer(const SkRect* bounds, 83 const SkPaint* paint, 84 const SkImageFilter* backdrop, 85 SkScalar backdropScale, 86 SkCanvas::SaveLayerFlags saveLayerFlags, 87 SkCanvas::FilterSpan filters = {}) { 88 return ScaledBackdropLayer(bounds, paint, backdrop, backdropScale, SkTileMode::kClamp, 89 saveLayerFlags, filters); 90 } 91 GetBackdropScaleFactor(const SkCanvas::SaveLayerRec & rec)92 static SkScalar GetBackdropScaleFactor(const SkCanvas::SaveLayerRec& rec) { 93 return rec.fExperimentalBackdropScale; 94 } 95 SetBackdropScaleFactor(SkCanvas::SaveLayerRec * rec,SkScalar scale)96 static void SetBackdropScaleFactor(SkCanvas::SaveLayerRec* rec, SkScalar scale) { 97 rec->fExperimentalBackdropScale = scale; 98 } 99 100 // Attempts to convert an image filter to its equivalent color filter, which if possible, 101 // modifies the paint to compose the image filter's color filter into the paint's color filter 102 // slot. 103 // Returns true if the paint has been modified. 104 // Requires the paint to have an image filter and the copy-on-write be initialized. 105 static bool ImageToColorFilter(SkPaint*); 106 }; 107 108 /** 109 * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, 110 * against the playback cost of recursing into the subpicture to get at its actual ops. 111 * 112 * For now we pick a conservatively small value, though measurement (and other heuristics like 113 * the type of ops contained) may justify changing this value. 114 */ 115 constexpr int kMaxPictureOpsToUnrollInsteadOfRef = 1; 116 117 /** 118 * We implement ImageFilters and MaskFilters for a given draw by creating a layer, then applying 119 * the filter to the pixels of that layer (its backing surface/image), and then we call restore() 120 * to blend that layer to the main canvas. 121 * 122 * If the paint has neither an image filter nor a mask filter, there will be no layer and paint() 123 * returns the original without modification. 124 * 125 * NOTE: This works by assuming all sources of color and shading are represented by the SkPaint. 126 * Operations like drawImageRect must convert to an equivalent drawRect call if there's a mask 127 * filter, or otherwise ensure there are no mask filters (e.g. drawAtlas). 128 */ 129 class AutoLayerForImageFilter { 130 public: 131 // `rawBounds` is the original bounds of the primitive about to be drawn, unmodified by the 132 // paint. It's used to determine the size of the offscreen layer for filters. 133 // If null, the clip will be used instead. 134 // 135 // If `skipMaskFilterLayer` is true, any SkMaskFilter on `paint` will be left as-is and is 136 // assumed to be handled by the SkDevice that handles the draw. 137 // 138 // Draw functions should use layer->paint() instead of the passed-in paint. 139 AutoLayerForImageFilter(SkCanvas* canvas, 140 const SkPaint& paint, 141 const SkRect* rawBounds, 142 bool skipMaskFilterLayer); 143 144 AutoLayerForImageFilter(const AutoLayerForImageFilter&) = delete; 145 AutoLayerForImageFilter& operator=(const AutoLayerForImageFilter&) = delete; 146 AutoLayerForImageFilter(AutoLayerForImageFilter&&); 147 AutoLayerForImageFilter& operator=(AutoLayerForImageFilter&&); 148 149 ~AutoLayerForImageFilter(); 150 paint()151 const SkPaint& paint() const { return fPaint; } 152 153 // This is public so that a canvas can attempt to specially handle mask filters, specifically 154 // for blurs, and then if the attempt fails fall back on a regular draw with the same autolayer. 155 void addMaskFilterLayer(const SkRect* drawBounds); 156 157 private: 158 void addImageFilterLayer(const SkRect* drawBounds); 159 160 void addLayer(const SkPaint& restorePaint, const SkRect* drawBounds, bool coverageOnly); 161 162 SkPaint fPaint; 163 SkCanvas* fCanvas; 164 int fTempLayersForFilters; 165 166 SkDEBUGCODE(int fSaveCount;) 167 }; 168 169 #endif 170