1 /*
2  * Copyright 2010 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 "SkImageInfoPriv.h"
9 #include "SkSafeMath.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 
SkColorTypeBytesPerPixel(SkColorType ct)13 int SkColorTypeBytesPerPixel(SkColorType ct) {
14     switch (ct) {
15         case kUnknown_SkColorType:      return 0;
16         case kAlpha_8_SkColorType:      return 1;
17         case kRGB_565_SkColorType:      return 2;
18         case kARGB_4444_SkColorType:    return 2;
19         case kRGBA_8888_SkColorType:    return 4;
20         case kBGRA_8888_SkColorType:    return 4;
21         case kRGB_888x_SkColorType:     return 4;
22         case kRGBA_1010102_SkColorType: return 4;
23         case kRGB_101010x_SkColorType:  return 4;
24         case kGray_8_SkColorType:       return 1;
25         case kRGBA_F16_SkColorType:     return 8;
26         case kRGBA_F32_SkColorType:     return 16;
27     }
28     return 0;
29 }
30 
SkColorTypeIsAlwaysOpaque(SkColorType ct)31 bool SkColorTypeIsAlwaysOpaque(SkColorType ct) {
32     return !(kAlpha_SkColorTypeComponentFlag & SkColorTypeComponentFlags(ct));
33 }
34 
35 ///////////////////////////////////////////////////////////////////////////////////////////////////
36 
bytesPerPixel() const37 int SkImageInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
38 
shiftPerPixel() const39 int SkImageInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
40 
computeOffset(int x,int y,size_t rowBytes) const41 size_t SkImageInfo::computeOffset(int x, int y, size_t rowBytes) const {
42     SkASSERT((unsigned)x < (unsigned)this->width());
43     SkASSERT((unsigned)y < (unsigned)this->height());
44     return SkColorTypeComputeOffset(this->colorType(), x, y, rowBytes);
45 }
46 
computeByteSize(size_t rowBytes) const47 size_t SkImageInfo::computeByteSize(size_t rowBytes) const {
48     if (0 == this->height()) {
49         return 0;
50     }
51     SkSafeMath safe;
52     size_t bytes = safe.add(safe.mul(safe.addInt(this->height(), -1), rowBytes),
53                             safe.mul(this->width(), this->bytesPerPixel()));
54     return safe ? bytes : SIZE_MAX;
55 }
56 
MakeS32(int width,int height,SkAlphaType at)57 SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
58     return SkImageInfo(width, height, kN32_SkColorType, at,
59                        SkColorSpace::MakeSRGB());
60 }
61 
SkColorTypeValidateAlphaType(SkColorType colorType,SkAlphaType alphaType,SkAlphaType * canonical)62 bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
63                                   SkAlphaType* canonical) {
64     switch (colorType) {
65         case kUnknown_SkColorType:
66             alphaType = kUnknown_SkAlphaType;
67             break;
68         case kAlpha_8_SkColorType:
69             if (kUnpremul_SkAlphaType == alphaType) {
70                 alphaType = kPremul_SkAlphaType;
71             }
72             // fall-through
73         case kARGB_4444_SkColorType:
74         case kRGBA_8888_SkColorType:
75         case kBGRA_8888_SkColorType:
76         case kRGBA_1010102_SkColorType:
77         case kRGBA_F16_SkColorType:
78         case kRGBA_F32_SkColorType:
79             if (kUnknown_SkAlphaType == alphaType) {
80                 return false;
81             }
82             break;
83         case kGray_8_SkColorType:
84         case kRGB_565_SkColorType:
85         case kRGB_888x_SkColorType:
86         case kRGB_101010x_SkColorType:
87             alphaType = kOpaque_SkAlphaType;
88             break;
89         default:
90             return false;
91     }
92     if (canonical) {
93         *canonical = alphaType;
94     }
95     return true;
96 }
97 
98 ///////////////////////////////////////////////////////////////////////////////////////////////////
99 
100 #include "SkReadPixelsRec.h"
101 
trim(int srcWidth,int srcHeight)102 bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
103     if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
104         return false;
105     }
106     if (0 >= fInfo.width() || 0 >= fInfo.height()) {
107         return false;
108     }
109 
110     int x = fX;
111     int y = fY;
112     SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
113     if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
114         return false;
115     }
116 
117     // if x or y are negative, then we have to adjust pixels
118     if (x > 0) {
119         x = 0;
120     }
121     if (y > 0) {
122         y = 0;
123     }
124     // here x,y are either 0 or negative
125     // we negate and add them so UBSAN (pointer-overflow) doesn't get confused.
126     fPixels = ((char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel());
127     // the intersect may have shrunk info's logical size
128     fInfo = fInfo.makeWH(srcR.width(), srcR.height());
129     fX = srcR.x();
130     fY = srcR.y();
131 
132     return true;
133 }
134 
135 ///////////////////////////////////////////////////////////////////////////////////////////////////
136 
137 #include "SkWritePixelsRec.h"
138 
trim(int dstWidth,int dstHeight)139 bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) {
140     if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
141         return false;
142     }
143     if (0 >= fInfo.width() || 0 >= fInfo.height()) {
144         return false;
145     }
146 
147     int x = fX;
148     int y = fY;
149     SkIRect dstR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
150     if (!dstR.intersect(0, 0, dstWidth, dstHeight)) {
151         return false;
152     }
153 
154     // if x or y are negative, then we have to adjust pixels
155     if (x > 0) {
156         x = 0;
157     }
158     if (y > 0) {
159         y = 0;
160     }
161     // here x,y are either 0 or negative
162     // we negate and add them so UBSAN (pointer-overflow) doesn't get confused.
163     fPixels = ((const char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel());
164     // the intersect may have shrunk info's logical size
165     fInfo = fInfo.makeWH(dstR.width(), dstR.height());
166     fX = dstR.x();
167     fY = dstR.y();
168 
169     return true;
170 }
171