Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkBlitter_Sprite.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
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
19#include "src/core/SkBlitter.h"
28
29#include <cstdint>
30#include <cstring>
31#include <optional>
32#include <utility>
33
34struct SkIRect;
35struct SkMask;
36
38
41
42bool SkSpriteBlitter::setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) {
43 fDst = dst;
44 fLeft = left;
45 fTop = top;
46 fPaint = &paint;
47 return true;
48}
49
50void SkSpriteBlitter::blitH(int x, int y, int width) {
51 SkDEBUGFAIL("how did we get here?");
52
53 // Fallback to blitRect.
54 this->blitRect(x, y, width, 1);
55}
56
57void SkSpriteBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) {
58 SkDEBUGFAIL("how did we get here?");
59
60 // No fallback strategy.
61}
62
63void SkSpriteBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
64 SkDEBUGFAIL("how did we get here?");
65
66 // Fall back to superclass if the code gets here in release mode.
67 INHERITED::blitV(x, y, height, alpha);
68}
69
70void SkSpriteBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
71 SkDEBUGFAIL("how did we get here?");
72
73 // Fall back to superclass if the code gets here in release mode.
75}
76
77///////////////////////////////////////////////////////////////////////////////
78
80public:
81 static bool Supports(const SkPixmap& dst, const SkPixmap& src, const SkPaint& paint) {
82 // the caller has already inspected the colorspace on src and dst
83 SkASSERT(0 == SkColorSpaceXformSteps(src,dst).flags.mask());
84
85 if (dst.colorType() != src.colorType()) {
86 return false;
87 }
88 if (paint.getMaskFilter() || paint.getColorFilter() || paint.getImageFilter()) {
89 return false;
90 }
91 if (0xFF != paint.getAlpha()) {
92 return false;
93 }
94 const auto mode = paint.asBlendMode();
95 return mode == SkBlendMode::kSrc || (mode == SkBlendMode::kSrcOver && src.isOpaque());
96 }
97
99 : INHERITED(src) {}
100
101 void blitRect(int x, int y, int width, int height) override {
103 SkASSERT(width > 0 && height > 0);
104
105 char* dst = (char*)fDst.writable_addr(x, y);
106 const char* src = (const char*)fSource.addr(x - fLeft, y - fTop);
107 const size_t dstRB = fDst.rowBytes();
108 const size_t srcRB = fSource.rowBytes();
109 const size_t bytesToCopy = width << fSource.shiftPerPixel();
110
111 while (height --> 0) {
112 memcpy(dst, src, bytesToCopy);
113 dst += dstRB;
114 src += srcRB;
115 }
116 }
117
118private:
119 using INHERITED = SkSpriteBlitter;
120};
121
123public:
125 sk_sp<SkShader> clipShader)
126 : INHERITED(src)
127 , fAlloc(alloc)
128 , fBlitter(nullptr)
129 , fSrcPtr{nullptr, 0}
130 , fClipShader(std::move(clipShader))
131 {}
132
133 bool setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override {
134 fDst = dst;
135 fLeft = left;
136 fTop = top;
137 fPaintColor = paint.getColor4f();
138
139 SkRasterPipeline p(fAlloc);
140 p.appendLoad(fSource.colorType(), &fSrcPtr);
141
143 // The color for A8 images comes from the (sRGB) paint color.
144 p.appendSetRGB(fAlloc, fPaintColor);
145 p.append(SkRasterPipelineOp::premul);
146 }
147 if (auto dstCS = fDst.colorSpace()) {
148 auto srcCS = fSource.colorSpace();
149 if (!srcCS || SkColorTypeIsAlphaOnly(fSource.colorType())) {
150 // We treat untagged images as sRGB.
151 // Alpha-only images get their r,g,b from the paint color, so they're also sRGB.
152 srcCS = sk_srgb_singleton();
153 }
154 auto srcAT = fSource.isOpaque() ? kOpaque_SkAlphaType
156 fAlloc->make<SkColorSpaceXformSteps>(srcCS, srcAT,
157 dstCS, kPremul_SkAlphaType)
158 ->apply(&p);
159 }
160 if (fPaintColor.fA != 1.0f) {
161 p.append(SkRasterPipelineOp::scale_1_float, &fPaintColor.fA);
162 }
163
164 bool is_opaque = fSource.isOpaque() && fPaintColor.fA == 1.0f;
165 fBlitter = SkCreateRasterPipelineBlitter(fDst, paint, p, is_opaque, fAlloc, fClipShader);
166 return fBlitter != nullptr;
167 }
168
169 void blitRect(int x, int y, int width, int height) override {
170 fSrcPtr.stride = fSource.rowBytesAsPixels();
171
172 // We really want fSrcPtr.pixels = fSource.addr(-fLeft, -fTop) here, but that asserts.
173 // Instead we ask for addr(-fLeft+x, -fTop+y), then back up (x,y) manually.
174 // Representing bpp as a size_t keeps all this math in size_t instead of int,
175 // which could wrap around with large enough fSrcPtr.stride and y.
176 size_t bpp = fSource.info().bytesPerPixel();
177 fSrcPtr.pixels = (char*)fSource.writable_addr(-fLeft+x, -fTop+y) - bpp * x
178 - bpp * y * fSrcPtr.stride;
179
180 fBlitter->blitRect(x,y,width,height);
181 }
182
183private:
184 SkArenaAlloc* fAlloc;
185 SkBlitter* fBlitter;
187 SkColor4f fPaintColor;
188 sk_sp<SkShader> fClipShader;
189
190 using INHERITED = SkSpriteBlitter;
191};
192
193// returning null means the caller will call SkBlitter::Choose() and
194// have wrapped the source bitmap inside a shader
196 const SkPixmap& source, int left, int top,
197 SkArenaAlloc* alloc, sk_sp<SkShader> clipShader) {
198 /* We currently ignore antialiasing and filtertype, meaning we will take our
199 special blitters regardless of these settings. Ignoring filtertype seems fine
200 since by definition there is no scale in the matrix. Ignoring antialiasing is
201 a bit of a hack, since we "could" pass in the fractional left/top for the bitmap,
202 and respect that by blending the edges of the bitmap against the device. To support
203 this we could either add more special blitters here, or detect antialiasing in the
204 paint and return null if it is set, forcing the client to take the slow shader case
205 (which does respect soft edges).
206 */
207 SkASSERT(alloc != nullptr);
208
209 // TODO: in principle SkRasterPipelineSpriteBlitter could be made to handle this.
211 return nullptr;
212 }
213
214 SkSpriteBlitter* blitter = nullptr;
215
217 // Do not use any of these optimized memory blitters
218 } else if (0 == SkColorSpaceXformSteps(source,dst).flags.mask() && !clipShader) {
219 if (!blitter && SkSpriteBlitter_Memcpy::Supports(dst, source, paint)) {
220 blitter = alloc->make<SkSpriteBlitter_Memcpy>(source);
221 }
222 if (!blitter) {
223 switch (dst.colorType()) {
224 case kN32_SkColorType:
225 blitter = SkSpriteBlitter::ChooseL32(source, paint, alloc);
226 break;
227 default:
228 break;
229 }
230 }
231 }
232 if (!blitter && !paint.getMaskFilter()) {
233 blitter = alloc->make<SkRasterPipelineSpriteBlitter>(source, alloc, clipShader);
234 }
235
236 if (blitter && blitter->setup(dst, left,top, paint)) {
237 return blitter;
238 }
239
240 return nullptr;
241}
kUnpremul_SkAlphaType
@ kOpaque_SkAlphaType
pixel is opaque
Definition SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition SkAlphaType.h:29
#define SkDEBUGFAIL(message)
Definition SkAssert.h:118
#define SkASSERT(cond)
Definition SkAssert.h:116
@ kSrcOver
r = s + (1-sa)*d
bool gSkForceRasterPipelineBlitter
Definition SkBlitter.cpp:44
SkColorSpace * sk_srgb_singleton()
uint8_t SkAlpha
Definition SkColor.h:26
SkBlitter * SkCreateRasterPipelineBlitter(const SkPixmap &, const SkPaint &, const SkMatrix &ctm, SkArenaAlloc *, sk_sp< SkShader > clipShader, const SkSurfaceProps &props)
static bool SkColorTypeIsAlphaOnly(SkColorType ct)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition SkPath.cpp:3824
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool apply(Pass *pass, SkRecord *record)
auto make(Ctor &&ctor) -> decltype(ctor(nullptr))
SkAlphaType alphaType() const
Definition SkBitmap.h:162
static SkBlitter * ChooseSprite(const SkPixmap &dst, const SkPaint &, const SkPixmap &src, int left, int top, SkArenaAlloc *, sk_sp< SkShader > clipShader)
virtual void blitMask(const SkMask &, const SkIRect &clip)
virtual void blitV(int x, int y, int height, SkAlpha alpha)
Blit a vertical run of pixels with a constant alpha value.
virtual void blitRect(int x, int y, int width, int height)
Blit a solid rectangle one or more pixels wide.
size_t rowBytes() const
Definition SkPixmap.h:145
SkColorType colorType() const
Definition SkPixmap.h:173
bool isOpaque() const
Definition SkPixmap.h:201
SkColorSpace * colorSpace() const
Definition SkPixmap.cpp:61
const SkImageInfo & info() const
Definition SkPixmap.h:135
int rowBytesAsPixels() const
Definition SkPixmap.h:214
void * writable_addr() const
Definition SkPixmap.h:483
const void * addr() const
Definition SkPixmap.h:153
int shiftPerPixel() const
Definition SkPixmap.h:221
void blitRect(int x, int y, int width, int height) override
Blit a solid rectangle one or more pixels wide.
bool setup(const SkPixmap &dst, int left, int top, const SkPaint &paint) override
SkRasterPipelineSpriteBlitter(const SkPixmap &src, SkArenaAlloc *alloc, sk_sp< SkShader > clipShader)
static bool Supports(const SkPixmap &dst, const SkPixmap &src, const SkPaint &paint)
void blitRect(int x, int y, int width, int height) override
Blit a solid rectangle one or more pixels wide.
SkSpriteBlitter_Memcpy(const SkPixmap &src)
SkSpriteBlitter(const SkPixmap &source)
const SkPaint * fPaint
const SkPixmap fSource
static SkSpriteBlitter * ChooseL32(const SkPixmap &source, const SkPaint &, SkArenaAlloc *)
void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override
void blitV(int x, int y, int height, SkAlpha alpha) override
Blit a vertical run of pixels with a constant alpha value.
void blitRect(int x, int y, int width, int height) override=0
Blit a solid rectangle one or more pixels wide.
void blitH(int x, int y, int width) override
Blit a horizontal run of one or more pixels.
virtual bool setup(const SkPixmap &dst, int left, int top, const SkPaint &)
void blitMask(const SkMask &, const SkIRect &clip) override
const Paint & paint
SkBitmap source
Definition examples.cpp:28
FlutterSemanticsFlag flags
double y
double x
Definition ref_ptr.h:256
bool gSkForceRasterPipelineBlitter
Definition SkBlitter.cpp:44
int32_t height
int32_t width
int bytesPerPixel() const