1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #include "gtest/gtest.h"
8 #include "mozilla/ArrayUtils.h"
9 #include "mozilla/gfx/Swizzle.h"
10 #include "Orientation.h"
11
12 using namespace mozilla;
13 using namespace mozilla::gfx;
14 using namespace mozilla::image;
15
TEST(Moz2D,PremultiplyData)16 TEST(Moz2D, PremultiplyData)
17 {
18 const uint8_t in_bgra[5 * 4] = {
19 255, 255, 0, 255, // verify 255 alpha leaves RGB unchanged
20 0, 0, 255, 255,
21 0, 255, 255, 0, // verify 0 alpha zeroes out RGB
22 0, 0, 0, 0,
23 255, 0, 0, 128, // verify that 255 RGB maps to alpha
24 };
25 uint8_t out[5 * 4];
26 const uint8_t check_bgra[5 * 4] = {
27 255, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128,
28 };
29 // check swizzled output
30 const uint8_t check_rgba[5 * 4] = {
31 0, 255, 255, 255, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128,
32 };
33 const uint8_t check_argb[5 * 4] = {
34 255, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128,
35 };
36
37 PremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
38 sizeof(in_bgra), SurfaceFormat::B8G8R8A8, IntSize(5, 1));
39 EXPECT_TRUE(ArrayEqual(out, check_bgra));
40
41 PremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
42 sizeof(in_bgra), SurfaceFormat::R8G8B8A8, IntSize(5, 1));
43 EXPECT_TRUE(ArrayEqual(out, check_rgba));
44
45 PremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
46 sizeof(in_bgra), SurfaceFormat::A8R8G8B8, IntSize(5, 1));
47 EXPECT_TRUE(ArrayEqual(out, check_argb));
48 }
49
TEST(Moz2D,PremultiplyRow)50 TEST(Moz2D, PremultiplyRow)
51 {
52 const uint8_t in_bgra[5 * 4] = {
53 255, 255, 0, 255, // verify 255 alpha leaves RGB unchanged
54 0, 0, 255, 255,
55 0, 255, 255, 0, // verify 0 alpha zeroes out RGB
56 0, 0, 0, 0,
57 255, 0, 0, 128, // verify that 255 RGB maps to alpha
58 };
59 uint8_t out[5 * 4];
60 const uint8_t check_bgra[5 * 4] = {
61 255, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128,
62 };
63 // check swizzled output
64 const uint8_t check_rgba[5 * 4] = {
65 0, 255, 255, 255, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128,
66 };
67 const uint8_t check_argb[5 * 4] = {
68 255, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 128,
69 };
70
71 SwizzleRowFn func =
72 PremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8A8);
73 func(in_bgra, out, 5);
74 EXPECT_TRUE(ArrayEqual(out, check_bgra));
75
76 func = PremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::R8G8B8A8);
77 func(in_bgra, out, 5);
78 EXPECT_TRUE(ArrayEqual(out, check_rgba));
79
80 func = PremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::A8R8G8B8);
81 func(in_bgra, out, 5);
82 EXPECT_TRUE(ArrayEqual(out, check_argb));
83 }
84
TEST(Moz2D,PremultiplyYFlipData)85 TEST(Moz2D, PremultiplyYFlipData)
86 {
87 const uint8_t stride = 2 * 4;
88 const uint8_t in_bgra[6 * 4] = {
89 255, 255, 0, 255, // row 1: verify 255 alpha leaves RGB unchanged
90 0, 0, 255, 255,
91 0, 255, 255, 0, // row 2: verify 0 alpha zeroes out RGB
92 0, 0, 0, 0,
93 255, 0, 0, 128, // row 3: verify that 255 RGB maps to alpha
94 255, 255, 255, 128,
95 };
96 const uint8_t in_bgra_2[4 * 4] = {
97 255, 255, 0, 255, // row 1: verify 255 alpha leaves RGB unchanged
98 0, 0, 255, 255,
99 0, 255, 255, 0, // row 2: verify 0 alpha zeroes out RGB
100 0, 0, 0, 0,
101 };
102 const uint8_t in_bgra_3[2 * 4] = {
103 255, 0, 0, 128, // row 1: verify that 255 RGB maps to alpha
104 255, 255, 255, 128,
105 };
106 uint8_t out[6 * 4];
107 uint8_t out_2[4 * 4];
108 uint8_t out_3[2 * 4];
109 const uint8_t check_bgra[6 * 4] = {
110 128, 0, 0, 128, 128, 128, 128, 128, 0, 0, 0, 0,
111 0, 0, 0, 0, 255, 255, 0, 255, 0, 0, 255, 255,
112 };
113 const uint8_t check_bgra_2[4 * 4] = {
114 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 0, 255, 0, 0, 255, 255,
115 };
116 const uint8_t check_bgra_3[2 * 4] = {
117 128, 0, 0, 128, 128, 128, 128, 128,
118 };
119 // check swizzled output
120 const uint8_t check_rgba[6 * 4] = {
121 0, 0, 128, 128, 128, 128, 128, 128, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 255,
123 };
124
125 // Premultiply.
126 PremultiplyYFlipData(in_bgra, stride, SurfaceFormat::B8G8R8A8, out, stride,
127 SurfaceFormat::B8G8R8A8, IntSize(2, 3));
128 EXPECT_TRUE(ArrayEqual(out, check_bgra));
129
130 // Premultiply in-place with middle row.
131 memcpy(out, in_bgra, sizeof(out));
132 PremultiplyYFlipData(out, stride, SurfaceFormat::B8G8R8A8, out, stride,
133 SurfaceFormat::B8G8R8A8, IntSize(2, 3));
134 EXPECT_TRUE(ArrayEqual(out, check_bgra));
135
136 // Premultiply in-place without middle row.
137 memcpy(out_2, in_bgra_2, sizeof(out_2));
138 PremultiplyYFlipData(out_2, stride, SurfaceFormat::B8G8R8A8, out_2, stride,
139 SurfaceFormat::B8G8R8A8, IntSize(2, 2));
140 EXPECT_TRUE(ArrayEqual(out_2, check_bgra_2));
141
142 // Premultiply in-place only middle row.
143 memcpy(out_3, in_bgra_3, sizeof(out_3));
144 PremultiplyYFlipData(out_3, stride, SurfaceFormat::B8G8R8A8, out_3, stride,
145 SurfaceFormat::B8G8R8A8, IntSize(2, 1));
146 EXPECT_TRUE(ArrayEqual(out_3, check_bgra_3));
147
148 // Premultiply and swizzle with middle row.
149 PremultiplyYFlipData(in_bgra, stride, SurfaceFormat::B8G8R8A8, out, stride,
150 SurfaceFormat::R8G8B8A8, IntSize(2, 3));
151 EXPECT_TRUE(ArrayEqual(out, check_rgba));
152 }
153
TEST(Moz2D,UnpremultiplyData)154 TEST(Moz2D, UnpremultiplyData)
155 {
156 const uint8_t in_bgra[5 * 4] = {
157 255, 255, 0, 255, // verify 255 alpha leaves RGB unchanged
158 0, 0, 255, 255, 0, 0, 0, 0, // verify 0 alpha leaves RGB at 0
159 0, 0, 0, 64, // verify 0 RGB stays 0 with non-zero alpha
160 128, 0, 0, 128, // verify that RGB == alpha maps to 255
161
162 };
163 uint8_t out[5 * 4];
164 const uint8_t check_bgra[5 * 4] = {
165 255, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 64, 255, 0, 0, 128,
166 };
167 // check swizzled output
168 const uint8_t check_rgba[5 * 4] = {
169 0, 255, 255, 255, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 255, 128,
170 };
171 const uint8_t check_argb[5 * 4] = {
172 255, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 128, 0, 0, 255,
173 };
174
175 UnpremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
176 sizeof(in_bgra), SurfaceFormat::B8G8R8A8, IntSize(5, 1));
177 EXPECT_TRUE(ArrayEqual(out, check_bgra));
178
179 UnpremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
180 sizeof(in_bgra), SurfaceFormat::R8G8B8A8, IntSize(5, 1));
181 EXPECT_TRUE(ArrayEqual(out, check_rgba));
182
183 UnpremultiplyData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
184 sizeof(in_bgra), SurfaceFormat::A8R8G8B8, IntSize(5, 1));
185 EXPECT_TRUE(ArrayEqual(out, check_argb));
186 }
187
TEST(Moz2D,UnpremultiplyRow)188 TEST(Moz2D, UnpremultiplyRow)
189 {
190 const uint8_t in_bgra[5 * 4] = {
191 255, 255, 0, 255, // verify 255 alpha leaves RGB unchanged
192 0, 0, 255, 255, 0, 0, 0, 0, // verify 0 alpha leaves RGB at 0
193 0, 0, 0, 64, // verify 0 RGB stays 0 with non-zero alpha
194 128, 0, 0, 128, // verify that RGB == alpha maps to 255
195
196 };
197 uint8_t out[5 * 4];
198 const uint8_t check_bgra[5 * 4] = {
199 255, 255, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 64, 255, 0, 0, 128,
200 };
201 // check swizzled output
202 const uint8_t check_rgba[5 * 4] = {
203 0, 255, 255, 255, 255, 0, 0, 255, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 255, 128,
204 };
205 const uint8_t check_argb[5 * 4] = {
206 255, 0, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 128, 0, 0, 255,
207 };
208
209 SwizzleRowFn func =
210 UnpremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8A8);
211 func(in_bgra, out, 5);
212 EXPECT_TRUE(ArrayEqual(out, check_bgra));
213
214 func = UnpremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::R8G8B8A8);
215 func(in_bgra, out, 5);
216 EXPECT_TRUE(ArrayEqual(out, check_rgba));
217
218 func = UnpremultiplyRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::A8R8G8B8);
219 func(in_bgra, out, 5);
220 EXPECT_TRUE(ArrayEqual(out, check_argb));
221 }
222
TEST(Moz2D,SwizzleData)223 TEST(Moz2D, SwizzleData)
224 {
225 const uint8_t in_bgra[5 * 4] = {
226 253, 254, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 1, 2, 3, 64, 127, 0, 9, 128,
227
228 };
229 uint8_t out[5 * 4];
230 // check copy
231 const uint8_t check_bgra[5 * 4] = {
232 253, 254, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 1, 2, 3, 64, 127, 0, 9, 128,
233 };
234 // check swaps
235 const uint8_t check_rgba[5 * 4] = {
236 0, 254, 253, 255, 255, 0, 0, 255, 0, 0, 0, 0, 3, 2, 1, 64, 9, 0, 127, 128,
237 };
238 const uint8_t check_argb[5 * 4] = {
239 255, 0, 254, 253, 255, 255, 0, 0, 0, 0, 0, 0, 64, 3, 2, 1, 128, 9, 0, 127,
240 };
241 // check opaquifying
242 const uint8_t check_rgbx[5 * 4] = {
243 0, 254, 253, 255, 255, 0, 0, 255, 0, 0,
244 0, 255, 3, 2, 1, 255, 9, 0, 127, 255,
245 };
246 // check packing
247 uint8_t out24[5 * 3];
248 const uint8_t check_bgr[5 * 3] = {253, 254, 0, 0, 0, 255, 0, 0,
249 0, 1, 2, 3, 127, 0, 9};
250 const uint8_t check_rgb[5 * 3] = {
251 0, 254, 253, 255, 0, 0, 0, 0, 0, 3, 2, 1, 9, 0, 127,
252 };
253 uint8_t out8[5];
254 const uint8_t check_a[5] = {255, 255, 0, 64, 128};
255 uint16_t out16[5];
256 #define PACK_RGB565(b, g, r) \
257 (((b & 0xF8) >> 3) | ((g & 0xFC) << 3) | ((r & 0xF8) << 8))
258 const uint16_t check_16[5] = {
259 PACK_RGB565(253, 254, 0), PACK_RGB565(0, 0, 255), PACK_RGB565(0, 0, 0),
260 PACK_RGB565(1, 2, 3), PACK_RGB565(127, 0, 9),
261 };
262
263 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
264 sizeof(out), SurfaceFormat::B8G8R8A8, IntSize(5, 1));
265 EXPECT_TRUE(ArrayEqual(out, check_bgra));
266
267 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
268 sizeof(out), SurfaceFormat::R8G8B8A8, IntSize(5, 1));
269 EXPECT_TRUE(ArrayEqual(out, check_rgba));
270
271 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
272 sizeof(out), SurfaceFormat::A8R8G8B8, IntSize(5, 1));
273 EXPECT_TRUE(ArrayEqual(out, check_argb));
274
275 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out,
276 sizeof(out), SurfaceFormat::R8G8B8X8, IntSize(5, 1));
277 EXPECT_TRUE(ArrayEqual(out, check_rgbx));
278
279 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out24,
280 sizeof(out24), SurfaceFormat::B8G8R8, IntSize(5, 1));
281 EXPECT_TRUE(ArrayEqual(out24, check_bgr));
282
283 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out24,
284 sizeof(out24), SurfaceFormat::R8G8B8, IntSize(5, 1));
285 EXPECT_TRUE(ArrayEqual(out24, check_rgb));
286
287 SwizzleData(in_bgra, sizeof(in_bgra), SurfaceFormat::B8G8R8A8, out8,
288 sizeof(out8), SurfaceFormat::A8, IntSize(5, 1));
289 EXPECT_TRUE(ArrayEqual(out8, check_a));
290
291 const uint8_t* uint32_argb;
292
293 #if MOZ_BIG_ENDIAN()
294 EXPECT_EQ(SurfaceFormat::A8R8G8B8_UINT32, SurfaceFormat::A8R8G8B8);
295 uint32_argb = check_argb;
296 #else
297 EXPECT_EQ(SurfaceFormat::A8R8G8B8_UINT32, SurfaceFormat::B8G8R8A8);
298 uint32_argb = check_bgra;
299 #endif
300
301 SwizzleData(uint32_argb, sizeof(in_bgra), SurfaceFormat::A8R8G8B8_UINT32,
302 reinterpret_cast<uint8_t*>(out16), sizeof(out16),
303 SurfaceFormat::R5G6B5_UINT16, IntSize(5, 1));
304 EXPECT_TRUE(ArrayEqual(out16, check_16));
305 }
306
TEST(Moz2D,SwizzleYFlipData)307 TEST(Moz2D, SwizzleYFlipData)
308 {
309 const uint8_t stride = 2 * 4;
310 const uint8_t in_bgra[6 * 4] = {
311 255, 255, 0, 255, // row 1
312 0, 0, 255, 255, 0, 255, 255, 0, // row 2
313 0, 0, 0, 0, 255, 0, 0, 128, // row 3
314 255, 255, 255, 128,
315 };
316 const uint8_t in_bgra_2[4 * 4] = {
317 255, 255, 0, 255, // row 1
318 0, 0, 255, 255, 0, 255, 255, 0, // row 2
319 0, 0, 0, 0,
320 };
321 const uint8_t in_bgra_3[2 * 4] = {
322 255, 0, 0, 128, // row 1
323 255, 255, 255, 128,
324 };
325 uint8_t out[6 * 4];
326 uint8_t out_2[4 * 4];
327 uint8_t out_3[2 * 4];
328 const uint8_t check_rgba[6 * 4] = {
329 0, 0, 255, 128, 255, 255, 255, 128, 255, 255, 0, 0,
330 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 255,
331 };
332 const uint8_t check_rgba_2[4 * 4] = {
333 255, 255, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255, 0, 0, 255,
334 };
335 const uint8_t check_rgba_3[2 * 4] = {
336 0, 0, 255, 128, 255, 255, 255, 128,
337 };
338
339 // Swizzle.
340 SwizzleYFlipData(in_bgra, stride, SurfaceFormat::B8G8R8A8, out, stride,
341 SurfaceFormat::R8G8B8A8, IntSize(2, 3));
342 EXPECT_TRUE(ArrayEqual(out, check_rgba));
343
344 // Swizzle in-place with middle row.
345 memcpy(out, in_bgra, sizeof(out));
346 SwizzleYFlipData(out, stride, SurfaceFormat::B8G8R8A8, out, stride,
347 SurfaceFormat::R8G8B8A8, IntSize(2, 3));
348 EXPECT_TRUE(ArrayEqual(out, check_rgba));
349
350 // Swizzle in-place without middle row.
351 memcpy(out_2, in_bgra_2, sizeof(out_2));
352 SwizzleYFlipData(out_2, stride, SurfaceFormat::B8G8R8A8, out_2, stride,
353 SurfaceFormat::R8G8B8A8, IntSize(2, 2));
354 EXPECT_TRUE(ArrayEqual(out_2, check_rgba_2));
355
356 // Swizzle in-place only middle row.
357 memcpy(out_3, in_bgra_3, sizeof(out_3));
358 SwizzleYFlipData(out_3, stride, SurfaceFormat::B8G8R8A8, out_3, stride,
359 SurfaceFormat::R8G8B8A8, IntSize(2, 1));
360 EXPECT_TRUE(ArrayEqual(out_3, check_rgba_3));
361 }
362
TEST(Moz2D,SwizzleRow)363 TEST(Moz2D, SwizzleRow)
364 {
365 const uint8_t in_bgra[5 * 4] = {
366 253, 254, 0, 255, 0, 0, 255, 255, 0, 0, 0, 0, 1, 2, 3, 64, 127, 0, 9, 128,
367
368 };
369 uint8_t out[5 * 4];
370 // check swaps
371 const uint8_t check_rgba[5 * 4] = {
372 0, 254, 253, 255, 255, 0, 0, 255, 0, 0, 0, 0, 3, 2, 1, 64, 9, 0, 127, 128,
373 };
374 // check opaquifying
375 const uint8_t check_rgbx[5 * 4] = {
376 0, 254, 253, 255, 255, 0, 0, 255, 0, 0,
377 0, 255, 3, 2, 1, 255, 9, 0, 127, 255,
378 };
379 // check packing
380 uint8_t out24[5 * 3];
381 const uint8_t check_bgr[5 * 3] = {253, 254, 0, 0, 0, 255, 0, 0,
382 0, 1, 2, 3, 127, 0, 9};
383 const uint8_t check_rgb[5 * 3] = {
384 0, 254, 253, 255, 0, 0, 0, 0, 0, 3, 2, 1, 9, 0, 127,
385 };
386 // check unpacking
387 uint8_t out_unpack[16 * 4];
388 const uint8_t in_rgb[16 * 3] = {
389 0, 254, 253, 255, 0, 0, 0, 0, 0, 3, 2, 1, 9, 0, 127, 4,
390 5, 6, 9, 8, 7, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
391 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
392 };
393 const uint8_t check_unpack_rgbx[16 * 4] = {
394 0, 254, 253, 255, 255, 0, 0, 255, 0, 0, 0, 255, 3, 2, 1, 255,
395 9, 0, 127, 255, 4, 5, 6, 255, 9, 8, 7, 255, 10, 11, 12, 255,
396 13, 14, 15, 255, 16, 17, 18, 255, 19, 20, 21, 255, 22, 23, 24, 255,
397 25, 26, 27, 255, 28, 29, 30, 255, 31, 32, 33, 255, 34, 35, 36, 255,
398 };
399 const uint8_t check_unpack_bgrx[16 * 4] = {
400 253, 254, 0, 255, 0, 0, 255, 255, 0, 0, 0, 255, 1, 2, 3, 255,
401 127, 0, 9, 255, 6, 5, 4, 255, 7, 8, 9, 255, 12, 11, 10, 255,
402 15, 14, 13, 255, 18, 17, 16, 255, 21, 20, 19, 255, 24, 23, 22, 255,
403 27, 26, 25, 255, 30, 29, 28, 255, 33, 32, 31, 255, 36, 35, 34, 255,
404 };
405 const uint8_t check_unpack_xrgb[16 * 4] = {
406 255, 0, 254, 253, 255, 255, 0, 0, 255, 0, 0, 0, 255, 3, 2, 1,
407 255, 9, 0, 127, 255, 4, 5, 6, 255, 9, 8, 7, 255, 10, 11, 12,
408 255, 13, 14, 15, 255, 16, 17, 18, 255, 19, 20, 21, 255, 22, 23, 24,
409 255, 25, 26, 27, 255, 28, 29, 30, 255, 31, 32, 33, 255, 34, 35, 36,
410 };
411
412 SwizzleRowFn func =
413 SwizzleRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::R8G8B8A8);
414 func(in_bgra, out, 5);
415 EXPECT_TRUE(ArrayEqual(out, check_rgba));
416
417 func = SwizzleRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::R8G8B8X8);
418 func(in_bgra, out, 5);
419 EXPECT_TRUE(ArrayEqual(out, check_rgbx));
420
421 func = SwizzleRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8A8);
422 func(in_bgra, out, 5);
423 EXPECT_TRUE(ArrayEqual(out, in_bgra));
424
425 func = SwizzleRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::B8G8R8);
426 func(in_bgra, out24, 5);
427 EXPECT_TRUE(ArrayEqual(out24, check_bgr));
428
429 func = SwizzleRow(SurfaceFormat::B8G8R8A8, SurfaceFormat::R8G8B8);
430 func(in_bgra, out24, 5);
431 EXPECT_TRUE(ArrayEqual(out24, check_rgb));
432
433 func = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::B8G8R8X8);
434 func(in_rgb, out_unpack, 16);
435 EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_bgrx));
436
437 memset(out_unpack, 0xE5, sizeof(out_unpack));
438 memcpy(out_unpack, in_rgb, sizeof(in_rgb));
439 func(out_unpack, out_unpack, 16);
440 EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_bgrx));
441
442 func = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::R8G8B8X8);
443 func(in_rgb, out_unpack, 16);
444 EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_rgbx));
445
446 memset(out_unpack, 0xE5, sizeof(out_unpack));
447 memcpy(out_unpack, in_rgb, sizeof(in_rgb));
448 func(out_unpack, out_unpack, 16);
449 EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_rgbx));
450
451 func = SwizzleRow(SurfaceFormat::R8G8B8, SurfaceFormat::X8R8G8B8);
452 func(in_rgb, out_unpack, 16);
453 EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_xrgb));
454
455 memset(out_unpack, 0xE5, sizeof(out_unpack));
456 memcpy(out_unpack, in_rgb, sizeof(in_rgb));
457 func(out_unpack, out_unpack, 16);
458 EXPECT_TRUE(ArrayEqual(out_unpack, check_unpack_xrgb));
459 }
460
TEST(Moz2D,ReorientRow)461 TEST(Moz2D, ReorientRow)
462 {
463 // Input is a 3x4 image.
464 const uint8_t in_row0[3 * 4] = {
465 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
466 };
467 const uint8_t in_row1[3 * 4] = {
468 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
469 };
470 const uint8_t in_row2[3 * 4] = {
471 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
472 };
473 const uint8_t in_row3[3 * 4] = {
474 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
475 };
476
477 // Output is either a 3x4 image or 4x3 image.
478 uint8_t out[3 * 4 * 4];
479 IntSize outSize(3, 4);
480 IntSize outSizeSwap(4, 3);
481 int32_t outStride = 3 * 4;
482 int32_t outStrideSwap = 4 * 4;
483 IntRect dirty;
484
485 auto func = ReorientRow(Orientation());
486 dirty = func(in_row0, 0, out, outSize, outStride);
487 EXPECT_EQ(dirty, IntRect(0, 0, 3, 1));
488 dirty = func(in_row1, 1, out, outSize, outStride);
489 EXPECT_EQ(dirty, IntRect(0, 1, 3, 1));
490 dirty = func(in_row2, 2, out, outSize, outStride);
491 EXPECT_EQ(dirty, IntRect(0, 2, 3, 1));
492 dirty = func(in_row3, 3, out, outSize, outStride);
493 EXPECT_EQ(dirty, IntRect(0, 3, 3, 1));
494
495 // clang-format off
496 const uint8_t check_identity[3 * 4 * 4] = {
497 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
498 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
499 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
500 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
501 };
502 // clang-format on
503 EXPECT_TRUE(ArrayEqual(out, check_identity));
504
505 func = ReorientRow(Orientation(Angle::D90));
506 dirty = func(in_row0, 0, out, outSizeSwap, outStrideSwap);
507 EXPECT_EQ(dirty, IntRect(3, 0, 1, 3));
508 dirty = func(in_row1, 1, out, outSizeSwap, outStrideSwap);
509 EXPECT_EQ(dirty, IntRect(2, 0, 1, 3));
510 dirty = func(in_row2, 2, out, outSizeSwap, outStrideSwap);
511 EXPECT_EQ(dirty, IntRect(1, 0, 1, 3));
512 dirty = func(in_row3, 3, out, outSizeSwap, outStrideSwap);
513 EXPECT_EQ(dirty, IntRect(0, 0, 1, 3));
514
515 // clang-format off
516 const uint8_t check_d90[3 * 4 * 4] = {
517 36, 37, 38, 39, 24, 25, 26, 27, 12, 13, 14, 15, 0, 1, 2, 3,
518 40, 41, 42, 43, 28, 29, 30, 31, 16, 17, 18, 19, 4, 5, 6, 7,
519 44, 45, 46, 47, 32, 33, 34, 35, 20, 21, 22, 23, 8, 9, 10, 11,
520 };
521 // clang-format on
522 EXPECT_TRUE(ArrayEqual(out, check_d90));
523
524 func = ReorientRow(Orientation(Angle::D180));
525 dirty = func(in_row0, 0, out, outSize, outStride);
526 EXPECT_EQ(dirty, IntRect(0, 3, 3, 1));
527 dirty = func(in_row1, 1, out, outSize, outStride);
528 EXPECT_EQ(dirty, IntRect(0, 2, 3, 1));
529 dirty = func(in_row2, 2, out, outSize, outStride);
530 EXPECT_EQ(dirty, IntRect(0, 1, 3, 1));
531 dirty = func(in_row3, 3, out, outSize, outStride);
532 EXPECT_EQ(dirty, IntRect(0, 0, 3, 1));
533
534 // clang-format off
535 const uint8_t check_d180[3 * 4 * 4] = {
536 44, 45, 46, 47, 40, 41, 42, 43, 36, 37, 38, 39,
537 32, 33, 34, 35, 28, 29, 30, 31, 24, 25, 26, 27,
538 20, 21, 22, 23, 16, 17, 18, 19, 12, 13, 14, 15,
539 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3,
540 };
541 // clang-format on
542 EXPECT_TRUE(ArrayEqual(out, check_d180));
543
544 func = ReorientRow(Orientation(Angle::D270));
545 dirty = func(in_row0, 0, out, outSizeSwap, outStrideSwap);
546 EXPECT_EQ(dirty, IntRect(0, 0, 1, 3));
547 dirty = func(in_row1, 1, out, outSizeSwap, outStrideSwap);
548 EXPECT_EQ(dirty, IntRect(1, 0, 1, 3));
549 dirty = func(in_row2, 2, out, outSizeSwap, outStrideSwap);
550 EXPECT_EQ(dirty, IntRect(2, 0, 1, 3));
551 dirty = func(in_row3, 3, out, outSizeSwap, outStrideSwap);
552 EXPECT_EQ(dirty, IntRect(3, 0, 1, 3));
553
554 // clang-format off
555 const uint8_t check_d270[3 * 4 * 4] = {
556 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47,
557 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43,
558 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39,
559 };
560 // clang-format on
561 EXPECT_TRUE(ArrayEqual(out, check_d270));
562
563 func = ReorientRow(Orientation(Angle::D0, Flip::Horizontal));
564 dirty = func(in_row0, 0, out, outSize, outStride);
565 EXPECT_EQ(dirty, IntRect(0, 0, 3, 1));
566 dirty = func(in_row1, 1, out, outSize, outStride);
567 EXPECT_EQ(dirty, IntRect(0, 1, 3, 1));
568 dirty = func(in_row2, 2, out, outSize, outStride);
569 EXPECT_EQ(dirty, IntRect(0, 2, 3, 1));
570 dirty = func(in_row3, 3, out, outSize, outStride);
571 EXPECT_EQ(dirty, IntRect(0, 3, 3, 1));
572
573 // clang-format off
574 const uint8_t check_d0_flip[3 * 4 * 4] = {
575 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3,
576 20, 21, 22, 23, 16, 17, 18, 19, 12, 13, 14, 15,
577 32, 33, 34, 35, 28, 29, 30, 31, 24, 25, 26, 27,
578 44, 45, 46, 47, 40, 41, 42, 43, 36, 37, 38, 39,
579 };
580 // clang-format on
581 EXPECT_TRUE(ArrayEqual(out, check_d0_flip));
582
583 func = ReorientRow(Orientation(Angle::D90, Flip::Horizontal));
584 dirty = func(in_row0, 0, out, outSizeSwap, outStrideSwap);
585 EXPECT_EQ(dirty, IntRect(0, 0, 1, 3));
586 dirty = func(in_row1, 1, out, outSizeSwap, outStrideSwap);
587 EXPECT_EQ(dirty, IntRect(1, 0, 1, 3));
588 dirty = func(in_row2, 2, out, outSizeSwap, outStrideSwap);
589 EXPECT_EQ(dirty, IntRect(2, 0, 1, 3));
590 dirty = func(in_row3, 3, out, outSizeSwap, outStrideSwap);
591 EXPECT_EQ(dirty, IntRect(3, 0, 1, 3));
592
593 // clang-format off
594 const uint8_t check_d90_flip[3 * 4 * 4] = {
595 0, 1, 2, 3, 12, 13, 14, 15, 24, 25, 26, 27, 36, 37, 38, 39,
596 4, 5, 6, 7, 16, 17, 18, 19, 28, 29, 30, 31, 40, 41, 42, 43,
597 8, 9, 10, 11, 20, 21, 22, 23, 32, 33, 34, 35, 44, 45, 46, 47,
598 };
599 // clang-format on
600 EXPECT_TRUE(ArrayEqual(out, check_d90_flip));
601
602 func = ReorientRow(Orientation(Angle::D180, Flip::Horizontal));
603 dirty = func(in_row0, 0, out, outSize, outStride);
604 EXPECT_EQ(dirty, IntRect(0, 3, 3, 1));
605 dirty = func(in_row1, 1, out, outSize, outStride);
606 EXPECT_EQ(dirty, IntRect(0, 2, 3, 1));
607 dirty = func(in_row2, 2, out, outSize, outStride);
608 EXPECT_EQ(dirty, IntRect(0, 1, 3, 1));
609 dirty = func(in_row3, 3, out, outSize, outStride);
610 EXPECT_EQ(dirty, IntRect(0, 0, 3, 1));
611
612 // clang-format off
613 const uint8_t check_d180_flip[3 * 4 * 4] = {
614 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
615 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
616 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
617 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
618 };
619 // clang-format on
620 EXPECT_TRUE(ArrayEqual(out, check_d180_flip));
621
622 func = ReorientRow(Orientation(Angle::D270, Flip::Horizontal));
623 dirty = func(in_row0, 0, out, outSizeSwap, outStrideSwap);
624 EXPECT_EQ(dirty, IntRect(3, 0, 1, 3));
625 dirty = func(in_row1, 1, out, outSizeSwap, outStrideSwap);
626 EXPECT_EQ(dirty, IntRect(2, 0, 1, 3));
627 dirty = func(in_row2, 2, out, outSizeSwap, outStrideSwap);
628 EXPECT_EQ(dirty, IntRect(1, 0, 1, 3));
629 dirty = func(in_row3, 3, out, outSizeSwap, outStrideSwap);
630 EXPECT_EQ(dirty, IntRect(0, 0, 1, 3));
631
632 // clang-format off
633 const uint8_t check_d270_flip[3 * 4 * 4] = {
634 44, 45, 46, 47, 32, 33, 34, 35, 20, 21, 22, 23, 8, 9, 10, 11,
635 40, 41, 42, 43, 28, 29, 30, 31, 16, 17, 18, 19, 4, 5, 6, 7,
636 36, 37, 38, 39, 24, 25, 26, 27, 12, 13, 14, 15, 0, 1, 2, 3,
637 };
638 // clang-format on
639 EXPECT_TRUE(ArrayEqual(out, check_d270_flip));
640
641 func = ReorientRow(
642 Orientation(Angle::D0, Flip::Horizontal, /* aFlipFirst */ true));
643 dirty = func(in_row0, 0, out, outSize, outStride);
644 EXPECT_EQ(dirty, IntRect(0, 0, 3, 1));
645 dirty = func(in_row1, 1, out, outSize, outStride);
646 EXPECT_EQ(dirty, IntRect(0, 1, 3, 1));
647 dirty = func(in_row2, 2, out, outSize, outStride);
648 EXPECT_EQ(dirty, IntRect(0, 2, 3, 1));
649 dirty = func(in_row3, 3, out, outSize, outStride);
650 EXPECT_EQ(dirty, IntRect(0, 3, 3, 1));
651
652 // No rotation, so flipping before and after are the same.
653 EXPECT_TRUE(ArrayEqual(out, check_d0_flip));
654
655 func = ReorientRow(
656 Orientation(Angle::D90, Flip::Horizontal, /* aFlipFirst */ true));
657 dirty = func(in_row0, 0, out, outSizeSwap, outStrideSwap);
658 EXPECT_EQ(dirty, IntRect(3, 0, 1, 3));
659 dirty = func(in_row1, 1, out, outSizeSwap, outStrideSwap);
660 EXPECT_EQ(dirty, IntRect(2, 0, 1, 3));
661 dirty = func(in_row2, 2, out, outSizeSwap, outStrideSwap);
662 EXPECT_EQ(dirty, IntRect(1, 0, 1, 3));
663 dirty = func(in_row3, 3, out, outSizeSwap, outStrideSwap);
664 EXPECT_EQ(dirty, IntRect(0, 0, 1, 3));
665
666 // Flip, rotate 90 degrees is the same as rotate 270 degrees, flip.
667 EXPECT_TRUE(ArrayEqual(out, check_d270_flip));
668
669 func = ReorientRow(
670 Orientation(Angle::D180, Flip::Horizontal, /* aFlipFirst */ true));
671 dirty = func(in_row0, 0, out, outSize, outStride);
672 EXPECT_EQ(dirty, IntRect(0, 3, 3, 1));
673 dirty = func(in_row1, 1, out, outSize, outStride);
674 EXPECT_EQ(dirty, IntRect(0, 2, 3, 1));
675 dirty = func(in_row2, 2, out, outSize, outStride);
676 EXPECT_EQ(dirty, IntRect(0, 1, 3, 1));
677 dirty = func(in_row3, 3, out, outSize, outStride);
678 EXPECT_EQ(dirty, IntRect(0, 0, 3, 1));
679
680 // Flip, rotate 180 degrees is the same as rotate 180 degrees, flip.
681 EXPECT_TRUE(ArrayEqual(out, check_d180_flip));
682
683 func = ReorientRow(
684 Orientation(Angle::D270, Flip::Horizontal, /* aFlipFirst */ true));
685 dirty = func(in_row0, 0, out, outSizeSwap, outStrideSwap);
686 EXPECT_EQ(dirty, IntRect(0, 0, 1, 3));
687 dirty = func(in_row1, 1, out, outSizeSwap, outStrideSwap);
688 EXPECT_EQ(dirty, IntRect(1, 0, 1, 3));
689 dirty = func(in_row2, 2, out, outSizeSwap, outStrideSwap);
690 EXPECT_EQ(dirty, IntRect(2, 0, 1, 3));
691 dirty = func(in_row3, 3, out, outSizeSwap, outStrideSwap);
692 EXPECT_EQ(dirty, IntRect(3, 0, 1, 3));
693
694 // Flip, rotate 270 degrees is the same as rotate 90 degrees, flip.
695 EXPECT_TRUE(ArrayEqual(out, check_d90_flip));
696 }
697