gfx/layers/LayerUtils.cpp

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:cce5b1195b4e
1 /* -*- Mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "LayerUtils.h"
7 #include "PremultiplyTables.h"
8 #include "mozilla/Endian.h"
9
10 namespace mozilla {
11 namespace layers {
12
13 using namespace mozilla::gfx;
14
15 static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
16 return PremultiplyTable[a*256+v];
17 }
18
19 static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
20 return UnpremultiplyTable[a*256+v];
21 }
22
23 #ifdef DEBUG
24 static bool IsLittleEndian()
25 {
26 // Violate strict aliasing, because violating strict aliasing is how
27 // we always pack and unpack between uint32_t and uint8_t[].
28 uint16_t testShort;
29 static const uint8_t testBytes[2] = { 0xAA, 0xBB };
30 memcpy(&testShort, testBytes, sizeof(testBytes));
31 return testShort == 0xBBAA;
32 }
33 #endif // DEBUG
34
35 #ifdef MOZ_LITTLE_ENDIAN
36 #define ASSERT_ENDIAN() MOZ_ASSERT(IsLittleEndian(), "Defined as little endian, but actually big!")
37 #else
38 #define ASSERT_ENDIAN() MOZ_ASSERT(!IsLittleEndian(), "Defined as big endian, but actually little!")
39 #endif
40
41 void
42 PremultiplySurface(DataSourceSurface* srcSurface,
43 DataSourceSurface* destSurface)
44 {
45 if (!destSurface)
46 destSurface = srcSurface;
47
48 IntSize srcSize = srcSurface->GetSize();
49 MOZ_ASSERT(srcSurface->GetFormat() == destSurface->GetFormat() &&
50 srcSize.width == destSurface->GetSize().width &&
51 srcSize.height == destSurface->GetSize().height &&
52 srcSurface->Stride() == destSurface->Stride(),
53 "Source and destination surfaces don't have identical characteristics");
54
55 MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
56 "Source surface stride isn't tightly packed");
57
58 // Only premultiply ARGB32
59 if (srcSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
60 if (destSurface != srcSurface) {
61 memcpy(destSurface->GetData(), srcSurface->GetData(),
62 srcSurface->Stride() * srcSize.height);
63 }
64 return;
65 }
66
67 uint8_t *src = srcSurface->GetData();
68 uint8_t *dst = destSurface->GetData();
69
70 // Assert that our endian define is correct.
71 ASSERT_ENDIAN();
72
73 uint32_t dim = srcSize.width * srcSize.height;
74 for (uint32_t i = 0; i < dim; ++i) {
75 #ifdef MOZ_LITTLE_ENDIAN
76 uint8_t b = *src++;
77 uint8_t g = *src++;
78 uint8_t r = *src++;
79 uint8_t a = *src++;
80
81 *dst++ = PremultiplyValue(a, b);
82 *dst++ = PremultiplyValue(a, g);
83 *dst++ = PremultiplyValue(a, r);
84 *dst++ = a;
85 #else
86 uint8_t a = *src++;
87 uint8_t r = *src++;
88 uint8_t g = *src++;
89 uint8_t b = *src++;
90
91 *dst++ = a;
92 *dst++ = PremultiplyValue(a, r);
93 *dst++ = PremultiplyValue(a, g);
94 *dst++ = PremultiplyValue(a, b);
95 #endif
96 }
97 }
98
99
100 }
101 }

mercurial