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