/src/skia/src/core/SkPixmap.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2015 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 "include/core/SkPixmap.h" |
9 | | |
10 | | #include "include/core/SkBitmap.h" |
11 | | #include "include/core/SkData.h" |
12 | | #include "include/core/SkSurface.h" |
13 | | #include "include/core/SkUnPreMultiply.h" |
14 | | #include "include/private/SkColorData.h" |
15 | | #include "include/private/SkHalf.h" |
16 | | #include "include/private/SkImageInfoPriv.h" |
17 | | #include "include/private/SkNx.h" |
18 | | #include "include/private/SkTPin.h" |
19 | | #include "include/private/SkTemplates.h" |
20 | | #include "include/private/SkTo.h" |
21 | | #include "src/core/SkConvertPixels.h" |
22 | | #include "src/core/SkDraw.h" |
23 | | #include "src/core/SkMask.h" |
24 | | #include "src/core/SkMatrixProvider.h" |
25 | | #include "src/core/SkPixmapPriv.h" |
26 | | #include "src/core/SkRasterClip.h" |
27 | | #include "src/core/SkUtils.h" |
28 | | #include "src/image/SkReadPixelsRec.h" |
29 | | #include "src/shaders/SkImageShader.h" |
30 | | |
31 | | #include <utility> |
32 | | |
33 | | ///////////////////////////////////////////////////////////////////////////////////////////////// |
34 | | |
35 | 323k | void SkPixmap::reset() { |
36 | 323k | fPixels = nullptr; |
37 | 323k | fRowBytes = 0; |
38 | 323k | fInfo = SkImageInfo::MakeUnknown(); |
39 | 323k | } |
40 | | |
41 | 1.88M | void SkPixmap::reset(const SkImageInfo& info, const void* addr, size_t rowBytes) { |
42 | 1.88M | if (addr) { |
43 | 593k | SkASSERT(info.validRowBytes(rowBytes)); |
44 | 593k | } |
45 | 1.88M | fPixels = addr; |
46 | 1.88M | fRowBytes = rowBytes; |
47 | 1.88M | fInfo = info; |
48 | 1.88M | } |
49 | | |
50 | 7.07k | bool SkPixmap::reset(const SkMask& src) { |
51 | 7.07k | if (SkMask::kA8_Format == src.fFormat) { |
52 | 7.07k | this->reset(SkImageInfo::MakeA8(src.fBounds.width(), src.fBounds.height()), |
53 | 7.07k | src.fImage, src.fRowBytes); |
54 | 7.07k | return true; |
55 | 7.07k | } |
56 | 0 | this->reset(); |
57 | 0 | return false; |
58 | 0 | } |
59 | | |
60 | 339 | void SkPixmap::setColorSpace(sk_sp<SkColorSpace> cs) { |
61 | 339 | fInfo = fInfo.makeColorSpace(std::move(cs)); |
62 | 339 | } |
63 | | |
64 | 133k | bool SkPixmap::extractSubset(SkPixmap* result, const SkIRect& subset) const { |
65 | 133k | SkIRect srcRect, r; |
66 | 133k | srcRect.setWH(this->width(), this->height()); |
67 | 133k | if (!r.intersect(srcRect, subset)) { |
68 | 0 | return false; // r is empty (i.e. no intersection) |
69 | 0 | } |
70 | | |
71 | | // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have |
72 | | // exited above. |
73 | 133k | SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); |
74 | 133k | SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); |
75 | | |
76 | 133k | const void* pixels = nullptr; |
77 | 133k | if (fPixels) { |
78 | 133k | const size_t bpp = fInfo.bytesPerPixel(); |
79 | 133k | pixels = (const uint8_t*)fPixels + r.fTop * fRowBytes + r.fLeft * bpp; |
80 | 133k | } |
81 | 133k | result->reset(fInfo.makeDimensions(r.size()), pixels, fRowBytes); |
82 | 133k | return true; |
83 | 133k | } |
84 | | |
85 | | // This is the same as SkPixmap::addr(x,y), but this version gets inlined, while the public |
86 | | // method does not. Perhaps we could bloat it so it can be inlined, but that would grow code-size |
87 | | // everywhere, instead of just here (on behalf of getAlphaf()). |
88 | 0 | static const void* fast_getaddr(const SkPixmap& pm, int x, int y) { |
89 | 0 | x <<= SkColorTypeShiftPerPixel(pm.colorType()); |
90 | 0 | return static_cast<const char*>(pm.addr()) + y * pm.rowBytes() + x; |
91 | 0 | } |
92 | | |
93 | 0 | float SkPixmap::getAlphaf(int x, int y) const { |
94 | 0 | SkASSERT(this->addr()); |
95 | 0 | SkASSERT((unsigned)x < (unsigned)this->width()); |
96 | 0 | SkASSERT((unsigned)y < (unsigned)this->height()); |
97 | |
|
98 | 0 | float value = 0; |
99 | 0 | const void* srcPtr = fast_getaddr(*this, x, y); |
100 | |
|
101 | 0 | switch (this->colorType()) { |
102 | 0 | case kUnknown_SkColorType: |
103 | 0 | return 0; |
104 | 0 | case kGray_8_SkColorType: |
105 | 0 | case kR8G8_unorm_SkColorType: |
106 | 0 | case kR16G16_unorm_SkColorType: |
107 | 0 | case kR16G16_float_SkColorType: |
108 | 0 | case kRGB_565_SkColorType: |
109 | 0 | case kRGB_888x_SkColorType: |
110 | 0 | case kRGB_101010x_SkColorType: |
111 | 0 | case kBGR_101010x_SkColorType: |
112 | 0 | return 1; |
113 | 0 | case kAlpha_8_SkColorType: |
114 | 0 | value = static_cast<const uint8_t*>(srcPtr)[0] * (1.0f/255); |
115 | 0 | break; |
116 | 0 | case kA16_unorm_SkColorType: |
117 | 0 | value = static_cast<const uint16_t*>(srcPtr)[0] * (1.0f/65535); |
118 | 0 | break; |
119 | 0 | case kA16_float_SkColorType: { |
120 | 0 | SkHalf half = static_cast<const SkHalf*>(srcPtr)[0]; |
121 | 0 | value = SkHalfToFloat(half); |
122 | 0 | break; |
123 | 0 | } |
124 | 0 | case kARGB_4444_SkColorType: { |
125 | 0 | uint16_t u16 = static_cast<const uint16_t*>(srcPtr)[0]; |
126 | 0 | value = SkGetPackedA4444(u16) * (1.0f/15); |
127 | 0 | break; |
128 | 0 | } |
129 | 0 | case kRGBA_8888_SkColorType: |
130 | 0 | case kBGRA_8888_SkColorType: |
131 | 0 | value = static_cast<const uint8_t*>(srcPtr)[3] * (1.0f/255); |
132 | 0 | break; |
133 | 0 | case kRGBA_1010102_SkColorType: |
134 | 0 | case kBGRA_1010102_SkColorType: { |
135 | 0 | uint32_t u32 = static_cast<const uint32_t*>(srcPtr)[0]; |
136 | 0 | value = (u32 >> 30) * (1.0f/3); |
137 | 0 | break; |
138 | 0 | } |
139 | 0 | case kR16G16B16A16_unorm_SkColorType: { |
140 | 0 | uint64_t u64 = static_cast<const uint64_t*>(srcPtr)[0]; |
141 | 0 | value = (u64 >> 48) * (1.0f/65535); |
142 | 0 | break; |
143 | 0 | } |
144 | 0 | case kRGBA_F16Norm_SkColorType: |
145 | 0 | case kRGBA_F16_SkColorType: { |
146 | 0 | uint64_t px; |
147 | 0 | memcpy(&px, srcPtr, sizeof(px)); |
148 | 0 | value = SkHalfToFloat_finite_ftz(px)[3]; |
149 | 0 | break; |
150 | 0 | } |
151 | 0 | case kRGBA_F32_SkColorType: |
152 | 0 | value = static_cast<const float*>(srcPtr)[3]; |
153 | 0 | break; |
154 | 0 | } |
155 | 0 | return value; |
156 | 0 | } Unexecuted instantiation: SkPixmap::getAlphaf(int, int) const Unexecuted instantiation: SkPixmap::getAlphaf(int, int) const |
157 | | |
158 | | bool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, |
159 | 4.80k | int x, int y) const { |
160 | 4.80k | if (!SkImageInfoValidConversion(dstInfo, fInfo)) { |
161 | 0 | return false; |
162 | 0 | } |
163 | | |
164 | 4.80k | SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, x, y); |
165 | 4.80k | if (!rec.trim(fInfo.width(), fInfo.height())) { |
166 | 0 | return false; |
167 | 0 | } |
168 | | |
169 | 4.80k | const void* srcPixels = this->addr(rec.fX, rec.fY); |
170 | 4.80k | const SkImageInfo srcInfo = fInfo.makeDimensions(rec.fInfo.dimensions()); |
171 | 4.80k | return SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels, |
172 | 4.80k | this->rowBytes()); |
173 | 4.80k | } |
174 | | |
175 | 15.9k | bool SkPixmap::erase(SkColor color, const SkIRect& subset) const { |
176 | 15.9k | return this->erase(SkColor4f::FromColor(color), &subset); |
177 | 15.9k | } |
178 | | |
179 | 15.9k | bool SkPixmap::erase(const SkColor4f& color, SkColorSpace* cs, const SkIRect* subset) const { |
180 | 15.9k | SkPaint paint; |
181 | 15.9k | paint.setBlendMode(SkBlendMode::kSrc); |
182 | 15.9k | paint.setColor4f(color, cs); |
183 | | |
184 | 15.9k | SkIRect clip = this->bounds(); |
185 | 15.9k | if (subset && !clip.intersect(*subset)) { |
186 | 0 | return false; |
187 | 0 | } |
188 | 15.9k | SkRasterClip rc{clip}; |
189 | | |
190 | 15.9k | SkDraw draw; |
191 | 15.9k | SkSimpleMatrixProvider matrixProvider(SkMatrix::I()); |
192 | 15.9k | draw.fDst = *this; |
193 | 15.9k | draw.fMatrixProvider = &matrixProvider; |
194 | 15.9k | draw.fRC = &rc; |
195 | | |
196 | 15.9k | draw.drawPaint(paint); |
197 | 15.9k | return true; |
198 | 15.9k | } |
199 | | |
200 | 0 | bool SkPixmap::scalePixels(const SkPixmap& actualDst, const SkSamplingOptions& sampling) const { |
201 | | // We may need to tweak how we interpret these just a little below, so we make copies. |
202 | 0 | SkPixmap src = *this, |
203 | 0 | dst = actualDst; |
204 | | |
205 | | // Can't do anthing with empty src or dst |
206 | 0 | if (src.width() <= 0 || src.height() <= 0 || |
207 | 0 | dst.width() <= 0 || dst.height() <= 0) { |
208 | 0 | return false; |
209 | 0 | } |
210 | | |
211 | | // no scaling involved? |
212 | 0 | if (src.width() == dst.width() && src.height() == dst.height()) { |
213 | 0 | return src.readPixels(dst); |
214 | 0 | } |
215 | | |
216 | | // If src and dst are both unpremul, we'll fake the source out to appear as if premul, |
217 | | // and mark the destination as opaque. This odd combination allows us to scale unpremul |
218 | | // pixels without ever premultiplying them (perhaps losing information in the color channels). |
219 | | // This is an idiosyncratic feature of scalePixels(), and is tested by scalepixels_unpremul GM. |
220 | 0 | bool clampAsIfUnpremul = false; |
221 | 0 | if (src.alphaType() == kUnpremul_SkAlphaType && |
222 | 0 | dst.alphaType() == kUnpremul_SkAlphaType) { |
223 | 0 | src.reset(src.info().makeAlphaType(kPremul_SkAlphaType), src.addr(), src.rowBytes()); |
224 | 0 | dst.reset(dst.info().makeAlphaType(kOpaque_SkAlphaType), dst.addr(), dst.rowBytes()); |
225 | | |
226 | | // We'll need to tell the image shader to clamp to [0,1] instead of the |
227 | | // usual [0,a] when using a bicubic scaling (kHigh_SkFilterQuality). |
228 | 0 | clampAsIfUnpremul = true; |
229 | 0 | } |
230 | |
|
231 | 0 | SkBitmap bitmap; |
232 | 0 | if (!bitmap.installPixels(src)) { |
233 | 0 | return false; |
234 | 0 | } |
235 | 0 | bitmap.setImmutable(); // Don't copy when we create an image. |
236 | |
|
237 | 0 | SkMatrix scale = SkMatrix::RectToRect(SkRect::Make(src.bounds()), SkRect::Make(dst.bounds())); |
238 | |
|
239 | 0 | sk_sp<SkShader> shader = SkImageShader::Make(bitmap.asImage(), |
240 | 0 | SkTileMode::kClamp, |
241 | 0 | SkTileMode::kClamp, |
242 | 0 | sampling, |
243 | 0 | &scale, |
244 | 0 | clampAsIfUnpremul); |
245 | |
|
246 | 0 | sk_sp<SkSurface> surface = SkSurface::MakeRasterDirect(dst.info(), |
247 | 0 | dst.writable_addr(), |
248 | 0 | dst.rowBytes()); |
249 | 0 | if (!shader || !surface) { |
250 | 0 | return false; |
251 | 0 | } |
252 | | |
253 | 0 | SkPaint paint; |
254 | 0 | paint.setBlendMode(SkBlendMode::kSrc); |
255 | 0 | paint.setShader(std::move(shader)); |
256 | 0 | surface->getCanvas()->drawPaint(paint); |
257 | 0 | return true; |
258 | 0 | } |
259 | | |
260 | | ////////////////////////////////////////////////////////////////////////////////////////////////// |
261 | | |
262 | 0 | SkColor SkPixmap::getColor(int x, int y) const { |
263 | 0 | SkASSERT(this->addr()); |
264 | 0 | SkASSERT((unsigned)x < (unsigned)this->width()); |
265 | 0 | SkASSERT((unsigned)y < (unsigned)this->height()); |
266 | |
|
267 | 0 | const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType()); |
268 | 0 | auto toColor = [needsUnpremul](uint32_t maybePremulColor) { |
269 | 0 | return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor) |
270 | 0 | : SkSwizzle_BGRA_to_PMColor(maybePremulColor); |
271 | 0 | }; Unexecuted instantiation: SkPixmap.cpp:SkPixmap::getColor(int, int) const::$_0::operator()(unsigned int) const Unexecuted instantiation: SkPixmap.cpp:SkPixmap::getColor(int, int) const::$_9::operator()(unsigned int) const |
272 | |
|
273 | 0 | switch (this->colorType()) { |
274 | 0 | case kGray_8_SkColorType: { |
275 | 0 | uint8_t value = *this->addr8(x, y); |
276 | 0 | return SkColorSetRGB(value, value, value); |
277 | 0 | } |
278 | 0 | case kAlpha_8_SkColorType: { |
279 | 0 | return SkColorSetA(0, *this->addr8(x, y)); |
280 | 0 | } |
281 | 0 | case kA16_unorm_SkColorType: { |
282 | 0 | uint16_t value = *this->addr16(x, y); |
283 | 0 | return SkColorSetA(0, value * (255 / 65535.0f)); |
284 | 0 | } |
285 | 0 | case kA16_float_SkColorType: { |
286 | 0 | SkHalf value = *this->addr16(x, y); |
287 | 0 | return SkColorSetA(0, 255 * SkHalfToFloat(value)); |
288 | 0 | } |
289 | 0 | case kRGB_565_SkColorType: { |
290 | 0 | return SkPixel16ToColor(*this->addr16(x, y)); |
291 | 0 | } |
292 | 0 | case kARGB_4444_SkColorType: { |
293 | 0 | uint16_t value = *this->addr16(x, y); |
294 | 0 | SkPMColor c = SkPixel4444ToPixel32(value); |
295 | 0 | return toColor(c); |
296 | 0 | } |
297 | 0 | case kR8G8_unorm_SkColorType: { |
298 | 0 | uint16_t value = *this->addr16(x, y); |
299 | 0 | return (uint32_t)( ((value >> 0) & 0xff) ) << 16 |
300 | 0 | | (uint32_t)( ((value >> 8) & 0xff) ) << 8 |
301 | 0 | | 0xff000000; |
302 | 0 | } |
303 | 0 | case kR16G16_unorm_SkColorType: { |
304 | 0 | uint32_t value = *this->addr32(x, y); |
305 | 0 | return (uint32_t)( ((value >> 0) & 0xffff) * (255/65535.0f) ) << 16 |
306 | 0 | | (uint32_t)( ((value >> 16) & 0xffff) * (255/65535.0f) ) << 8 |
307 | 0 | | 0xff000000; |
308 | 0 | } |
309 | 0 | case kR16G16_float_SkColorType: { |
310 | 0 | uint32_t value = *this->addr32(x, y); |
311 | 0 | uint32_t r = 255 * SkHalfToFloat((value >> 0) & 0xffff); |
312 | 0 | uint32_t g = 255 * SkHalfToFloat((value >> 16) & 0xffff); |
313 | 0 | return (r << 16) | (g << 8) | 0xff000000; |
314 | 0 | } |
315 | 0 | case kRGB_888x_SkColorType: { |
316 | 0 | uint32_t value = *this->addr32(x, y); |
317 | 0 | return SkSwizzle_RB(value | 0xff000000); |
318 | 0 | } |
319 | 0 | case kBGRA_8888_SkColorType: { |
320 | 0 | uint32_t value = *this->addr32(x, y); |
321 | 0 | SkPMColor c = SkSwizzle_BGRA_to_PMColor(value); |
322 | 0 | return toColor(c); |
323 | 0 | } |
324 | 0 | case kRGBA_8888_SkColorType: { |
325 | 0 | uint32_t value = *this->addr32(x, y); |
326 | 0 | SkPMColor c = SkSwizzle_RGBA_to_PMColor(value); |
327 | 0 | return toColor(c); |
328 | 0 | } |
329 | 0 | case kRGB_101010x_SkColorType: { |
330 | 0 | uint32_t value = *this->addr32(x, y); |
331 | | // Convert 10-bit rgb to 8-bit bgr, and mask in 0xff alpha at the top. |
332 | 0 | return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 16 |
333 | 0 | | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8 |
334 | 0 | | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 0 |
335 | 0 | | 0xff000000; |
336 | 0 | } |
337 | 0 | case kBGR_101010x_SkColorType: { |
338 | 0 | uint32_t value = *this->addr32(x, y); |
339 | | // Convert 10-bit bgr to 8-bit bgr, and mask in 0xff alpha at the top. |
340 | 0 | return (uint32_t)( ((value >> 0) & 0x3ff) * (255/1023.0f) ) << 0 |
341 | 0 | | (uint32_t)( ((value >> 10) & 0x3ff) * (255/1023.0f) ) << 8 |
342 | 0 | | (uint32_t)( ((value >> 20) & 0x3ff) * (255/1023.0f) ) << 16 |
343 | 0 | | 0xff000000; |
344 | 0 | } |
345 | 0 | case kRGBA_1010102_SkColorType: |
346 | 0 | case kBGRA_1010102_SkColorType: { |
347 | 0 | uint32_t value = *this->addr32(x, y); |
348 | |
|
349 | 0 | float r = ((value >> 0) & 0x3ff) * (1/1023.0f), |
350 | 0 | g = ((value >> 10) & 0x3ff) * (1/1023.0f), |
351 | 0 | b = ((value >> 20) & 0x3ff) * (1/1023.0f), |
352 | 0 | a = ((value >> 30) & 0x3 ) * (1/ 3.0f); |
353 | 0 | if (this->colorType() == kBGRA_1010102_SkColorType) { |
354 | 0 | std::swap(r,b); |
355 | 0 | } |
356 | 0 | if (a != 0 && needsUnpremul) { |
357 | 0 | r = SkTPin(r/a, 0.0f, 1.0f); |
358 | 0 | g = SkTPin(g/a, 0.0f, 1.0f); |
359 | 0 | b = SkTPin(b/a, 0.0f, 1.0f); |
360 | 0 | } |
361 | 0 | return (uint32_t)( r * 255.0f ) << 16 |
362 | 0 | | (uint32_t)( g * 255.0f ) << 8 |
363 | 0 | | (uint32_t)( b * 255.0f ) << 0 |
364 | 0 | | (uint32_t)( a * 255.0f ) << 24; |
365 | 0 | } |
366 | 0 | case kR16G16B16A16_unorm_SkColorType: { |
367 | 0 | uint64_t value = *this->addr64(x, y); |
368 | |
|
369 | 0 | float r = ((value ) & 0xffff) * (1/65535.0f), |
370 | 0 | g = ((value >> 16) & 0xffff) * (1/65535.0f), |
371 | 0 | b = ((value >> 32) & 0xffff) * (1/65535.0f), |
372 | 0 | a = ((value >> 48) & 0xffff) * (1/65535.0f); |
373 | 0 | if (a != 0 && needsUnpremul) { |
374 | 0 | r *= (1.0f/a); |
375 | 0 | g *= (1.0f/a); |
376 | 0 | b *= (1.0f/a); |
377 | 0 | } |
378 | 0 | return (uint32_t)( r * 255.0f ) << 16 |
379 | 0 | | (uint32_t)( g * 255.0f ) << 8 |
380 | 0 | | (uint32_t)( b * 255.0f ) << 0 |
381 | 0 | | (uint32_t)( a * 255.0f ) << 24; |
382 | 0 | } |
383 | 0 | case kRGBA_F16Norm_SkColorType: |
384 | 0 | case kRGBA_F16_SkColorType: { |
385 | 0 | const uint64_t* addr = |
386 | 0 | (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x; |
387 | 0 | Sk4f p4 = SkHalfToFloat_finite_ftz(*addr); |
388 | 0 | if (p4[3] && needsUnpremul) { |
389 | 0 | float inva = 1 / p4[3]; |
390 | 0 | p4 = p4 * Sk4f(inva, inva, inva, 1); |
391 | 0 | } |
392 | 0 | SkColor c; |
393 | 0 | SkNx_cast<uint8_t>(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); |
394 | | // p4 is RGBA, but we want BGRA, so we need to swap next |
395 | 0 | return SkSwizzle_RB(c); |
396 | 0 | } |
397 | 0 | case kRGBA_F32_SkColorType: { |
398 | 0 | const float* rgba = |
399 | 0 | (const float*)fPixels + 4*y*(fRowBytes >> 4) + 4*x; |
400 | 0 | Sk4f p4 = Sk4f::Load(rgba); |
401 | | // From here on, just like F16: |
402 | 0 | if (p4[3] && needsUnpremul) { |
403 | 0 | float inva = 1 / p4[3]; |
404 | 0 | p4 = p4 * Sk4f(inva, inva, inva, 1); |
405 | 0 | } |
406 | 0 | SkColor c; |
407 | 0 | SkNx_cast<uint8_t>(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); |
408 | | // p4 is RGBA, but we want BGRA, so we need to swap next |
409 | 0 | return SkSwizzle_RB(c); |
410 | 0 | } |
411 | 0 | case kUnknown_SkColorType: |
412 | 0 | break; |
413 | 0 | } |
414 | 0 | SkDEBUGFAIL(""); |
415 | 0 | return SkColorSetARGB(0, 0, 0, 0); |
416 | 0 | } Unexecuted instantiation: SkPixmap::getColor(int, int) const Unexecuted instantiation: SkPixmap::getColor(int, int) const |
417 | | |
418 | 0 | bool SkPixmap::computeIsOpaque() const { |
419 | 0 | const int height = this->height(); |
420 | 0 | const int width = this->width(); |
421 | |
|
422 | 0 | switch (this->colorType()) { |
423 | 0 | case kAlpha_8_SkColorType: { |
424 | 0 | unsigned a = 0xFF; |
425 | 0 | for (int y = 0; y < height; ++y) { |
426 | 0 | const uint8_t* row = this->addr8(0, y); |
427 | 0 | for (int x = 0; x < width; ++x) { |
428 | 0 | a &= row[x]; |
429 | 0 | } |
430 | 0 | if (0xFF != a) { |
431 | 0 | return false; |
432 | 0 | } |
433 | 0 | } |
434 | 0 | return true; |
435 | 0 | } |
436 | 0 | case kA16_unorm_SkColorType: { |
437 | 0 | unsigned a = 0xFFFF; |
438 | 0 | for (int y = 0; y < height; ++y) { |
439 | 0 | const uint16_t* row = this->addr16(0, y); |
440 | 0 | for (int x = 0; x < width; ++x) { |
441 | 0 | a &= row[x]; |
442 | 0 | } |
443 | 0 | if (0xFFFF != a) { |
444 | 0 | return false; |
445 | 0 | } |
446 | 0 | } |
447 | 0 | return true; |
448 | 0 | } |
449 | 0 | case kA16_float_SkColorType: { |
450 | 0 | for (int y = 0; y < height; ++y) { |
451 | 0 | const SkHalf* row = this->addr16(0, y); |
452 | 0 | for (int x = 0; x < width; ++x) { |
453 | 0 | if (row[x] < SK_Half1) { |
454 | 0 | return false; |
455 | 0 | } |
456 | 0 | } |
457 | 0 | } |
458 | 0 | return true; |
459 | 0 | } |
460 | 0 | case kRGB_565_SkColorType: |
461 | 0 | case kGray_8_SkColorType: |
462 | 0 | case kR8G8_unorm_SkColorType: |
463 | 0 | case kR16G16_unorm_SkColorType: |
464 | 0 | case kR16G16_float_SkColorType: |
465 | 0 | case kRGB_888x_SkColorType: |
466 | 0 | case kRGB_101010x_SkColorType: |
467 | 0 | case kBGR_101010x_SkColorType: |
468 | 0 | return true; |
469 | 0 | break; |
470 | 0 | case kARGB_4444_SkColorType: { |
471 | 0 | unsigned c = 0xFFFF; |
472 | 0 | for (int y = 0; y < height; ++y) { |
473 | 0 | const SkPMColor16* row = this->addr16(0, y); |
474 | 0 | for (int x = 0; x < width; ++x) { |
475 | 0 | c &= row[x]; |
476 | 0 | } |
477 | 0 | if (0xF != SkGetPackedA4444(c)) { |
478 | 0 | return false; |
479 | 0 | } |
480 | 0 | } |
481 | 0 | return true; |
482 | 0 | } |
483 | 0 | case kBGRA_8888_SkColorType: |
484 | 0 | case kRGBA_8888_SkColorType: { |
485 | 0 | SkPMColor c = (SkPMColor)~0; |
486 | 0 | for (int y = 0; y < height; ++y) { |
487 | 0 | const SkPMColor* row = this->addr32(0, y); |
488 | 0 | for (int x = 0; x < width; ++x) { |
489 | 0 | c &= row[x]; |
490 | 0 | } |
491 | 0 | if (0xFF != SkGetPackedA32(c)) { |
492 | 0 | return false; |
493 | 0 | } |
494 | 0 | } |
495 | 0 | return true; |
496 | 0 | } |
497 | 0 | case kRGBA_F16Norm_SkColorType: |
498 | 0 | case kRGBA_F16_SkColorType: { |
499 | 0 | const SkHalf* row = (const SkHalf*)this->addr(); |
500 | 0 | for (int y = 0; y < height; ++y) { |
501 | 0 | for (int x = 0; x < width; ++x) { |
502 | 0 | if (row[4 * x + 3] < SK_Half1) { |
503 | 0 | return false; |
504 | 0 | } |
505 | 0 | } |
506 | 0 | row += this->rowBytes() >> 1; |
507 | 0 | } |
508 | 0 | return true; |
509 | 0 | } |
510 | 0 | case kRGBA_F32_SkColorType: { |
511 | 0 | const float* row = (const float*)this->addr(); |
512 | 0 | for (int y = 0; y < height; ++y) { |
513 | 0 | for (int x = 0; x < width; ++x) { |
514 | 0 | if (row[4 * x + 3] < 1.0f) { |
515 | 0 | return false; |
516 | 0 | } |
517 | 0 | } |
518 | 0 | row += this->rowBytes() >> 2; |
519 | 0 | } |
520 | 0 | return true; |
521 | 0 | } |
522 | 0 | case kRGBA_1010102_SkColorType: |
523 | 0 | case kBGRA_1010102_SkColorType: { |
524 | 0 | uint32_t c = ~0; |
525 | 0 | for (int y = 0; y < height; ++y) { |
526 | 0 | const uint32_t* row = this->addr32(0, y); |
527 | 0 | for (int x = 0; x < width; ++x) { |
528 | 0 | c &= row[x]; |
529 | 0 | } |
530 | 0 | if (0b11 != c >> 30) { |
531 | 0 | return false; |
532 | 0 | } |
533 | 0 | } |
534 | 0 | return true; |
535 | 0 | } |
536 | 0 | case kR16G16B16A16_unorm_SkColorType: { |
537 | 0 | uint16_t acc = 0xFFFF; |
538 | 0 | for (int y = 0; y < height; ++y) { |
539 | 0 | const uint64_t* row = this->addr64(0, y); |
540 | 0 | for (int x = 0; x < width; ++x) { |
541 | 0 | acc &= (row[x] >> 48); |
542 | 0 | } |
543 | 0 | if (0xFFFF != acc) { |
544 | 0 | return false; |
545 | 0 | } |
546 | 0 | } |
547 | 0 | return true; |
548 | 0 | } |
549 | 0 | case kUnknown_SkColorType: |
550 | 0 | SkDEBUGFAIL(""); |
551 | 0 | break; |
552 | 0 | } |
553 | 0 | return false; |
554 | 0 | } Unexecuted instantiation: SkPixmap::computeIsOpaque() const Unexecuted instantiation: SkPixmap::computeIsOpaque() const |
555 | | |
556 | | ////////////////////////////////////////////////////////////////////////////////////////////////// |
557 | | |
558 | 23 | static bool draw_orientation(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin) { |
559 | 23 | auto surf = SkSurface::MakeRasterDirect(dst.info(), dst.writable_addr(), dst.rowBytes()); |
560 | 23 | if (!surf) { |
561 | 0 | return false; |
562 | 0 | } |
563 | | |
564 | 23 | SkBitmap bm; |
565 | 23 | bm.installPixels(src); |
566 | | |
567 | 23 | SkMatrix m = SkEncodedOriginToMatrix(origin, dst.width(), dst.height()); |
568 | | |
569 | 23 | SkPaint p; |
570 | 23 | p.setBlendMode(SkBlendMode::kSrc); |
571 | 23 | surf->getCanvas()->concat(m); |
572 | 23 | surf->getCanvas()->drawImage(SkImage::MakeFromBitmap(bm), 0, 0, SkSamplingOptions(), &p); |
573 | 23 | return true; |
574 | 23 | } |
575 | | |
576 | 23 | bool SkPixmapPriv::Orient(const SkPixmap& dst, const SkPixmap& src, SkEncodedOrigin origin) { |
577 | 23 | if (src.colorType() != dst.colorType()) { |
578 | 0 | return false; |
579 | 0 | } |
580 | | // note: we just ignore alphaType and colorSpace for this transformation |
581 | | |
582 | 23 | int w = src.width(); |
583 | 23 | int h = src.height(); |
584 | 23 | if (SkEncodedOriginSwapsWidthHeight(origin)) { |
585 | 8 | using std::swap; |
586 | 8 | swap(w, h); |
587 | 8 | } |
588 | 23 | if (dst.width() != w || dst.height() != h) { |
589 | 0 | return false; |
590 | 0 | } |
591 | 23 | if (w == 0 || h == 0) { |
592 | 0 | return true; |
593 | 0 | } |
594 | | |
595 | | // check for aliasing to self |
596 | 23 | if (src.addr() == dst.addr()) { |
597 | 0 | return kTopLeft_SkEncodedOrigin == origin; |
598 | 0 | } |
599 | 23 | return draw_orientation(dst, src, origin); |
600 | 23 | } |
601 | | |
602 | 17 | SkImageInfo SkPixmapPriv::SwapWidthHeight(const SkImageInfo& info) { |
603 | 17 | return info.makeWH(info.height(), info.width()); |
604 | 17 | } |
605 | | |