reed | 92fc2ae | 2015-05-22 08:06:21 -0700 | [diff] [blame] | 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 | |
Hal Canary | 4cba3fe | 2016-12-07 14:59:27 -0500 | [diff] [blame] | 8 | #include "SkBitmap.h" |
| 9 | #include "SkCanvas.h" |
Cary Clark | a4083c9 | 2017-09-15 11:59:23 -0400 | [diff] [blame] | 10 | #include "SkColorData.h" |
Matt Sarett | 485c499 | 2017-02-14 14:18:27 -0500 | [diff] [blame] | 11 | #include "SkConvertPixels.h" |
fmalita | 3a94c6c | 2016-02-04 13:09:59 -0800 | [diff] [blame] | 12 | #include "SkData.h" |
Matt Sarett | cb6266b | 2017-01-17 10:48:53 -0500 | [diff] [blame] | 13 | #include "SkImageInfoPriv.h" |
Hal Canary | 4cba3fe | 2016-12-07 14:59:27 -0500 | [diff] [blame] | 14 | #include "SkHalf.h" |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 15 | #include "SkMask.h" |
Hal Canary | 4cba3fe | 2016-12-07 14:59:27 -0500 | [diff] [blame] | 16 | #include "SkNx.h" |
reed | dd9ffea | 2016-02-18 12:39:14 -0800 | [diff] [blame] | 17 | #include "SkPM4f.h" |
Hal Canary | 4cba3fe | 2016-12-07 14:59:27 -0500 | [diff] [blame] | 18 | #include "SkPixmap.h" |
Matt Sarett | 03dd6d5 | 2017-01-23 12:15:09 -0500 | [diff] [blame] | 19 | #include "SkReadPixelsRec.h" |
Hal Canary | 4cba3fe | 2016-12-07 14:59:27 -0500 | [diff] [blame] | 20 | #include "SkSurface.h" |
| 21 | #include "SkUtils.h" |
reed | 92fc2ae | 2015-05-22 08:06:21 -0700 | [diff] [blame] | 22 | |
reed | 95d343f | 2015-05-23 13:21:06 -0700 | [diff] [blame] | 23 | ///////////////////////////////////////////////////////////////////////////////////////////////// |
| 24 | |
reed | 884e97c | 2015-05-26 11:31:54 -0700 | [diff] [blame] | 25 | void SkPixmap::reset() { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 26 | fPixels = nullptr; |
reed | 884e97c | 2015-05-26 11:31:54 -0700 | [diff] [blame] | 27 | fRowBytes = 0; |
| 28 | fInfo = SkImageInfo::MakeUnknown(); |
| 29 | } |
| 30 | |
Mike Reed | 086a427 | 2017-07-18 10:53:11 -0400 | [diff] [blame] | 31 | void SkPixmap::reset(const SkImageInfo& info, const void* addr, size_t rowBytes) { |
reed | 884e97c | 2015-05-26 11:31:54 -0700 | [diff] [blame] | 32 | if (addr) { |
| 33 | SkASSERT(info.validRowBytes(rowBytes)); |
| 34 | } |
| 35 | fPixels = addr; |
reed | 884e97c | 2015-05-26 11:31:54 -0700 | [diff] [blame] | 36 | fRowBytes = rowBytes; |
| 37 | fInfo = info; |
| 38 | } |
| 39 | |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 40 | bool SkPixmap::reset(const SkMask& src) { |
| 41 | if (SkMask::kA8_Format == src.fFormat) { |
| 42 | this->reset(SkImageInfo::MakeA8(src.fBounds.width(), src.fBounds.height()), |
Mike Reed | 086a427 | 2017-07-18 10:53:11 -0400 | [diff] [blame] | 43 | src.fImage, src.fRowBytes); |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 44 | return true; |
| 45 | } |
| 46 | this->reset(); |
| 47 | return false; |
| 48 | } |
| 49 | |
msarett | 804b461 | 2016-06-09 11:03:45 -0700 | [diff] [blame] | 50 | void SkPixmap::setColorSpace(sk_sp<SkColorSpace> cs) { |
| 51 | fInfo = fInfo.makeColorSpace(std::move(cs)); |
| 52 | } |
| 53 | |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 54 | bool SkPixmap::extractSubset(SkPixmap* result, const SkIRect& subset) const { |
| 55 | SkIRect srcRect, r; |
| 56 | srcRect.set(0, 0, this->width(), this->height()); |
| 57 | if (!r.intersect(srcRect, subset)) { |
| 58 | return false; // r is empty (i.e. no intersection) |
| 59 | } |
halcanary | 9d524f2 | 2016-03-29 09:03:52 -0700 | [diff] [blame] | 60 | |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 61 | // If the upper left of the rectangle was outside the bounds of this SkBitmap, we should have |
| 62 | // exited above. |
| 63 | SkASSERT(static_cast<unsigned>(r.fLeft) < static_cast<unsigned>(this->width())); |
| 64 | SkASSERT(static_cast<unsigned>(r.fTop) < static_cast<unsigned>(this->height())); |
| 65 | |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 66 | const void* pixels = nullptr; |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 67 | if (fPixels) { |
| 68 | const size_t bpp = fInfo.bytesPerPixel(); |
| 69 | pixels = (const uint8_t*)fPixels + r.fTop * fRowBytes + r.fLeft * bpp; |
| 70 | } |
Mike Reed | 26e9ddd | 2017-07-17 17:33:53 -0400 | [diff] [blame] | 71 | result->reset(fInfo.makeWH(r.width(), r.height()), pixels, fRowBytes); |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 72 | return true; |
| 73 | } |
| 74 | |
Matt Sarett | 3928ff8 | 2017-06-06 10:11:34 -0400 | [diff] [blame] | 75 | bool SkPixmap::readPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRB, int x, int y, |
| 76 | SkTransferFunctionBehavior behavior) const { |
Matt Sarett | 03dd6d5 | 2017-01-23 12:15:09 -0500 | [diff] [blame] | 77 | if (!SkImageInfoValidConversion(dstInfo, fInfo)) { |
reed | 95d343f | 2015-05-23 13:21:06 -0700 | [diff] [blame] | 78 | return false; |
| 79 | } |
Matt Sarett | cb6266b | 2017-01-17 10:48:53 -0500 | [diff] [blame] | 80 | |
Matt Sarett | 03dd6d5 | 2017-01-23 12:15:09 -0500 | [diff] [blame] | 81 | SkReadPixelsRec rec(dstInfo, dstPixels, dstRB, x, y); |
| 82 | if (!rec.trim(fInfo.width(), fInfo.height())) { |
reed | 95d343f | 2015-05-23 13:21:06 -0700 | [diff] [blame] | 83 | return false; |
| 84 | } |
halcanary | 9d524f2 | 2016-03-29 09:03:52 -0700 | [diff] [blame] | 85 | |
Matt Sarett | 03dd6d5 | 2017-01-23 12:15:09 -0500 | [diff] [blame] | 86 | const void* srcPixels = this->addr(rec.fX, rec.fY); |
| 87 | const SkImageInfo srcInfo = fInfo.makeWH(rec.fInfo.width(), rec.fInfo.height()); |
Matt Sarett | 485c499 | 2017-02-14 14:18:27 -0500 | [diff] [blame] | 88 | SkConvertPixels(rec.fInfo, rec.fPixels, rec.fRowBytes, srcInfo, srcPixels, this->rowBytes(), |
Mike Reed | 086a427 | 2017-07-18 10:53:11 -0400 | [diff] [blame] | 89 | nullptr, behavior); |
Matt Sarett | 8572d85 | 2017-02-14 11:21:02 -0500 | [diff] [blame] | 90 | return true; |
reed | 95d343f | 2015-05-23 13:21:06 -0700 | [diff] [blame] | 91 | } |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 92 | |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 93 | static uint16_t pack_8888_to_4444(unsigned a, unsigned r, unsigned g, unsigned b) { |
| 94 | unsigned pixel = (SkA32To4444(a) << SK_A4444_SHIFT) | |
| 95 | (SkR32To4444(r) << SK_R4444_SHIFT) | |
| 96 | (SkG32To4444(g) << SK_G4444_SHIFT) | |
| 97 | (SkB32To4444(b) << SK_B4444_SHIFT); |
| 98 | return SkToU16(pixel); |
| 99 | } |
| 100 | |
| 101 | bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const { |
halcanary | 96fcdcc | 2015-08-27 07:41:13 -0700 | [diff] [blame] | 102 | if (nullptr == fPixels) { |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 103 | return false; |
| 104 | } |
| 105 | SkIRect area; |
| 106 | if (!area.intersect(this->bounds(), inArea)) { |
| 107 | return false; |
| 108 | } |
| 109 | |
| 110 | U8CPU a = SkColorGetA(color); |
| 111 | U8CPU r = SkColorGetR(color); |
| 112 | U8CPU g = SkColorGetG(color); |
| 113 | U8CPU b = SkColorGetB(color); |
| 114 | |
| 115 | int height = area.height(); |
| 116 | const int width = area.width(); |
| 117 | const int rowBytes = this->rowBytes(); |
halcanary | 9d524f2 | 2016-03-29 09:03:52 -0700 | [diff] [blame] | 118 | |
Mike Klein | adbbfa6 | 2017-09-01 11:20:46 -0400 | [diff] [blame] | 119 | if (color == 0 |
| 120 | && width == this->rowBytesAsPixels() |
| 121 | && inArea == this->bounds()) { |
| 122 | // All formats represent SkColor(0) as byte 0. |
| 123 | memset(this->writable_addr(), 0, height * rowBytes); |
| 124 | return true; |
| 125 | } |
| 126 | |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 127 | switch (this->colorType()) { |
| 128 | case kGray_8_SkColorType: { |
| 129 | if (255 != a) { |
| 130 | r = SkMulDiv255Round(r, a); |
| 131 | g = SkMulDiv255Round(g, a); |
| 132 | b = SkMulDiv255Round(b, a); |
| 133 | } |
| 134 | int gray = SkComputeLuminance(r, g, b); |
| 135 | uint8_t* p = this->writable_addr8(area.fLeft, area.fTop); |
| 136 | while (--height >= 0) { |
| 137 | memset(p, gray, width); |
| 138 | p += rowBytes; |
| 139 | } |
| 140 | break; |
| 141 | } |
| 142 | case kAlpha_8_SkColorType: { |
| 143 | uint8_t* p = this->writable_addr8(area.fLeft, area.fTop); |
| 144 | while (--height >= 0) { |
| 145 | memset(p, a, width); |
| 146 | p += rowBytes; |
| 147 | } |
| 148 | break; |
| 149 | } |
| 150 | case kARGB_4444_SkColorType: |
| 151 | case kRGB_565_SkColorType: { |
| 152 | uint16_t* p = this->writable_addr16(area.fLeft, area.fTop); |
| 153 | uint16_t v; |
halcanary | 9d524f2 | 2016-03-29 09:03:52 -0700 | [diff] [blame] | 154 | |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 155 | // make rgb premultiplied |
| 156 | if (255 != a) { |
benjaminwagner | a1bb8e0 | 2015-12-11 14:08:58 -0800 | [diff] [blame] | 157 | r = SkMulDiv255Round(r, a); |
| 158 | g = SkMulDiv255Round(g, a); |
| 159 | b = SkMulDiv255Round(b, a); |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 160 | } |
halcanary | 9d524f2 | 2016-03-29 09:03:52 -0700 | [diff] [blame] | 161 | |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 162 | if (kARGB_4444_SkColorType == this->colorType()) { |
| 163 | v = pack_8888_to_4444(a, r, g, b); |
| 164 | } else { |
| 165 | v = SkPackRGB16(r >> (8 - SK_R16_BITS), |
| 166 | g >> (8 - SK_G16_BITS), |
| 167 | b >> (8 - SK_B16_BITS)); |
| 168 | } |
| 169 | while (--height >= 0) { |
| 170 | sk_memset16(p, v, width); |
| 171 | p = (uint16_t*)((char*)p + rowBytes); |
| 172 | } |
| 173 | break; |
| 174 | } |
| 175 | case kBGRA_8888_SkColorType: |
| 176 | case kRGBA_8888_SkColorType: { |
| 177 | uint32_t* p = this->writable_addr32(area.fLeft, area.fTop); |
halcanary | 9d524f2 | 2016-03-29 09:03:52 -0700 | [diff] [blame] | 178 | |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 179 | if (255 != a && kPremul_SkAlphaType == this->alphaType()) { |
benjaminwagner | a1bb8e0 | 2015-12-11 14:08:58 -0800 | [diff] [blame] | 180 | r = SkMulDiv255Round(r, a); |
| 181 | g = SkMulDiv255Round(g, a); |
| 182 | b = SkMulDiv255Round(b, a); |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 183 | } |
benjaminwagner | a1bb8e0 | 2015-12-11 14:08:58 -0800 | [diff] [blame] | 184 | uint32_t v = kRGBA_8888_SkColorType == this->colorType() |
| 185 | ? SkPackARGB_as_RGBA(a, r, g, b) |
| 186 | : SkPackARGB_as_BGRA(a, r, g, b); |
| 187 | |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 188 | while (--height >= 0) { |
| 189 | sk_memset32(p, v, width); |
| 190 | p = (uint32_t*)((char*)p + rowBytes); |
| 191 | } |
| 192 | break; |
| 193 | } |
Hal Canary | 4cba3fe | 2016-12-07 14:59:27 -0500 | [diff] [blame] | 194 | case kRGBA_F16_SkColorType: |
| 195 | // The colorspace is unspecified, so assume linear just like getColor(). |
| 196 | this->erase(SkColor4f{(1 / 255.0f) * r, |
| 197 | (1 / 255.0f) * g, |
| 198 | (1 / 255.0f) * b, |
| 199 | (1 / 255.0f) * a}, &area); |
| 200 | break; |
reed | 7aefe03 | 2015-06-08 10:22:22 -0700 | [diff] [blame] | 201 | default: |
| 202 | return false; // no change, so don't call notifyPixelsChanged() |
| 203 | } |
| 204 | return true; |
| 205 | } |
| 206 | |
reed | 3601f28 | 2016-02-05 11:18:39 -0800 | [diff] [blame] | 207 | bool SkPixmap::erase(const SkColor4f& origColor, const SkIRect* subset) const { |
| 208 | SkPixmap pm; |
| 209 | if (subset) { |
| 210 | if (!this->extractSubset(&pm, *subset)) { |
| 211 | return false; |
| 212 | } |
| 213 | } else { |
| 214 | pm = *this; |
| 215 | } |
| 216 | |
| 217 | const SkColor4f color = origColor.pin(); |
| 218 | |
| 219 | if (kRGBA_F16_SkColorType != pm.colorType()) { |
brianosman | e074d1f | 2016-06-24 06:31:47 -0700 | [diff] [blame] | 220 | return pm.erase(color.toSkColor()); |
reed | 3601f28 | 2016-02-05 11:18:39 -0800 | [diff] [blame] | 221 | } |
| 222 | |
| 223 | const uint64_t half4 = color.premul().toF16(); |
| 224 | for (int y = 0; y < pm.height(); ++y) { |
| 225 | sk_memset64(pm.writable_addr64(0, y), half4, pm.width()); |
| 226 | } |
| 227 | return true; |
| 228 | } |
| 229 | |
reed | 0955303 | 2015-11-23 12:32:16 -0800 | [diff] [blame] | 230 | bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { |
| 231 | // Can't do anthing with empty src or dst |
| 232 | if (this->width() <= 0 || this->height() <= 0 || dst.width() <= 0 || dst.height() <= 0) { |
| 233 | return false; |
| 234 | } |
| 235 | |
| 236 | // no scaling involved? |
| 237 | if (dst.width() == this->width() && dst.height() == this->height()) { |
| 238 | return this->readPixels(dst); |
| 239 | } |
| 240 | |
| 241 | SkBitmap bitmap; |
halcanary | e36ec87 | 2015-12-09 11:36:59 -0800 | [diff] [blame] | 242 | if (!bitmap.installPixels(*this)) { |
reed | 0955303 | 2015-11-23 12:32:16 -0800 | [diff] [blame] | 243 | return false; |
| 244 | } |
| 245 | bitmap.setIsVolatile(true); // so we don't try to cache it |
| 246 | |
reed | e8f3062 | 2016-03-23 18:59:25 -0700 | [diff] [blame] | 247 | auto surface(SkSurface::MakeRasterDirect(dst.info(), dst.writable_addr(), dst.rowBytes())); |
reed | 0955303 | 2015-11-23 12:32:16 -0800 | [diff] [blame] | 248 | if (!surface) { |
| 249 | return false; |
| 250 | } |
| 251 | |
| 252 | SkPaint paint; |
| 253 | paint.setFilterQuality(quality); |
reed | 374772b | 2016-10-05 17:33:02 -0700 | [diff] [blame] | 254 | paint.setBlendMode(SkBlendMode::kSrc); |
reed | 0955303 | 2015-11-23 12:32:16 -0800 | [diff] [blame] | 255 | surface->getCanvas()->drawBitmapRect(bitmap, SkRect::MakeIWH(dst.width(), dst.height()), |
| 256 | &paint); |
| 257 | return true; |
| 258 | } |
| 259 | |
reed | 183b57f | 2015-06-05 14:33:17 -0700 | [diff] [blame] | 260 | ////////////////////////////////////////////////////////////////////////////////////////////////// |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 261 | |
| 262 | SkColor SkPixmap::getColor(int x, int y) const { |
| 263 | SkASSERT(this->addr()); |
| 264 | SkASSERT((unsigned)x < (unsigned)this->width()); |
| 265 | SkASSERT((unsigned)y < (unsigned)this->height()); |
Matt Sarett | 9466bf5 | 2017-06-09 09:54:55 -0400 | [diff] [blame] | 266 | |
| 267 | const bool needsUnpremul = (kPremul_SkAlphaType == fInfo.alphaType()); |
| 268 | auto toColor = [needsUnpremul](uint32_t maybePremulColor) { |
| 269 | return needsUnpremul ? SkUnPreMultiply::PMColorToColor(maybePremulColor) |
| 270 | : SkSwizzle_BGRA_to_PMColor(maybePremulColor); |
| 271 | }; |
| 272 | |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 273 | switch (this->colorType()) { |
| 274 | case kGray_8_SkColorType: { |
| 275 | uint8_t value = *this->addr8(x, y); |
| 276 | return SkColorSetRGB(value, value, value); |
| 277 | } |
| 278 | case kAlpha_8_SkColorType: { |
| 279 | return SkColorSetA(0, *this->addr8(x, y)); |
| 280 | } |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 281 | case kRGB_565_SkColorType: { |
| 282 | return SkPixel16ToColor(*this->addr16(x, y)); |
| 283 | } |
| 284 | case kARGB_4444_SkColorType: { |
| 285 | uint16_t value = *this->addr16(x, y); |
| 286 | SkPMColor c = SkPixel4444ToPixel32(value); |
Matt Sarett | 9466bf5 | 2017-06-09 09:54:55 -0400 | [diff] [blame] | 287 | return toColor(c); |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 288 | } |
| 289 | case kBGRA_8888_SkColorType: { |
| 290 | uint32_t value = *this->addr32(x, y); |
| 291 | SkPMColor c = SkSwizzle_BGRA_to_PMColor(value); |
Matt Sarett | 9466bf5 | 2017-06-09 09:54:55 -0400 | [diff] [blame] | 292 | return toColor(c); |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 293 | } |
| 294 | case kRGBA_8888_SkColorType: { |
| 295 | uint32_t value = *this->addr32(x, y); |
| 296 | SkPMColor c = SkSwizzle_RGBA_to_PMColor(value); |
Matt Sarett | 9466bf5 | 2017-06-09 09:54:55 -0400 | [diff] [blame] | 297 | return toColor(c); |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 298 | } |
| 299 | case kRGBA_F16_SkColorType: { |
| 300 | const uint64_t* addr = |
| 301 | (const uint64_t*)fPixels + y * (fRowBytes >> 3) + x; |
| 302 | Sk4f p4 = SkHalfToFloat_finite_ftz(*addr); |
Matt Sarett | 9466bf5 | 2017-06-09 09:54:55 -0400 | [diff] [blame] | 303 | if (p4[3] && needsUnpremul) { |
Hal Canary | 94e1a2f | 2016-10-31 09:38:12 -0400 | [diff] [blame] | 304 | float inva = 1 / p4[3]; |
| 305 | p4 = p4 * Sk4f(inva, inva, inva, 1); |
| 306 | } |
| 307 | SkColor c; |
| 308 | SkNx_cast<uint8_t>(p4 * Sk4f(255) + Sk4f(0.5f)).store(&c); |
| 309 | // p4 is RGBA, but we want BGRA, so we need to swap next |
| 310 | return SkSwizzle_RB(c); |
| 311 | } |
| 312 | default: |
| 313 | SkDEBUGFAIL(""); |
| 314 | return SkColorSetARGB(0, 0, 0, 0); |
| 315 | } |
| 316 | } |
Hal Canary | 58a7694 | 2016-12-07 15:24:59 -0500 | [diff] [blame] | 317 | |
| 318 | bool SkPixmap::computeIsOpaque() const { |
| 319 | const int height = this->height(); |
| 320 | const int width = this->width(); |
| 321 | |
| 322 | switch (this->colorType()) { |
| 323 | case kAlpha_8_SkColorType: { |
| 324 | unsigned a = 0xFF; |
| 325 | for (int y = 0; y < height; ++y) { |
| 326 | const uint8_t* row = this->addr8(0, y); |
| 327 | for (int x = 0; x < width; ++x) { |
| 328 | a &= row[x]; |
| 329 | } |
| 330 | if (0xFF != a) { |
| 331 | return false; |
| 332 | } |
| 333 | } |
| 334 | return true; |
| 335 | } break; |
Hal Canary | 58a7694 | 2016-12-07 15:24:59 -0500 | [diff] [blame] | 336 | case kRGB_565_SkColorType: |
| 337 | case kGray_8_SkColorType: |
| 338 | return true; |
| 339 | break; |
| 340 | case kARGB_4444_SkColorType: { |
| 341 | unsigned c = 0xFFFF; |
| 342 | for (int y = 0; y < height; ++y) { |
| 343 | const SkPMColor16* row = this->addr16(0, y); |
| 344 | for (int x = 0; x < width; ++x) { |
| 345 | c &= row[x]; |
| 346 | } |
| 347 | if (0xF != SkGetPackedA4444(c)) { |
| 348 | return false; |
| 349 | } |
| 350 | } |
| 351 | return true; |
| 352 | } break; |
| 353 | case kBGRA_8888_SkColorType: |
| 354 | case kRGBA_8888_SkColorType: { |
| 355 | SkPMColor c = (SkPMColor)~0; |
| 356 | for (int y = 0; y < height; ++y) { |
| 357 | const SkPMColor* row = this->addr32(0, y); |
| 358 | for (int x = 0; x < width; ++x) { |
| 359 | c &= row[x]; |
| 360 | } |
| 361 | if (0xFF != SkGetPackedA32(c)) { |
| 362 | return false; |
| 363 | } |
| 364 | } |
| 365 | return true; |
| 366 | } |
| 367 | case kRGBA_F16_SkColorType: { |
| 368 | const SkHalf* row = (const SkHalf*)this->addr(); |
| 369 | for (int y = 0; y < height; ++y) { |
| 370 | for (int x = 0; x < width; ++x) { |
| 371 | if (row[4 * x + 3] < SK_Half1) { |
| 372 | return false; |
| 373 | } |
| 374 | } |
| 375 | row += this->rowBytes() >> 1; |
| 376 | } |
| 377 | return true; |
| 378 | } |
| 379 | default: |
| 380 | break; |
| 381 | } |
| 382 | return false; |
| 383 | } |