• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/private/SkImageInfoPriv.h"
9 #include "src/core/SkReadBuffer.h"
10 #include "src/core/SkSafeMath.h"
11 #include "src/core/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 kBGRA_1010102_SkColorType:       return 4;
25         case kBGR_101010x_SkColorType:        return 4;
26         case kGray_8_SkColorType:             return 1;
27         case kRGBA_F16Norm_SkColorType:       return 8;
28         case kRGBA_F16_SkColorType:           return 8;
29         case kRGBA_F32_SkColorType:           return 16;
30         case kR8G8_unorm_SkColorType:         return 2;
31         case kA16_unorm_SkColorType:          return 2;
32         case kR16G16_unorm_SkColorType:       return 4;
33         case kA16_float_SkColorType:          return 2;
34         case kR16G16_float_SkColorType:       return 4;
35         case kR16G16B16A16_unorm_SkColorType: return 8;
36         case kSRGBA_8888_SkColorType:         return 4;
37         case kR8_unorm_SkColorType:           return 1;
38     }
39     SkUNREACHABLE;
40 }
41 
SkColorTypeIsAlwaysOpaque(SkColorType ct)42 bool SkColorTypeIsAlwaysOpaque(SkColorType ct) {
43     return !(SkColorTypeChannelFlags(ct) & kAlpha_SkColorChannelFlag);
44 }
45 
46 ///////////////////////////////////////////////////////////////////////////////////////////////////
47 
bytesPerPixel() const48 int SkColorInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
49 
shiftPerPixel() const50 int SkColorInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
51 
52 ///////////////////////////////////////////////////////////////////////////////////////////////////
53 
computeOffset(int x,int y,size_t rowBytes) const54 size_t SkImageInfo::computeOffset(int x, int y, size_t rowBytes) const {
55     SkASSERT((unsigned)x < (unsigned)this->width());
56     SkASSERT((unsigned)y < (unsigned)this->height());
57     return SkColorTypeComputeOffset(this->colorType(), x, y, rowBytes);
58 }
59 
computeByteSize(size_t rowBytes) const60 size_t SkImageInfo::computeByteSize(size_t rowBytes) const {
61     if (0 == this->height()) {
62         return 0;
63     }
64     SkSafeMath safe;
65     size_t bytes = safe.add(safe.mul(safe.addInt(this->height(), -1), rowBytes),
66                             safe.mul(this->width(), this->bytesPerPixel()));
67 
68     // The CPU backend implements some memory operations on images using instructions that take a
69     // signed 32-bit offset from the base. If we ever make an image larger than that, overflow can
70     // cause us to read/write memory that starts 2GB *before* the buffer. (crbug.com/1264705)
71     constexpr size_t kMaxSigned32BitSize = SK_MaxS32;
72     return (safe.ok() && (bytes <= kMaxSigned32BitSize)) ? bytes : SIZE_MAX;
73 }
74 
MakeS32(int width,int height,SkAlphaType at)75 SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
76     return SkImageInfo({width, height}, {kN32_SkColorType, at, SkColorSpace::MakeSRGB()});
77 }
78 
79 #ifdef SK_DEBUG
validate() const80 void SkImageInfo::validate() const {
81     SkASSERT(fDimensions.width() >= 0);
82     SkASSERT(fDimensions.height() >= 0);
83     SkASSERT(SkColorTypeIsValid(this->colorType()));
84     SkASSERT(SkAlphaTypeIsValid(this->alphaType()));
85 }
86 #endif
87 
SkColorTypeValidateAlphaType(SkColorType colorType,SkAlphaType alphaType,SkAlphaType * canonical)88 bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
89                                   SkAlphaType* canonical) {
90     switch (colorType) {
91         case kUnknown_SkColorType:
92             alphaType = kUnknown_SkAlphaType;
93             break;
94         case kAlpha_8_SkColorType:         // fall-through
95         case kA16_unorm_SkColorType:       // fall-through
96         case kA16_float_SkColorType:
97             if (kUnpremul_SkAlphaType == alphaType) {
98                 alphaType = kPremul_SkAlphaType;
99             }
100             [[fallthrough]];
101         case kARGB_4444_SkColorType:
102         case kRGBA_8888_SkColorType:
103         case kSRGBA_8888_SkColorType:
104         case kBGRA_8888_SkColorType:
105         case kRGBA_1010102_SkColorType:
106         case kBGRA_1010102_SkColorType:
107         case kRGBA_F16Norm_SkColorType:
108         case kRGBA_F16_SkColorType:
109         case kRGBA_F32_SkColorType:
110         case kR16G16B16A16_unorm_SkColorType:
111             if (kUnknown_SkAlphaType == alphaType) {
112                 return false;
113             }
114             break;
115         case kGray_8_SkColorType:
116         case kR8G8_unorm_SkColorType:
117         case kR16G16_unorm_SkColorType:
118         case kR16G16_float_SkColorType:
119         case kRGB_565_SkColorType:
120         case kRGB_888x_SkColorType:
121         case kRGB_101010x_SkColorType:
122         case kBGR_101010x_SkColorType:
123         case kR8_unorm_SkColorType:
124             alphaType = kOpaque_SkAlphaType;
125             break;
126     }
127     if (canonical) {
128         *canonical = alphaType;
129     }
130     return true;
131 }
132 
133 ///////////////////////////////////////////////////////////////////////////////////////////////////
134 
135 #include "src/image/SkReadPixelsRec.h"
136 
trim(int srcWidth,int srcHeight)137 bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
138     if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
139         return false;
140     }
141     if (0 >= fInfo.width() || 0 >= fInfo.height()) {
142         return false;
143     }
144 
145     int x = fX;
146     int y = fY;
147     SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
148     if (!srcR.intersect({0, 0, srcWidth, srcHeight})) {
149         return false;
150     }
151 
152     // if x or y are negative, then we have to adjust pixels
153     if (x > 0) {
154         x = 0;
155     }
156     if (y > 0) {
157         y = 0;
158     }
159     // here x,y are either 0 or negative
160     // we negate and add them so UBSAN (pointer-overflow) doesn't get confused.
161     fPixels = ((char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel());
162     // the intersect may have shrunk info's logical size
163     fInfo = fInfo.makeDimensions(srcR.size());
164     fX = srcR.x();
165     fY = srcR.y();
166 
167     return true;
168 }
169 
170 ///////////////////////////////////////////////////////////////////////////////////////////////////
171 
172 #include "src/core/SkWritePixelsRec.h"
173 
trim(int dstWidth,int dstHeight)174 bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) {
175     if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
176         return false;
177     }
178     if (0 >= fInfo.width() || 0 >= fInfo.height()) {
179         return false;
180     }
181 
182     int x = fX;
183     int y = fY;
184     SkIRect dstR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
185     if (!dstR.intersect({0, 0, dstWidth, dstHeight})) {
186         return false;
187     }
188 
189     // if x or y are negative, then we have to adjust pixels
190     if (x > 0) {
191         x = 0;
192     }
193     if (y > 0) {
194         y = 0;
195     }
196     // here x,y are either 0 or negative
197     // we negate and add them so UBSAN (pointer-overflow) doesn't get confused.
198     fPixels = ((const char*)fPixels + -y*fRowBytes + -x*fInfo.bytesPerPixel());
199     // the intersect may have shrunk info's logical size
200     fInfo = fInfo.makeDimensions(dstR.size());
201     fX = dstR.x();
202     fY = dstR.y();
203 
204     return true;
205 }
206