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