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 #ifndef MOZILLA_GFX_TYPES_H_
8 #define MOZILLA_GFX_TYPES_H_
9 
10 #include "mozilla/EndianUtils.h"
11 #include "mozilla/MacroArgs.h"  // for MOZ_CONCAT
12 
13 #include <stddef.h>
14 #include <stdint.h>
15 
16 namespace mozilla {
17 namespace gfx {
18 
19 typedef float Float;
20 typedef double Double;
21 
22 enum class SurfaceType : int8_t {
23   DATA,                   /* Data surface - bitmap in memory */
24   D2D1_BITMAP,            /* Surface wrapping a ID2D1Bitmap */
25   D2D1_DRAWTARGET,        /* Surface made from a D2D draw target */
26   CAIRO,                  /* Surface wrapping a cairo surface */
27   CAIRO_IMAGE,            /* Data surface wrapping a cairo image surface */
28   COREGRAPHICS_IMAGE,     /* Surface wrapping a CoreGraphics Image */
29   COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */
30   SKIA,                   /* Surface wrapping a Skia bitmap */
31   DUAL_DT,                /* Snapshot of a dual drawtarget */
32   D2D1_1_IMAGE,           /* A D2D 1.1 ID2D1Image SourceSurface */
33   RECORDING,              /* Surface used for recording */
34   TILED,                  /* Surface from a tiled DrawTarget */
35   DATA_SHARED,            /* Data surface using shared memory */
36   CAPTURE                 /* Data from a DrawTargetCapture */
37 };
38 
39 enum class SurfaceFormat : int8_t {
40   // The following values are named to reflect layout of colors in memory, from
41   // lowest byte to highest byte. The 32-bit value layout depends on machine
42   // endianness.
43   //               in-memory            32-bit LE value   32-bit BE value
44   B8G8R8A8,  // [BB, GG, RR, AA]     0xAARRGGBB        0xBBGGRRAA
45   B8G8R8X8,  // [BB, GG, RR, 00]     0x00RRGGBB        0xBBGGRR00
46   R8G8B8A8,  // [RR, GG, BB, AA]     0xAABBGGRR        0xRRGGBBAA
47   R8G8B8X8,  // [RR, GG, BB, 00]     0x00BBGGRR        0xRRGGBB00
48   A8R8G8B8,  // [AA, RR, GG, BB]     0xBBGGRRAA        0xAARRGGBB
49   X8R8G8B8,  // [00, RR, GG, BB]     0xBBGGRR00        0x00RRGGBB
50 
51   R8G8B8,
52   B8G8R8,
53 
54   // The _UINT16 suffix here indicates that the name reflects the layout when
55   // viewed as a uint16_t value. In memory these values are stored using native
56   // endianness.
57   R5G6B5_UINT16,  // 0bRRRRRGGGGGGBBBBB
58 
59   // This one is a single-byte, so endianness isn't an issue.
60   A8,
61   A16,
62 
63   R8G8,
64 
65   // These ones are their own special cases.
66   YUV,
67   NV12,
68   YUV422,
69   HSV,
70   Lab,
71   Depth,
72 
73   // This represents the unknown format.
74   UNKNOWN,
75 
76 // The following values are endian-independent synonyms. The _UINT32 suffix
77 // indicates that the name reflects the layout when viewed as a uint32_t
78 // value.
79 #if MOZ_LITTLE_ENDIAN
80   A8R8G8B8_UINT32 = B8G8R8A8,  // 0xAARRGGBB
81   X8R8G8B8_UINT32 = B8G8R8X8   // 0x00RRGGBB
82 #elif MOZ_BIG_ENDIAN
83   A8R8G8B8_UINT32 = A8R8G8B8,  // 0xAARRGGBB
84   X8R8G8B8_UINT32 = X8R8G8B8   // 0x00RRGGBB
85 #else
86 #error "bad endianness"
87 #endif
88 };
89 
IsOpaque(SurfaceFormat aFormat)90 inline bool IsOpaque(SurfaceFormat aFormat) {
91   switch (aFormat) {
92     case SurfaceFormat::B8G8R8X8:
93     case SurfaceFormat::R8G8B8X8:
94     case SurfaceFormat::R5G6B5_UINT16:
95     case SurfaceFormat::YUV:
96     case SurfaceFormat::NV12:
97     case SurfaceFormat::YUV422:
98       return true;
99     default:
100       return false;
101   }
102 }
103 
104 enum class FilterType : int8_t {
105   BLEND = 0,
106   TRANSFORM,
107   MORPHOLOGY,
108   COLOR_MATRIX,
109   FLOOD,
110   TILE,
111   TABLE_TRANSFER,
112   DISCRETE_TRANSFER,
113   LINEAR_TRANSFER,
114   GAMMA_TRANSFER,
115   CONVOLVE_MATRIX,
116   DISPLACEMENT_MAP,
117   TURBULENCE,
118   ARITHMETIC_COMBINE,
119   COMPOSITE,
120   DIRECTIONAL_BLUR,
121   GAUSSIAN_BLUR,
122   POINT_DIFFUSE,
123   POINT_SPECULAR,
124   SPOT_DIFFUSE,
125   SPOT_SPECULAR,
126   DISTANT_DIFFUSE,
127   DISTANT_SPECULAR,
128   CROP,
129   PREMULTIPLY,
130   UNPREMULTIPLY
131 };
132 
133 enum class DrawTargetType : int8_t {
134   SOFTWARE_RASTER = 0,
135   HARDWARE_RASTER,
136   VECTOR
137 };
138 
139 enum class BackendType : int8_t {
140   NONE = 0,
141   DIRECT2D,  // Used for version independent D2D objects.
142   CAIRO,
143   SKIA,
144   RECORDING,
145   DIRECT2D1_1,
146   WEBRENDER_TEXT,
147 
148   // Add new entries above this line.
149   BACKEND_LAST
150 };
151 
152 enum class FontType : int8_t {
153   DWRITE,
154   GDI,
155   MAC,
156   SKIA,
157   CAIRO,
158   COREGRAPHICS,
159   FONTCONFIG,
160   FREETYPE
161 };
162 
163 enum class NativeSurfaceType : int8_t {
164   D3D10_TEXTURE,
165   CAIRO_CONTEXT,
166   CGCONTEXT,
167   CGCONTEXT_ACCELERATED,
168   OPENGL_TEXTURE
169 };
170 
171 enum class NativeFontType : int8_t {
172   DWRITE_FONT_FACE,
173   GDI_FONT_FACE,
174   MAC_FONT_FACE,
175   SKIA_FONT_FACE,
176   CAIRO_FONT_FACE
177 };
178 
179 enum class FontStyle : int8_t { NORMAL, ITALIC, BOLD, BOLD_ITALIC };
180 
181 enum class FontHinting : int8_t { NONE, LIGHT, NORMAL, FULL };
182 
183 enum class CompositionOp : int8_t {
184   OP_OVER,
185   OP_ADD,
186   OP_ATOP,
187   OP_OUT,
188   OP_IN,
189   OP_SOURCE,
190   OP_DEST_IN,
191   OP_DEST_OUT,
192   OP_DEST_OVER,
193   OP_DEST_ATOP,
194   OP_XOR,
195   OP_MULTIPLY,
196   OP_SCREEN,
197   OP_OVERLAY,
198   OP_DARKEN,
199   OP_LIGHTEN,
200   OP_COLOR_DODGE,
201   OP_COLOR_BURN,
202   OP_HARD_LIGHT,
203   OP_SOFT_LIGHT,
204   OP_DIFFERENCE,
205   OP_EXCLUSION,
206   OP_HUE,
207   OP_SATURATION,
208   OP_COLOR,
209   OP_LUMINOSITY,
210   OP_COUNT
211 };
212 
213 enum class Axis : int8_t { X_AXIS, Y_AXIS, BOTH };
214 
215 enum class ExtendMode : int8_t {
216   CLAMP,     // Do not repeat
217   REPEAT,    // Repeat in both axis
218   REPEAT_X,  // Only X axis
219   REPEAT_Y,  // Only Y axis
220   REFLECT    // Mirror the image
221 };
222 
223 enum class FillRule : int8_t { FILL_WINDING, FILL_EVEN_ODD };
224 
225 enum class AntialiasMode : int8_t { NONE, GRAY, SUBPIXEL, DEFAULT };
226 
227 // See https://en.wikipedia.org/wiki/Texture_filtering
228 enum class SamplingFilter : int8_t {
229   GOOD,
230   LINEAR,
231   POINT,
232   SENTINEL  // one past the last valid value
233 };
234 
235 enum class PatternType : int8_t {
236   COLOR,
237   SURFACE,
238   LINEAR_GRADIENT,
239   RADIAL_GRADIENT
240 };
241 
242 enum class JoinStyle : int8_t {
243   BEVEL,
244   ROUND,
245   MITER,  //!< Mitered if within the miter limit, else, if the backed supports
246           //!< it (D2D), the miter is clamped. If the backend does not support
247           //!< miter clamping the behavior is as for MITER_OR_BEVEL.
248   MITER_OR_BEVEL  //!< Mitered if within the miter limit, else beveled.
249 };
250 
251 enum class CapStyle : int8_t { BUTT, ROUND, SQUARE };
252 
253 enum class SamplingBounds : int8_t { UNBOUNDED, BOUNDED };
254 
255 // Moz2d version for SVG mask types
256 enum class LuminanceType : int8_t {
257   LUMINANCE,
258   LINEARRGB,
259 };
260 
261 /* Color is stored in non-premultiplied form */
262 struct Color {
263  public:
ColorColor264   Color() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {}
ColorColor265   Color(Float aR, Float aG, Float aB, Float aA) : r(aR), g(aG), b(aB), a(aA) {}
ColorColor266   Color(Float aR, Float aG, Float aB) : r(aR), g(aG), b(aB), a(1.0f) {}
267 
FromABGRColor268   static Color FromABGR(uint32_t aColor) {
269     Color newColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f),
270                    ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
271                    ((aColor >> 16) & 0xff) * (1.0f / 255.0f),
272                    ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
273 
274     return newColor;
275   }
276 
277   // The "Unusual" prefix is to avoid unintentionally using this function when
278   // FromABGR(), which is much more common, is needed.
UnusualFromARGBColor279   static Color UnusualFromARGB(uint32_t aColor) {
280     Color newColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f),
281                    ((aColor >> 8) & 0xff) * (1.0f / 255.0f),
282                    ((aColor >> 0) & 0xff) * (1.0f / 255.0f),
283                    ((aColor >> 24) & 0xff) * (1.0f / 255.0f));
284 
285     return newColor;
286   }
287 
ToABGRColor288   uint32_t ToABGR() const {
289     return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 |
290            uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
291   }
292 
293   // The "Unusual" prefix is to avoid unintentionally using this function when
294   // ToABGR(), which is much more common, is needed.
UnusualToARGBColor295   uint32_t UnusualToARGB() const {
296     return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 |
297            uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24;
298   }
299 
300   bool operator==(const Color& aColor) const {
301     return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a;
302   }
303 
304   bool operator!=(const Color& aColor) const { return !(*this == aColor); }
305 
306   Float r, g, b, a;
307 };
308 
309 struct GradientStop {
310   bool operator<(const GradientStop& aOther) const {
311     return offset < aOther.offset;
312   }
313 
314   Float offset;
315   Color color;
316 };
317 
318 enum class JobStatus { Complete, Wait, Yield, Error };
319 
320 }  // namespace gfx
321 }  // namespace mozilla
322 
323 // XXX: temporary
324 typedef mozilla::gfx::SurfaceFormat gfxImageFormat;
325 
326 #if defined(XP_WIN) && defined(MOZ_GFX)
327 #ifdef GFX2D_INTERNAL
328 #define GFX2D_API __declspec(dllexport)
329 #else
330 #define GFX2D_API __declspec(dllimport)
331 #endif
332 #else
333 #define GFX2D_API
334 #endif
335 
336 namespace mozilla {
337 
338 // Side constants for use in various places.
339 enum Side { eSideTop, eSideRight, eSideBottom, eSideLeft };
340 
341 enum SideBits {
342   eSideBitsNone = 0,
343   eSideBitsTop = 1 << eSideTop,
344   eSideBitsRight = 1 << eSideRight,
345   eSideBitsBottom = 1 << eSideBottom,
346   eSideBitsLeft = 1 << eSideLeft,
347   eSideBitsTopBottom = eSideBitsTop | eSideBitsBottom,
348   eSideBitsLeftRight = eSideBitsLeft | eSideBitsRight,
349   eSideBitsAll = eSideBitsTopBottom | eSideBitsLeftRight
350 };
351 
352 // Creates a for loop that walks over the four mozilla::Side values.
353 // We use an int32_t helper variable (instead of a Side) for our loop counter,
354 // to avoid triggering undefined behavior just before we exit the loop (at
355 // which point the counter is incremented beyond the largest valid Side value).
356 #define NS_FOR_CSS_SIDES(var_)                                               \
357   int32_t MOZ_CONCAT(var_, __LINE__) = mozilla::eSideTop;                    \
358   for (mozilla::Side var_;                                                   \
359        MOZ_CONCAT(var_, __LINE__) <= mozilla::eSideLeft &&                   \
360        (static_cast<void>(var_ = mozilla::Side(MOZ_CONCAT(var_, __LINE__))), \
361         true);                                                               \
362        ++MOZ_CONCAT(var_, __LINE__))
363 
364 static inline Side& operator++(Side& side) {
365   MOZ_ASSERT(side >= eSideTop && side <= eSideLeft, "Out of range side");
366   side = Side(side + 1);
367   return side;
368 }
369 
370 enum Corner {
371   // This order is important!
372   eCornerTopLeft = 0,
373   eCornerTopRight = 1,
374   eCornerBottomRight = 2,
375   eCornerBottomLeft = 3
376 };
377 
378 // RectCornerRadii::radii depends on this value. It is not being added to
379 // Corner because we want to lift the responsibility to handle it in the
380 // switch-case.
381 constexpr int eCornerCount = 4;
382 
383 // Creates a for loop that walks over the four mozilla::Corner values. This
384 // implementation uses the same technique as NS_FOR_CSS_SIDES.
385 #define NS_FOR_CSS_FULL_CORNERS(var_)                                          \
386   int32_t MOZ_CONCAT(var_, __LINE__) = mozilla::eCornerTopLeft;                \
387   for (mozilla::Corner var_;                                                   \
388        MOZ_CONCAT(var_, __LINE__) <= mozilla::eCornerBottomLeft &&             \
389        (static_cast<void>(var_ = mozilla::Corner(MOZ_CONCAT(var_, __LINE__))), \
390         true);                                                                 \
391        ++MOZ_CONCAT(var_, __LINE__))
392 
393 static inline Corner operator++(Corner& aCorner) {
394   MOZ_ASSERT(aCorner >= eCornerTopLeft && aCorner <= eCornerBottomLeft,
395              "Out of range corner!");
396   aCorner = Corner(aCorner + 1);
397   return aCorner;
398 }
399 
400 // Indices into "half corner" arrays (nsStyleCorners e.g.)
401 enum HalfCorner {
402   // This order is important!
403   eCornerTopLeftX = 0,
404   eCornerTopLeftY = 1,
405   eCornerTopRightX = 2,
406   eCornerTopRightY = 3,
407   eCornerBottomRightX = 4,
408   eCornerBottomRightY = 5,
409   eCornerBottomLeftX = 6,
410   eCornerBottomLeftY = 7
411 };
412 
413 // Creates a for loop that walks over the eight mozilla::HalfCorner values.
414 // This implementation uses the same technique as NS_FOR_CSS_SIDES.
415 #define NS_FOR_CSS_HALF_CORNERS(var_)                                \
416   int32_t MOZ_CONCAT(var_, __LINE__) = mozilla::eCornerTopLeftX;     \
417   for (mozilla::HalfCorner var_;                                     \
418        MOZ_CONCAT(var_, __LINE__) <= mozilla::eCornerBottomLeftY &&  \
419        (static_cast<void>(                                           \
420             var_ = mozilla::HalfCorner(MOZ_CONCAT(var_, __LINE__))), \
421         true);                                                       \
422        ++MOZ_CONCAT(var_, __LINE__))
423 
424 static inline HalfCorner operator++(HalfCorner& aHalfCorner) {
425   MOZ_ASSERT(
426       aHalfCorner >= eCornerTopLeftX && aHalfCorner <= eCornerBottomLeftY,
427       "Out of range half corner!");
428   aHalfCorner = HalfCorner(aHalfCorner + 1);
429   return aHalfCorner;
430 }
431 
432 // The result of these conversion functions are exhaustively checked in
433 // nsStyleCoord.cpp, which also serves as usage examples.
434 
HalfCornerIsX(HalfCorner aHalfCorner)435 constexpr bool HalfCornerIsX(HalfCorner aHalfCorner) {
436   return !(aHalfCorner % 2);
437 }
438 
HalfToFullCorner(HalfCorner aHalfCorner)439 constexpr Corner HalfToFullCorner(HalfCorner aHalfCorner) {
440   return Corner(aHalfCorner / 2);
441 }
442 
FullToHalfCorner(Corner aCorner,bool aIsVertical)443 constexpr HalfCorner FullToHalfCorner(Corner aCorner, bool aIsVertical) {
444   return HalfCorner(aCorner * 2 + aIsVertical);
445 }
446 
SideIsVertical(Side aSide)447 constexpr bool SideIsVertical(Side aSide) { return aSide % 2; }
448 
449 // @param aIsSecond when true, return the clockwise second of the two
450 // corners associated with aSide. For example, with aSide = eSideBottom the
451 // result is eCornerBottomRight when aIsSecond is false, and
452 // eCornerBottomLeft when aIsSecond is true.
SideToFullCorner(Side aSide,bool aIsSecond)453 constexpr Corner SideToFullCorner(Side aSide, bool aIsSecond) {
454   return Corner((aSide + aIsSecond) % 4);
455 }
456 
457 // @param aIsSecond see SideToFullCorner.
458 // @param aIsParallel return the half-corner that is parallel with aSide
459 // when aIsParallel is true. For example with aSide=eSideTop, aIsSecond=true
460 // the result is eCornerTopRightX when aIsParallel is true, and
461 // eCornerTopRightY when aIsParallel is false (because "X" is parallel with
462 // eSideTop/eSideBottom, similarly "Y" is parallel with
463 // eSideLeft/eSideRight)
SideToHalfCorner(Side aSide,bool aIsSecond,bool aIsParallel)464 constexpr HalfCorner SideToHalfCorner(Side aSide, bool aIsSecond,
465                                       bool aIsParallel) {
466   return HalfCorner(((aSide + aIsSecond) * 2 + (aSide + !aIsParallel) % 2) % 8);
467 }
468 
469 }  // namespace mozilla
470 
471 #endif /* MOZILLA_GFX_TYPES_H_ */
472