| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkCanvasPriv_DEFINED |
| #define SkCanvasPriv_DEFINED |
| |
| #include "include/core/SkCanvas.h" |
| #include "include/core/SkPaint.h" |
| #include "include/core/SkScalar.h" |
| #include "include/private/base/SkDebug.h" |
| #include "include/private/base/SkNoncopyable.h" |
| |
| #include <cstddef> |
| |
| class SkDevice; |
| class SkImageFilter; |
| class SkMatrix; |
| class SkReadBuffer; |
| struct SkRect; |
| class SkWriteBuffer; |
| |
| #if defined(GRAPHITE_TEST_UTILS) |
| namespace skgpu::graphite { |
| class TextureProxy; |
| } |
| #endif |
| |
| class SkAutoCanvasMatrixPaint : SkNoncopyable { |
| public: |
| SkAutoCanvasMatrixPaint(SkCanvas*, const SkMatrix*, const SkPaint*, const SkRect& bounds); |
| ~SkAutoCanvasMatrixPaint(); |
| |
| private: |
| SkCanvas* fCanvas; |
| int fSaveCount; |
| }; |
| |
| class SkCanvasPriv { |
| public: |
| // The lattice has pointers directly into the readbuffer |
| static bool ReadLattice(SkReadBuffer&, SkCanvas::Lattice*); |
| |
| static void WriteLattice(SkWriteBuffer&, const SkCanvas::Lattice&); |
| |
| // return the byte-size of the lattice, even if the buffer is null |
| // storage must be 4-byte aligned |
| static size_t WriteLattice(void* storage, const SkCanvas::Lattice&); |
| |
| static int SaveBehind(SkCanvas* canvas, const SkRect* subset) { |
| return canvas->only_axis_aligned_saveBehind(subset); |
| } |
| static void DrawBehind(SkCanvas* canvas, const SkPaint& paint) { |
| canvas->drawClippedToSaveBehind(paint); |
| } |
| |
| // Exposed for testing on non-Android framework builds |
| static void ResetClip(SkCanvas* canvas) { |
| canvas->internal_private_resetClip(); |
| } |
| |
| static SkDevice* TopDevice(const SkCanvas* canvas) { |
| return canvas->topDevice(); |
| } |
| |
| // The experimental_DrawEdgeAAImageSet API accepts separate dstClips and preViewMatrices arrays, |
| // where entries refer into them, but no explicit size is provided. Given a set of entries, |
| // computes the minimum length for these arrays that would provide index access errors. |
| static void GetDstClipAndMatrixCounts(const SkCanvas::ImageSetEntry set[], int count, |
| int* totalDstClipCount, int* totalMatrixCount); |
| |
| static SkCanvas::SaveLayerRec ScaledBackdropLayer(const SkRect* bounds, |
| const SkPaint* paint, |
| const SkImageFilter* backdrop, |
| SkScalar backdropScale, |
| SkCanvas::SaveLayerFlags saveLayerFlags, |
| SkCanvas::FilterSpan filters = {}) { |
| return SkCanvas::SaveLayerRec( |
| bounds, paint, backdrop, nullptr, backdropScale, saveLayerFlags, filters); |
| } |
| |
| static SkScalar GetBackdropScaleFactor(const SkCanvas::SaveLayerRec& rec) { |
| return rec.fExperimentalBackdropScale; |
| } |
| |
| static void SetBackdropScaleFactor(SkCanvas::SaveLayerRec* rec, SkScalar scale) { |
| rec->fExperimentalBackdropScale = scale; |
| } |
| |
| // Attempts to convert an image filter to its equivalent color filter, which if possible, |
| // modifies the paint to compose the image filter's color filter into the paint's color filter |
| // slot. |
| // Returns true if the paint has been modified. |
| // Requires the paint to have an image filter and the copy-on-write be initialized. |
| static bool ImageToColorFilter(SkPaint*); |
| }; |
| |
| /** |
| * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, |
| * against the playback cost of recursing into the subpicture to get at its actual ops. |
| * |
| * For now we pick a conservatively small value, though measurement (and other heuristics like |
| * the type of ops contained) may justify changing this value. |
| */ |
| constexpr int kMaxPictureOpsToUnrollInsteadOfRef = 1; |
| |
| /** |
| * We implement ImageFilters and MaskFilters for a given draw by creating a layer, then applying |
| * the filter to the pixels of that layer (its backing surface/image), and then we call restore() |
| * to blend that layer to the main canvas. |
| * |
| * If the paint has neither an image filter nor a mask filter, there will be no layer and paint() |
| * returns the original without modification. |
| * |
| * NOTE: This works by assuming all sources of color and shading are represented by the SkPaint. |
| * Operations like drawImageRect must convert to an equivalent drawRect call if there's a mask |
| * filter, or otherwise ensure there are no mask filters (e.g. drawAtlas). |
| */ |
| class AutoLayerForImageFilter { |
| public: |
| // `rawBounds` is the original bounds of the primitive about to be drawn, unmodified by the |
| // paint. It's used to determine the size of the offscreen layer for filters. |
| // If null, the clip will be used instead. |
| // |
| // If `skipMaskFilterLayer` is true, any SkMaskFilter on `paint` will be left as-is and is |
| // assumed to be handled by the SkDevice that handles the draw. |
| // |
| // Draw functions should use layer->paint() instead of the passed-in paint. |
| AutoLayerForImageFilter(SkCanvas* canvas, |
| const SkPaint& paint, |
| const SkRect* rawBounds, |
| bool skipMaskFilterLayer); |
| |
| AutoLayerForImageFilter(const AutoLayerForImageFilter&) = delete; |
| AutoLayerForImageFilter& operator=(const AutoLayerForImageFilter&) = delete; |
| AutoLayerForImageFilter(AutoLayerForImageFilter&&); |
| AutoLayerForImageFilter& operator=(AutoLayerForImageFilter&&); |
| |
| ~AutoLayerForImageFilter(); |
| |
| const SkPaint& paint() const { return fPaint; } |
| |
| // This is public so that a canvas can attempt to specially handle mask filters, specifically |
| // for blurs, and then if the attempt fails fall back on a regular draw with the same autolayer. |
| void addMaskFilterLayer(const SkRect* drawBounds); |
| |
| private: |
| void addImageFilterLayer(const SkRect* drawBounds); |
| |
| void addLayer(const SkPaint& restorePaint, const SkRect* drawBounds, bool coverageOnly); |
| |
| SkPaint fPaint; |
| SkCanvas* fCanvas; |
| int fTempLayersForFilters; |
| |
| SkDEBUGCODE(int fSaveCount;) |
| }; |
| |
| #endif |