1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #ifndef CORE_FXGE_DIB_FX_DIB_H_
8 #define CORE_FXGE_DIB_FX_DIB_H_
9
10 #include <stdint.h>
11
12 #include <utility>
13
14 #include "core/fxcrt/compiler_specific.h"
15
16 // Encoding:
17 // - Bits-per-pixel: value & 0xFF
18 // - Is mask: value & 0x100
19 // - Has alpha: value & 0x200
20 // - Is premultiplied-alpha: value & 0x400
21 enum class FXDIB_Format : uint16_t {
22 kInvalid = 0,
23 k1bppRgb = 0x001,
24 k8bppRgb = 0x008,
25 kBgr = 0x018,
26 kBgrx = 0x020,
27 k1bppMask = 0x101,
28 k8bppMask = 0x108,
29 kBgra = 0x220,
30 #if defined(PDF_USE_SKIA)
31 kBgraPremul = 0x620,
32 #endif
33 };
34
35 // Endian-dependent (in theory).
36 using FX_ARGB = uint32_t; // A in high bits, ..., B in low bits.
37 using FX_CMYK = uint32_t; // C in high bits, ..., K in low bits.
38
39 // FX_COLORREF, like win32 COLORREF, is BGR. i.e. 0x00BBGGRR.
40 // Note that while the non-existent alpha component should be set to 0, some
41 // parts of the codebase use 0xFFFFFFFF as a sentinel value to indicate error.
42 using FX_COLORREF = uint32_t;
43
44 // Endian-independent, name-ordered by increasing address.
45 template <typename T>
46 struct FX_RGB_STRUCT {
47 T red = 0;
48 T green = 0;
49 T blue = 0;
50 };
51
52 template <typename T>
53 struct FX_BGR_STRUCT {
54 T blue = 0;
55 T green = 0;
56 T red = 0;
57 };
58
59 template <typename T>
60 struct FX_ARGB_STRUCT {
61 T alpha = 0;
62 T red = 0;
63 T green = 0;
64 T blue = 0;
65 };
66
67 template <typename T>
68 struct FX_ABGR_STRUCT {
69 T alpha = 0;
70 T blue = 0;
71 T green = 0;
72 T red = 0;
73 };
74
75 template <typename T>
76 struct FX_RGBA_STRUCT {
77 T red = 0;
78 T green = 0;
79 T blue = 0;
80 T alpha = 0;
81 };
82
83 template <typename T>
84 struct FX_BGRA_STRUCT {
85 T blue = 0;
86 T green = 0;
87 T red = 0;
88 T alpha = 0;
89 };
90
91 template <typename T>
92 struct FX_CMYK_STRUCT {
93 T cyan = 0;
94 T magenta = 0;
95 T yellow = 0;
96 T key = 0;
97 };
98
99 template <typename T>
100 struct FX_LAB_STRUCT {
101 T lightness_star = 0;
102 T a_star = 0;
103 T b_star = 0;
104 };
105
106 struct FXDIB_ResampleOptions {
107 FXDIB_ResampleOptions();
108
109 bool HasAnyOptions() const;
110
111 bool bInterpolateBilinear = false;
112 bool bHalftone = false;
113 bool bNoSmoothing = false;
114 bool bLossy = false;
115 };
116
117 // See PDF 1.7 spec, table 7.2 and 7.3. The enum values need to be in the same
118 // order as listed in the spec.
119 enum class BlendMode {
120 kNormal = 0,
121 kMultiply,
122 kScreen,
123 kOverlay,
124 kDarken,
125 kLighten,
126 kColorDodge,
127 kColorBurn,
128 kHardLight,
129 kSoftLight,
130 kDifference,
131 kExclusion,
132 kHue,
133 kSaturation,
134 kColor,
135 kLuminosity,
136 kLast = kLuminosity,
137 };
138
FXSYS_BGR(uint8_t b,uint8_t g,uint8_t r)139 constexpr uint32_t FXSYS_BGR(uint8_t b, uint8_t g, uint8_t r) {
140 return (b << 16) | (g << 8) | r;
141 }
142
FXSYS_GetRValue(uint32_t bgr)143 constexpr uint8_t FXSYS_GetRValue(uint32_t bgr) {
144 return bgr & 0xff;
145 }
146
FXSYS_GetGValue(uint32_t bgr)147 constexpr uint8_t FXSYS_GetGValue(uint32_t bgr) {
148 return (bgr >> 8) & 0xff;
149 }
150
FXSYS_GetBValue(uint32_t bgr)151 constexpr uint8_t FXSYS_GetBValue(uint32_t bgr) {
152 return (bgr >> 16) & 0xff;
153 }
154
FXSYS_GetUnsignedAlpha(float alpha)155 constexpr unsigned int FXSYS_GetUnsignedAlpha(float alpha) {
156 return static_cast<unsigned int>(alpha * 255.f + 0.5f);
157 }
158
159 // Bits per pixel, not bytes.
GetBppFromFormat(FXDIB_Format format)160 inline int GetBppFromFormat(FXDIB_Format format) {
161 return static_cast<uint16_t>(format) & 0xff;
162 }
163
164 // AKA bytes per pixel, assuming 8-bits per component.
GetCompsFromFormat(FXDIB_Format format)165 inline int GetCompsFromFormat(FXDIB_Format format) {
166 return (static_cast<uint16_t>(format) & 0xff) / 8;
167 }
168
GetIsMaskFromFormat(FXDIB_Format format)169 inline bool GetIsMaskFromFormat(FXDIB_Format format) {
170 return !!(static_cast<uint16_t>(format) & 0x100);
171 }
172
GetIsAlphaFromFormat(FXDIB_Format format)173 inline bool GetIsAlphaFromFormat(FXDIB_Format format) {
174 return !!(static_cast<uint16_t>(format) & 0x200);
175 }
176
177 FX_BGRA_STRUCT<uint8_t> ArgbToBGRAStruct(FX_ARGB argb);
178
179 // Ignores alpha.
180 FX_BGR_STRUCT<uint8_t> ArgbToBGRStruct(FX_ARGB argb);
181
182 // Returns (a, FX_COLORREF)
183 std::pair<uint8_t, FX_COLORREF> ArgbToAlphaAndColorRef(FX_ARGB argb);
184
185 FX_COLORREF ArgbToColorRef(FX_ARGB argb);
186 FX_ARGB AlphaAndColorRefToArgb(int a, FX_COLORREF colorref);
187
ArgbEncode(uint32_t a,uint32_t r,uint32_t g,uint32_t b)188 constexpr FX_ARGB ArgbEncode(uint32_t a, uint32_t r, uint32_t g, uint32_t b) {
189 return (a << 24) | (r << 16) | (g << 8) | b;
190 }
191
CmykEncode(uint32_t c,uint32_t m,uint32_t y,uint32_t k)192 constexpr FX_CMYK CmykEncode(uint32_t c, uint32_t m, uint32_t y, uint32_t k) {
193 return (c << 24) | (m << 16) | (y << 8) | k;
194 }
195
196 #define FXARGB_A(argb) ((uint8_t)((argb) >> 24))
197 #define FXARGB_R(argb) ((uint8_t)((argb) >> 16))
198 #define FXARGB_G(argb) ((uint8_t)((argb) >> 8))
199 #define FXARGB_B(argb) ((uint8_t)(argb))
200 #define FXARGB_MUL_ALPHA(argb, alpha) \
201 (((((argb) >> 24) * (alpha) / 255) << 24) | ((argb)&0xffffff))
202
203 #define FXRGB2GRAY(r, g, b) (((b)*11 + (g)*59 + (r)*30) / 100)
204 #define FXDIB_ALPHA_MERGE(backdrop, source, source_alpha) \
205 (((backdrop) * (255 - (source_alpha)) + (source) * (source_alpha)) / 255)
206
207 #define FXCMYK_TODIB(cmyk) \
208 ((uint8_t)((cmyk) >> 24) | ((uint8_t)((cmyk) >> 16)) << 8 | \
209 ((uint8_t)((cmyk) >> 8)) << 16 | ((uint8_t)(cmyk) << 24))
210 #define FXARGB_TOBGRORDERDIB(argb) \
211 ((uint8_t)(argb >> 16) | ((uint8_t)(argb >> 8)) << 8 | \
212 ((uint8_t)(argb)) << 16 | ((uint8_t)(argb >> 24) << 24))
213
214 // SAFETY: Caller must ensure 4 valid bytes at `p`.
FXARGB_GetDIB(const uint8_t * p)215 UNSAFE_BUFFER_USAGE inline FX_ARGB FXARGB_GetDIB(const uint8_t* p) {
216 return ArgbEncode(UNSAFE_BUFFERS(p[3]), UNSAFE_BUFFERS(p[2]),
217 UNSAFE_BUFFERS(p[1]), UNSAFE_BUFFERS(p[0]));
218 }
219
220 // SAFETY: Caller must ensure 4 valid bytes at `p`.
FXARGB_SetDIB(uint8_t * p,uint32_t argb)221 UNSAFE_BUFFER_USAGE inline void FXARGB_SetDIB(uint8_t* p, uint32_t argb) {
222 UNSAFE_BUFFERS(p[0]) = FXARGB_B(argb);
223 UNSAFE_BUFFERS(p[1]) = FXARGB_G(argb);
224 UNSAFE_BUFFERS(p[2]) = FXARGB_R(argb);
225 UNSAFE_BUFFERS(p[3]) = FXARGB_A(argb);
226 }
227
228 // SAFETY: Caller must ensure 4 valid bytes at `p`.
FXARGB_SetRGBOrderDIB(uint8_t * p,uint32_t argb)229 UNSAFE_BUFFER_USAGE inline void FXARGB_SetRGBOrderDIB(uint8_t* p,
230 uint32_t argb) {
231 UNSAFE_BUFFERS(p[0]) = FXARGB_R(argb);
232 UNSAFE_BUFFERS(p[1]) = FXARGB_G(argb);
233 UNSAFE_BUFFERS(p[2]) = FXARGB_B(argb);
234 UNSAFE_BUFFERS(p[3]) = FXARGB_A(argb);
235 }
236
237 // SAFETY: Caller must ensure 3 valid bytes at `dest` and `src`.
ReverseCopy3Bytes(uint8_t * dest,const uint8_t * src)238 UNSAFE_BUFFER_USAGE inline void ReverseCopy3Bytes(uint8_t* dest,
239 const uint8_t* src) {
240 UNSAFE_BUFFERS(dest[2] = src[0]);
241 UNSAFE_BUFFERS(dest[1] = src[1]);
242 UNSAFE_BUFFERS(dest[0] = src[2]);
243 }
244
245 #if defined(PDF_USE_SKIA)
246 template <typename T>
PreMultiplyColor(const T & input)247 T PreMultiplyColor(const T& input) {
248 if (input.alpha == 255) {
249 return input;
250 }
251
252 T output;
253 output.alpha = input.alpha;
254 output.blue = static_cast<float>(input.blue) * input.alpha / 255.0f;
255 output.green = static_cast<float>(input.green) * input.alpha / 255.0f;
256 output.red = static_cast<float>(input.red) * input.alpha / 255.0f;
257 return output;
258 }
259
260 template <typename T>
UnPreMultiplyColor(const T & input)261 T UnPreMultiplyColor(const T& input) {
262 if (input.alpha == 255) {
263 return input;
264 }
265
266 T output;
267 output.alpha = input.alpha;
268 if (input.alpha == 0) {
269 output.blue = 0;
270 output.green = 0;
271 output.red = 0;
272 } else {
273 output.blue = static_cast<float>(input.blue) * 255.0f / input.alpha;
274 output.green = static_cast<float>(input.green) * 255.0f / input.alpha;
275 output.red = static_cast<float>(input.red) * 255.0f / input.alpha;
276 }
277 return output;
278 }
279 #endif // defined(PDF_USE_SKIA)
280
281 #endif // CORE_FXGE_DIB_FX_DIB_H_
282