1 :
2 : /*
3 : * Copyright 2011 Google Inc.
4 : *
5 : * Use of this source code is governed by a BSD-style license that can be
6 : * found in the LICENSE file.
7 : */
8 :
9 :
10 : #include "SkCanvas.h"
11 : #include "SkColorPriv.h"
12 :
13 : namespace {
14 :
15 : /**
16 : Copies all pixels from a bitmap to a dst ptr with a given rowBytes and
17 : Config8888. The bitmap must have kARGB_8888_Config.
18 : */
19 : inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels,
20 : size_t dstRowBytes,
21 : SkCanvas::Config8888 dstConfig8888,
22 : const SkBitmap& srcBmp);
23 :
24 : /**
25 : * Copies all pixels in a bitmap to a dst ptr with row bytes. The src bitmap
26 : * is assumed to have pixels and be kARGB_8888_Config. No conversion is applied
27 : */
28 : inline void SkCopyARGB8888BitmapTo(uint32_t* dstPixels,
29 : size_t dstRowBytes,
30 : const SkBitmap& srcBmp);
31 :
32 : /**
33 : Copies over all pixels in a bitmap from a src ptr with a given rowBytes and
34 : Config8888. The bitmap must have pixels and be kARGB_8888_Config.
35 : */
36 : inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp,
37 : const uint32_t* srcPixels,
38 : size_t srcRowBytes,
39 : SkCanvas::Config8888 srcConfig8888);
40 :
41 : }
42 :
43 : ///////////////////////////////////////////////////////////////////////////////
44 : // Implementation
45 :
46 : namespace {
47 :
48 : template <int A_IDX, int R_IDX, int G_IDX, int B_IDX>
49 0 : inline uint32_t pack_config8888(uint32_t a, uint32_t r,
50 : uint32_t g, uint32_t b) {
51 : #ifdef SK_CPU_LENDIAN
52 : return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) |
53 0 : (g << (G_IDX * 8)) | (b << (B_IDX * 8));
54 : #else
55 : return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) |
56 : (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8));
57 : #endif
58 : }
59 :
60 : template <int A_IDX, int R_IDX, int G_IDX, int B_IDX>
61 0 : inline void unpack_config8888(uint32_t color,
62 : uint32_t* a, uint32_t* r,
63 : uint32_t* g, uint32_t* b) {
64 : #ifdef SK_CPU_LENDIAN
65 0 : *a = (color >> (A_IDX * 8)) & 0xff;
66 0 : *r = (color >> (R_IDX * 8)) & 0xff;
67 0 : *g = (color >> (G_IDX * 8)) & 0xff;
68 0 : *b = (color >> (B_IDX * 8)) & 0xff;
69 : #else
70 : *a = (color >> ((3 - A_IDX) * 8)) & 0xff;
71 : *r = (color >> ((3 - R_IDX) * 8)) & 0xff;
72 : *g = (color >> ((3 - G_IDX) * 8)) & 0xff;
73 : *b = (color >> ((3 - B_IDX) * 8)) & 0xff;
74 : #endif
75 0 : }
76 :
77 : template <bool UNPM, int A_IDX, int R_IDX, int G_IDX, int B_IDX>
78 0 : inline void bitmap_copy_to_config8888(uint32_t* dstPixels,
79 : size_t dstRowBytes,
80 : const SkBitmap& srcBmp) {
81 0 : SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config());
82 0 : SkAutoLockPixels alp(srcBmp);
83 0 : int w = srcBmp.width();
84 0 : int h = srcBmp.height();
85 0 : size_t srcRowBytes = srcBmp.rowBytes();
86 :
87 0 : intptr_t src = reinterpret_cast<intptr_t>(srcBmp.getPixels());
88 0 : intptr_t dst = reinterpret_cast<intptr_t>(dstPixels);
89 :
90 0 : for (int y = 0; y < h; ++y) {
91 0 : const SkPMColor* srcRow = reinterpret_cast<SkPMColor*>(src);
92 0 : uint32_t* dstRow = reinterpret_cast<uint32_t*>(dst);
93 0 : for (int x = 0; x < w; ++x) {
94 0 : SkPMColor pmcolor = srcRow[x];
95 : if (UNPM) {
96 : U8CPU a, r, g, b;
97 0 : a = SkGetPackedA32(pmcolor);
98 0 : if (a) {
99 : // We're doing the explicit divide to match WebKit layout
100 : // test expectations. We can modify and rebaseline if there
101 : // it can be shown that there is a more performant way to
102 : // unpremul.
103 0 : r = SkGetPackedR32(pmcolor) * 0xff / a;
104 0 : g = SkGetPackedG32(pmcolor) * 0xff / a;
105 0 : b = SkGetPackedB32(pmcolor) * 0xff / a;
106 0 : dstRow[x] = pack_config8888<A_IDX, R_IDX,
107 : G_IDX, B_IDX>(a, r, g, b);
108 : } else {
109 0 : dstRow[x] = 0;
110 : }
111 : } else {
112 0 : dstRow[x] = pack_config8888<A_IDX, R_IDX,
113 : G_IDX, B_IDX>(
114 : SkGetPackedA32(pmcolor),
115 : SkGetPackedR32(pmcolor),
116 : SkGetPackedG32(pmcolor),
117 : SkGetPackedB32(pmcolor));
118 : }
119 : }
120 0 : dst += dstRowBytes;
121 0 : src += srcRowBytes;
122 : }
123 0 : }
124 :
125 : template <bool PM, int A_IDX, int R_IDX, int G_IDX, int B_IDX>
126 0 : inline void config8888_copy_to_bitmap(const SkBitmap& dstBmp,
127 : const uint32_t* srcPixels,
128 : size_t srcRowBytes) {
129 0 : SkASSERT(SkBitmap::kARGB_8888_Config == dstBmp.config());
130 0 : SkAutoLockPixels alp(dstBmp);
131 0 : int w = dstBmp.width();
132 0 : int h = dstBmp.height();
133 0 : size_t dstRowBytes = dstBmp.rowBytes();
134 :
135 0 : intptr_t src = reinterpret_cast<intptr_t>(srcPixels);
136 0 : intptr_t dst = reinterpret_cast<intptr_t>(dstBmp.getPixels());
137 :
138 0 : for (int y = 0; y < h; ++y) {
139 0 : const uint32_t* srcRow = reinterpret_cast<uint32_t*>(src);
140 0 : SkPMColor* dstRow = reinterpret_cast<SkPMColor*>(dst);
141 0 : for (int x = 0; x < w; ++x) {
142 0 : uint32_t c8888 = srcRow[x];
143 : uint32_t a, r, g, b;
144 0 : unpack_config8888<A_IDX, R_IDX, G_IDX, B_IDX>(c8888, &a, &r,
145 : &g, &b);
146 : if (PM) {
147 : // This matches WebKit's conversion which we are replacing.
148 : // We can consider alternative rounding rules for performance.
149 0 : r = SkMulDiv255Ceiling(r, a);
150 0 : g = SkMulDiv255Ceiling(g, a);
151 0 : b = SkMulDiv255Ceiling(b, a);
152 : }
153 : // NoCheck: https://bugs.webkit.org/show_bug.cgi?id=74025
154 0 : dstRow[x] = SkPackARGB32NoCheck(a, r, g, b);
155 : }
156 0 : src += srcRowBytes;
157 0 : dst += dstRowBytes;
158 : }
159 0 : }
160 :
161 : #ifdef SK_CPU_LENDIAN
162 : static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8;
163 : static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8;
164 : static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8;
165 : static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8;
166 : #else
167 : static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8);
168 : static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8);
169 : static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8);
170 : static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8);
171 : #endif
172 :
173 0 : inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels,
174 : size_t dstRowBytes,
175 : SkCanvas::Config8888 dstConfig8888,
176 : const SkBitmap& srcBmp) {
177 0 : switch (dstConfig8888) {
178 : case SkCanvas::kNative_Premul_Config8888:
179 : bitmap_copy_to_config8888<false,
180 : SK_NATIVE_A_IDX, SK_NATIVE_R_IDX,
181 : SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(
182 : dstPixels,
183 : dstRowBytes,
184 0 : srcBmp);
185 0 : break;
186 : case SkCanvas::kNative_Unpremul_Config8888:
187 : bitmap_copy_to_config8888<true,
188 : SK_NATIVE_A_IDX, SK_NATIVE_R_IDX,
189 : SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(
190 : dstPixels,
191 : dstRowBytes,
192 0 : srcBmp);
193 0 : break;
194 : case SkCanvas::kBGRA_Premul_Config8888:
195 : bitmap_copy_to_config8888<false, 3, 2, 1, 0> (
196 0 : dstPixels, dstRowBytes, srcBmp);
197 0 : break;
198 : case SkCanvas::kBGRA_Unpremul_Config8888:
199 : bitmap_copy_to_config8888<true, 3, 2, 1, 0> (
200 0 : dstPixels, dstRowBytes, srcBmp);
201 0 : break;
202 : case SkCanvas::kRGBA_Premul_Config8888:
203 : bitmap_copy_to_config8888<false, 3, 0, 1, 2> (
204 0 : dstPixels, dstRowBytes, srcBmp);
205 0 : break;
206 : case SkCanvas::kRGBA_Unpremul_Config8888:
207 : bitmap_copy_to_config8888<true, 3, 0, 1, 2> (
208 0 : dstPixels, dstRowBytes, srcBmp);
209 0 : break;
210 : default:
211 0 : SkDEBUGFAIL("unexpected Config8888");
212 0 : break;
213 : }
214 0 : }
215 :
216 0 : inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp,
217 : const uint32_t* srcPixels,
218 : size_t srcRowBytes,
219 : SkCanvas::Config8888 srcConfig8888) {
220 0 : switch (srcConfig8888) {
221 : case SkCanvas::kNative_Premul_Config8888:
222 : config8888_copy_to_bitmap<false,
223 : SK_NATIVE_A_IDX, SK_NATIVE_R_IDX,
224 : SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(
225 : dstBmp,
226 : srcPixels,
227 0 : srcRowBytes);
228 0 : break;
229 : case SkCanvas::kNative_Unpremul_Config8888:
230 : config8888_copy_to_bitmap<true,
231 : SK_NATIVE_A_IDX, SK_NATIVE_R_IDX,
232 : SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>(
233 : dstBmp,
234 : srcPixels,
235 0 : srcRowBytes);
236 0 : break;
237 : case SkCanvas::kBGRA_Premul_Config8888:
238 : config8888_copy_to_bitmap<false, 3, 2, 1, 0> (
239 0 : dstBmp, srcPixels, srcRowBytes);
240 0 : break;
241 : case SkCanvas::kBGRA_Unpremul_Config8888:
242 : config8888_copy_to_bitmap<true, 3, 2, 1, 0> (
243 0 : dstBmp, srcPixels, srcRowBytes);
244 0 : break;
245 : case SkCanvas::kRGBA_Premul_Config8888:
246 : config8888_copy_to_bitmap<false, 3, 0, 1, 2> (
247 0 : dstBmp, srcPixels, srcRowBytes);
248 0 : break;
249 : case SkCanvas::kRGBA_Unpremul_Config8888:
250 : config8888_copy_to_bitmap<true, 3, 0, 1, 2> (
251 0 : dstBmp, srcPixels, srcRowBytes);
252 0 : break;
253 : default:
254 0 : SkDEBUGFAIL("unexpected Config8888");
255 0 : break;
256 : }
257 0 : }
258 :
259 0 : inline void SkCopyARGB8888BitmapTo(uint32_t* dstPixels,
260 : size_t dstRowBytes,
261 : const SkBitmap& srcBmp) {
262 0 : SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config());
263 :
264 0 : SkAutoLockPixels alp(srcBmp);
265 :
266 0 : int w = srcBmp.width();
267 0 : int h = srcBmp.height();
268 0 : size_t srcRowBytes = srcBmp.rowBytes();
269 :
270 0 : size_t tightRowBytes = w * 4;
271 :
272 0 : char* src = reinterpret_cast<char*>(srcBmp.getPixels());
273 0 : char* dst = reinterpret_cast<char*>(dstPixels);
274 :
275 0 : if (tightRowBytes == srcRowBytes &&
276 : tightRowBytes == dstRowBytes) {
277 0 : memcpy(dst, src, tightRowBytes * h);
278 : } else {
279 0 : for (int y = 0; y < h; ++y) {
280 0 : memcpy(dst, src, tightRowBytes);
281 0 : dst += dstRowBytes;
282 0 : src += srcRowBytes;
283 : }
284 : }
285 0 : }
286 :
287 : }
|