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