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