Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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/. */
6 #include "LayerUtils.h"
7 #include "PremultiplyTables.h"
8 #include "mozilla/Endian.h"
10 namespace mozilla {
11 namespace layers {
13 using namespace mozilla::gfx;
15 static inline const uint8_t PremultiplyValue(uint8_t a, uint8_t v) {
16 return PremultiplyTable[a*256+v];
17 }
19 static inline const uint8_t UnpremultiplyValue(uint8_t a, uint8_t v) {
20 return UnpremultiplyTable[a*256+v];
21 }
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
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
41 void
42 PremultiplySurface(DataSourceSurface* srcSurface,
43 DataSourceSurface* destSurface)
44 {
45 if (!destSurface)
46 destSurface = srcSurface;
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");
55 MOZ_ASSERT(srcSurface->Stride() == srcSize.width * 4,
56 "Source surface stride isn't tightly packed");
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 }
67 uint8_t *src = srcSurface->GetData();
68 uint8_t *dst = destSurface->GetData();
70 // Assert that our endian define is correct.
71 ASSERT_ENDIAN();
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++;
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++;
91 *dst++ = a;
92 *dst++ = PremultiplyValue(a, r);
93 *dst++ = PremultiplyValue(a, g);
94 *dst++ = PremultiplyValue(a, b);
95 #endif
96 }
97 }
100 }
101 }