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