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.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
michael@0 | 2 | * This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef GFX_COLOR_H |
michael@0 | 7 | #define GFX_COLOR_H |
michael@0 | 8 | |
michael@0 | 9 | #include "gfxTypes.h" |
michael@0 | 10 | |
michael@0 | 11 | #include "mozilla/Attributes.h" // for MOZ_ALWAYS_INLINE |
michael@0 | 12 | #include "mozilla/Endian.h" // for mozilla::NativeEndian::swapToBigEndian |
michael@0 | 13 | |
michael@0 | 14 | #define GFX_UINT32_FROM_BPTR(pbptr,i) (((uint32_t*)(pbptr))[i]) |
michael@0 | 15 | |
michael@0 | 16 | /** |
michael@0 | 17 | * GFX_0XFF_PPIXEL_FROM_BPTR(x) |
michael@0 | 18 | * |
michael@0 | 19 | * Avoid tortured construction of 32-bit ARGB pixel from 3 individual bytes |
michael@0 | 20 | * of memory plus constant 0xFF. RGB bytes are already contiguous! |
michael@0 | 21 | * Equivalent to: GFX_PACKED_PIXEL(0xff,r,g,b) |
michael@0 | 22 | * |
michael@0 | 23 | * Attempt to use fast byte-swapping instruction(s), e.g. bswap on x86, in |
michael@0 | 24 | * preference to a sequence of shift/or operations. |
michael@0 | 25 | */ |
michael@0 | 26 | #define GFX_0XFF_PPIXEL_FROM_UINT32(x) \ |
michael@0 | 27 | ( (mozilla::NativeEndian::swapToBigEndian(uint32_t(x)) >> 8) | (0xFFU << 24) ) |
michael@0 | 28 | |
michael@0 | 29 | #define GFX_0XFF_PPIXEL_FROM_BPTR(x) \ |
michael@0 | 30 | ( GFX_0XFF_PPIXEL_FROM_UINT32(GFX_UINT32_FROM_BPTR((x),0)) ) |
michael@0 | 31 | |
michael@0 | 32 | /** |
michael@0 | 33 | * GFX_BLOCK_RGB_TO_FRGB(from,to) |
michael@0 | 34 | * sizeof(*from) == sizeof(char) |
michael@0 | 35 | * sizeof(*to) == sizeof(uint32_t) |
michael@0 | 36 | * |
michael@0 | 37 | * Copy 4 pixels at a time, reading blocks of 12 bytes (RGB x4) |
michael@0 | 38 | * and writing blocks of 16 bytes (FRGB x4) |
michael@0 | 39 | */ |
michael@0 | 40 | #define GFX_BLOCK_RGB_TO_FRGB(from,to) \ |
michael@0 | 41 | PR_BEGIN_MACRO \ |
michael@0 | 42 | uint32_t m0 = GFX_UINT32_FROM_BPTR(from,0), \ |
michael@0 | 43 | m1 = GFX_UINT32_FROM_BPTR(from,1), \ |
michael@0 | 44 | m2 = GFX_UINT32_FROM_BPTR(from,2), \ |
michael@0 | 45 | rgbr = mozilla::NativeEndian::swapToBigEndian(m0), \ |
michael@0 | 46 | gbrg = mozilla::NativeEndian::swapToBigEndian(m1), \ |
michael@0 | 47 | brgb = mozilla::NativeEndian::swapToBigEndian(m2), \ |
michael@0 | 48 | p0, p1, p2, p3; \ |
michael@0 | 49 | p0 = 0xFF000000 | ((rgbr) >> 8); \ |
michael@0 | 50 | p1 = 0xFF000000 | ((rgbr) << 16) | ((gbrg) >> 16); \ |
michael@0 | 51 | p2 = 0xFF000000 | ((gbrg) << 8) | ((brgb) >> 24); \ |
michael@0 | 52 | p3 = 0xFF000000 | (brgb); \ |
michael@0 | 53 | to[0] = p0; to[1] = p1; to[2] = p2; to[3] = p3; \ |
michael@0 | 54 | PR_END_MACRO |
michael@0 | 55 | |
michael@0 | 56 | /** |
michael@0 | 57 | * Fast approximate division by 255. It has the property that |
michael@0 | 58 | * for all 0 <= n <= 255*255, GFX_DIVIDE_BY_255(n) == n/255. |
michael@0 | 59 | * But it only uses two adds and two shifts instead of an |
michael@0 | 60 | * integer division (which is expensive on many processors). |
michael@0 | 61 | * |
michael@0 | 62 | * equivalent to ((v)/255) |
michael@0 | 63 | */ |
michael@0 | 64 | #define GFX_DIVIDE_BY_255(v) \ |
michael@0 | 65 | (((((unsigned)(v)) << 8) + ((unsigned)(v)) + 255) >> 16) |
michael@0 | 66 | |
michael@0 | 67 | /** |
michael@0 | 68 | * Fast premultiply |
michael@0 | 69 | * |
michael@0 | 70 | * equivalent to (((c)*(a))/255) |
michael@0 | 71 | */ |
michael@0 | 72 | uint8_t MOZ_ALWAYS_INLINE gfxPreMultiply(uint8_t c, uint8_t a) { |
michael@0 | 73 | return GFX_DIVIDE_BY_255((c)*(a)); |
michael@0 | 74 | } |
michael@0 | 75 | |
michael@0 | 76 | /** |
michael@0 | 77 | * Pack the 4 8-bit channels (A,R,G,B) |
michael@0 | 78 | * into a 32-bit packed NON-premultiplied pixel. |
michael@0 | 79 | */ |
michael@0 | 80 | uint32_t MOZ_ALWAYS_INLINE |
michael@0 | 81 | gfxPackedPixelNoPreMultiply(uint8_t a, uint8_t r, uint8_t g, uint8_t b) { |
michael@0 | 82 | return (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)); |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | /** |
michael@0 | 86 | * Pack the 4 8-bit channels (A,R,G,B) |
michael@0 | 87 | * into a 32-bit packed premultiplied pixel. |
michael@0 | 88 | */ |
michael@0 | 89 | uint32_t MOZ_ALWAYS_INLINE |
michael@0 | 90 | gfxPackedPixel(uint8_t a, uint8_t r, uint8_t g, uint8_t b) { |
michael@0 | 91 | if (a == 0x00) |
michael@0 | 92 | return 0x00000000; |
michael@0 | 93 | else if (a == 0xFF) { |
michael@0 | 94 | return gfxPackedPixelNoPreMultiply(a, r, g, b); |
michael@0 | 95 | } else { |
michael@0 | 96 | return ((a) << 24) | |
michael@0 | 97 | (gfxPreMultiply(r,a) << 16) | |
michael@0 | 98 | (gfxPreMultiply(g,a) << 8) | |
michael@0 | 99 | (gfxPreMultiply(b,a)); |
michael@0 | 100 | } |
michael@0 | 101 | } |
michael@0 | 102 | |
michael@0 | 103 | /** |
michael@0 | 104 | * A color value, storing red, green, blue and alpha components. |
michael@0 | 105 | * This class does not use premultiplied alpha. |
michael@0 | 106 | * |
michael@0 | 107 | * XXX should this use doubles (instead of gfxFloat), for consistency with |
michael@0 | 108 | * cairo? |
michael@0 | 109 | */ |
michael@0 | 110 | struct gfxRGBA { |
michael@0 | 111 | gfxFloat r, g, b, a; |
michael@0 | 112 | |
michael@0 | 113 | enum PackedColorType { |
michael@0 | 114 | PACKED_ABGR, |
michael@0 | 115 | PACKED_ABGR_PREMULTIPLIED, |
michael@0 | 116 | |
michael@0 | 117 | PACKED_ARGB, |
michael@0 | 118 | PACKED_ARGB_PREMULTIPLIED, |
michael@0 | 119 | |
michael@0 | 120 | PACKED_XRGB |
michael@0 | 121 | }; |
michael@0 | 122 | |
michael@0 | 123 | gfxRGBA() { } |
michael@0 | 124 | /** |
michael@0 | 125 | * Intialize this color using explicit red, green, blue and alpha |
michael@0 | 126 | * values. |
michael@0 | 127 | */ |
michael@0 | 128 | MOZ_CONSTEXPR gfxRGBA(gfxFloat _r, gfxFloat _g, gfxFloat _b, gfxFloat _a=1.0) : r(_r), g(_g), b(_b), a(_a) {} |
michael@0 | 129 | |
michael@0 | 130 | /** |
michael@0 | 131 | * Initialize this color from a packed 32-bit color. |
michael@0 | 132 | * The color value is interpreted based on colorType; |
michael@0 | 133 | * all values use the native platform endianness. |
michael@0 | 134 | * |
michael@0 | 135 | * Resulting gfxRGBA stores non-premultiplied data. |
michael@0 | 136 | * |
michael@0 | 137 | * @see gfxRGBA::Packed |
michael@0 | 138 | */ |
michael@0 | 139 | gfxRGBA(uint32_t c, PackedColorType colorType = PACKED_ABGR) { |
michael@0 | 140 | if (colorType == PACKED_ABGR || |
michael@0 | 141 | colorType == PACKED_ABGR_PREMULTIPLIED) |
michael@0 | 142 | { |
michael@0 | 143 | r = ((c >> 0) & 0xff) * (1.0 / 255.0); |
michael@0 | 144 | g = ((c >> 8) & 0xff) * (1.0 / 255.0); |
michael@0 | 145 | b = ((c >> 16) & 0xff) * (1.0 / 255.0); |
michael@0 | 146 | a = ((c >> 24) & 0xff) * (1.0 / 255.0); |
michael@0 | 147 | } else if (colorType == PACKED_ARGB || |
michael@0 | 148 | colorType == PACKED_XRGB || |
michael@0 | 149 | colorType == PACKED_ARGB_PREMULTIPLIED) |
michael@0 | 150 | { |
michael@0 | 151 | b = ((c >> 0) & 0xff) * (1.0 / 255.0); |
michael@0 | 152 | g = ((c >> 8) & 0xff) * (1.0 / 255.0); |
michael@0 | 153 | r = ((c >> 16) & 0xff) * (1.0 / 255.0); |
michael@0 | 154 | a = ((c >> 24) & 0xff) * (1.0 / 255.0); |
michael@0 | 155 | } |
michael@0 | 156 | |
michael@0 | 157 | if (colorType == PACKED_ABGR_PREMULTIPLIED || |
michael@0 | 158 | colorType == PACKED_ARGB_PREMULTIPLIED) |
michael@0 | 159 | { |
michael@0 | 160 | if (a > 0.0) { |
michael@0 | 161 | r /= a; |
michael@0 | 162 | g /= a; |
michael@0 | 163 | b /= a; |
michael@0 | 164 | } |
michael@0 | 165 | } else if (colorType == PACKED_XRGB) { |
michael@0 | 166 | a = 1.0; |
michael@0 | 167 | } |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | bool operator==(const gfxRGBA& other) const |
michael@0 | 171 | { |
michael@0 | 172 | return r == other.r && g == other.g && b == other.b && a == other.a; |
michael@0 | 173 | } |
michael@0 | 174 | bool operator!=(const gfxRGBA& other) const |
michael@0 | 175 | { |
michael@0 | 176 | return !(*this == other); |
michael@0 | 177 | } |
michael@0 | 178 | |
michael@0 | 179 | /** |
michael@0 | 180 | * Returns this color value as a packed 32-bit integer. This reconstructs |
michael@0 | 181 | * the int32_t based on the given colorType, always in the native byte order. |
michael@0 | 182 | * |
michael@0 | 183 | * Note: gcc 4.2.3 on at least Ubuntu (x86) does something strange with |
michael@0 | 184 | * (uint8_t)(c * 255.0) << x, where the result is different than |
michael@0 | 185 | * double d = c * 255.0; v = ((uint8_t) d) << x. |
michael@0 | 186 | */ |
michael@0 | 187 | uint32_t Packed(PackedColorType colorType = PACKED_ABGR) const { |
michael@0 | 188 | gfxFloat rb = (r * 255.0); |
michael@0 | 189 | gfxFloat gb = (g * 255.0); |
michael@0 | 190 | gfxFloat bb = (b * 255.0); |
michael@0 | 191 | gfxFloat ab = (a * 255.0); |
michael@0 | 192 | |
michael@0 | 193 | if (colorType == PACKED_ABGR) { |
michael@0 | 194 | return (uint8_t(ab) << 24) | |
michael@0 | 195 | (uint8_t(bb) << 16) | |
michael@0 | 196 | (uint8_t(gb) << 8) | |
michael@0 | 197 | (uint8_t(rb) << 0); |
michael@0 | 198 | } |
michael@0 | 199 | if (colorType == PACKED_ARGB || colorType == PACKED_XRGB) { |
michael@0 | 200 | return (uint8_t(ab) << 24) | |
michael@0 | 201 | (uint8_t(rb) << 16) | |
michael@0 | 202 | (uint8_t(gb) << 8) | |
michael@0 | 203 | (uint8_t(bb) << 0); |
michael@0 | 204 | } |
michael@0 | 205 | |
michael@0 | 206 | rb *= a; |
michael@0 | 207 | gb *= a; |
michael@0 | 208 | bb *= a; |
michael@0 | 209 | |
michael@0 | 210 | if (colorType == PACKED_ABGR_PREMULTIPLIED) { |
michael@0 | 211 | return (((uint8_t)(ab) << 24) | |
michael@0 | 212 | ((uint8_t)(bb) << 16) | |
michael@0 | 213 | ((uint8_t)(gb) << 8) | |
michael@0 | 214 | ((uint8_t)(rb) << 0)); |
michael@0 | 215 | } |
michael@0 | 216 | if (colorType == PACKED_ARGB_PREMULTIPLIED) { |
michael@0 | 217 | return (((uint8_t)(ab) << 24) | |
michael@0 | 218 | ((uint8_t)(rb) << 16) | |
michael@0 | 219 | ((uint8_t)(gb) << 8) | |
michael@0 | 220 | ((uint8_t)(bb) << 0)); |
michael@0 | 221 | } |
michael@0 | 222 | |
michael@0 | 223 | return 0; |
michael@0 | 224 | } |
michael@0 | 225 | }; |
michael@0 | 226 | |
michael@0 | 227 | #endif /* _GFX_COLOR_H */ |