tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TestSwizzle.cpp (26833B)


      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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 }