Types.h (35967B)
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/DefineEnum.h" // for MOZ_DEFINE_ENUM_CLASS_WITH_BASE 11 #include "mozilla/EndianUtils.h" 12 #include "mozilla/EnumeratedRange.h" 13 #include "mozilla/MacroArgs.h" // for MOZ_CONCAT 14 #include "mozilla/TypedEnumBits.h" 15 16 #include <iosfwd> // for ostream 17 #include <stddef.h> 18 #include <stdint.h> 19 #include <optional> 20 21 namespace mozilla { 22 namespace gfx { 23 24 typedef float Float; 25 typedef double Double; 26 27 enum class SurfaceType : int8_t { 28 DATA, /* Data surface - bitmap in memory */ 29 CAIRO, /* Surface wrapping a cairo surface */ 30 CAIRO_IMAGE, /* Data surface wrapping a cairo image surface */ 31 COREGRAPHICS_IMAGE, /* Surface wrapping a CoreGraphics Image */ 32 COREGRAPHICS_CGCONTEXT, /* Surface wrapping a CG context */ 33 SKIA, /* Surface wrapping a Skia bitmap */ 34 RECORDING, /* Surface used for recording */ 35 DATA_SHARED, /* Data surface using shared memory */ 36 DATA_RECYCLING_SHARED, /* Data surface using shared memory */ 37 OFFSET, /* Offset */ 38 DATA_ALIGNED, /* Data surface using aligned heap memory */ 39 DATA_SHARED_WRAPPER, /* Shared memory mapped in from another process */ 40 BLOB_IMAGE, /* Recorded blob image */ 41 DATA_MAPPED, /* Data surface wrapping a ScopedMap */ 42 WEBGL, /* Surface wrapping a DrawTargetWebgl texture */ 43 D3D11_TEXTURE, /* Surface wrapping a D3D11Texture */ 44 }; 45 46 enum class SurfaceFormat : int8_t { 47 // The following values are named to reflect layout of colors in memory, from 48 // lowest byte to highest byte. The 32-bit value layout depends on machine 49 // endianness. 50 // in-memory 32-bit LE value 32-bit BE value 51 B8G8R8A8, // [BB, GG, RR, AA] 0xAARRGGBB 0xBBGGRRAA 52 B8G8R8X8, // [BB, GG, RR, 00] 0x00RRGGBB 0xBBGGRR00 53 R8G8B8A8, // [RR, GG, BB, AA] 0xAABBGGRR 0xRRGGBBAA 54 R8G8B8X8, // [RR, GG, BB, 00] 0x00BBGGRR 0xRRGGBB00 55 A8R8G8B8, // [AA, RR, GG, BB] 0xBBGGRRAA 0xAARRGGBB 56 X8R8G8B8, // [00, RR, GG, BB] 0xBBGGRR00 0x00RRGGBB 57 58 R8G8B8, 59 B8G8R8, 60 61 // The _UINT16 suffix here indicates that the name reflects the layout when 62 // viewed as a uint16_t value. In memory these values are stored using native 63 // endianness. 64 R5G6B5_UINT16, // 0bRRRRRGGGGGGBBBBB 65 66 // This one is a single-byte, so endianness isn't an issue. 67 A8, 68 A16, 69 70 R8G8, 71 R16G16, 72 73 // These ones are their own special cases. 74 YUV420, // Sometimes called YU12. 3 planes of 8 bit Y, then Cb, then Cr. 75 // 4:2:0 chroma subsampling. 76 YUV420P10, // YUV420 but with 16 bit plane values where the 6 most 77 // significant bits are 0 (so it's 10-bit format). 78 YUV422P10, // 3 planes like YUV420, but with 4:2:2 chroma subampling and 79 // 16 bit plane values where the 6 least significant bits are 0. 80 NV12, // 2 planes. YUV 4:2:0 image with a plane of 8 bit Y samples 81 // followed by an interleaved U/V plane containing 8 bit 2x2 82 // subsampled colour difference samples. 83 P016, // Similar to NV12, but with 16 bits plane values 84 P010, // Identical to P016 but the 6 least significant bits are 0. 85 // With DXGI in theory entirely compatible, however practice has 86 // shown that it's not the case. 87 NV16, // Similar to NV12, but with 4:2:2 chroma subsampling. Technically 88 // 8 bit, but we only use it for 10 bit, and it's really only here 89 // to support the macOS bi-planar 422 formats. 90 YUY2, // Sometimes called YUYV. Single plane / packed YUV 4:2:2 8 bit 91 // samples interleaved as Y`0 Cb Y`1 Cr. Since 4 pixels require 92 // 64 bits, this can also be considered a 16bpp format, but each 93 // component is only 8 bits. We sometimes pack RGBA data into 94 // this format. 95 HSV, 96 Lab, 97 Depth, 98 99 // LE packed 10bit per channel format primarily associated with HDR10 video. 100 R10G10B10A2_UINT32, // 0bAARRRRRRRRRRGGGGGGGGGGBBBBBBBBBB 101 // Same as R10G10B10A2_UINT32 but with the alpha channel ignored. 102 R10G10B10X2_UINT32, // 0b00RRRRRRRRRRGGGGGGGGGGBBBBBBBBBB 103 // 4 half-float (f16) components in RGBA order for HDR rendering, each is 104 // machine endian. 105 R16G16B16A16F, 106 107 // This represents the unknown format. 108 UNKNOWN, // TODO: Replace uses with Maybe<SurfaceFormat>. 109 110 // The following values are endian-independent synonyms. The _UINT32 suffix 111 // indicates that the name reflects the layout when viewed as a uint32_t 112 // value. 113 #if MOZ_LITTLE_ENDIAN() 114 A8R8G8B8_UINT32 = B8G8R8A8, // 0xAARRGGBB 115 X8R8G8B8_UINT32 = B8G8R8X8, // 0x00RRGGBB 116 #elif MOZ_BIG_ENDIAN() 117 A8R8G8B8_UINT32 = A8R8G8B8, // 0xAARRGGBB 118 X8R8G8B8_UINT32 = X8R8G8B8, // 0x00RRGGBB 119 #else 120 # error "bad endianness" 121 #endif 122 123 // The following values are OS and endian-independent synonyms. 124 // 125 // TODO(aosmond): When everything blocking bug 1581828 has been resolved, we 126 // can make this use R8B8G8A8 and R8B8G8X8 for non-Windows platforms. 127 OS_RGBA = A8R8G8B8_UINT32, 128 OS_RGBX = X8R8G8B8_UINT32 129 }; 130 131 enum class SubpixelOrder : uint8_t { 132 UNKNOWN, 133 RGB, 134 BGR, 135 VRGB, 136 VBGR, 137 }; 138 139 struct SurfaceFormatInfo { 140 bool hasColor; 141 bool hasAlpha; 142 bool isYuv; 143 std::optional<uint8_t> bytesPerPixel; 144 }; 145 inline std::optional<SurfaceFormatInfo> Info(const SurfaceFormat aFormat) { 146 auto info = SurfaceFormatInfo{}; 147 148 switch (aFormat) { 149 case SurfaceFormat::B8G8R8A8: 150 case SurfaceFormat::R8G8B8A8: 151 case SurfaceFormat::A8R8G8B8: 152 case SurfaceFormat::R10G10B10A2_UINT32: 153 case SurfaceFormat::R16G16B16A16F: 154 info.hasColor = true; 155 info.hasAlpha = true; 156 break; 157 158 case SurfaceFormat::B8G8R8X8: 159 case SurfaceFormat::R8G8B8X8: 160 case SurfaceFormat::X8R8G8B8: 161 case SurfaceFormat::R8G8B8: 162 case SurfaceFormat::B8G8R8: 163 case SurfaceFormat::R5G6B5_UINT16: 164 case SurfaceFormat::R10G10B10X2_UINT32: 165 case SurfaceFormat::R8G8: 166 case SurfaceFormat::R16G16: 167 case SurfaceFormat::HSV: 168 case SurfaceFormat::Lab: 169 info.hasColor = true; 170 info.hasAlpha = false; 171 break; 172 173 case SurfaceFormat::A8: 174 case SurfaceFormat::A16: 175 info.hasColor = false; 176 info.hasAlpha = true; 177 break; 178 179 case SurfaceFormat::YUV420: 180 case SurfaceFormat::YUV420P10: 181 case SurfaceFormat::YUV422P10: 182 case SurfaceFormat::NV12: 183 case SurfaceFormat::P016: 184 case SurfaceFormat::P010: 185 case SurfaceFormat::NV16: 186 case SurfaceFormat::YUY2: 187 info.hasColor = true; 188 info.hasAlpha = false; 189 info.isYuv = true; 190 break; 191 192 case SurfaceFormat::Depth: 193 info.hasColor = false; 194 info.hasAlpha = false; 195 info.isYuv = false; 196 break; 197 198 case SurfaceFormat::UNKNOWN: 199 break; 200 } 201 202 // - 203 // bytesPerPixel 204 205 switch (aFormat) { 206 case SurfaceFormat::B8G8R8A8: 207 case SurfaceFormat::R8G8B8A8: 208 case SurfaceFormat::A8R8G8B8: 209 case SurfaceFormat::B8G8R8X8: 210 case SurfaceFormat::R8G8B8X8: 211 case SurfaceFormat::X8R8G8B8: 212 case SurfaceFormat::R16G16: 213 info.bytesPerPixel = 4; 214 break; 215 216 case SurfaceFormat::R8G8B8: 217 case SurfaceFormat::B8G8R8: 218 info.bytesPerPixel = 3; 219 break; 220 221 case SurfaceFormat::R5G6B5_UINT16: 222 case SurfaceFormat::R8G8: 223 case SurfaceFormat::A16: 224 case SurfaceFormat::Depth: // uint16_t 225 info.bytesPerPixel = 2; 226 break; 227 228 case SurfaceFormat::A8: 229 info.bytesPerPixel = 1; 230 break; 231 232 case SurfaceFormat::R10G10B10A2_UINT32: 233 case SurfaceFormat::R10G10B10X2_UINT32: 234 info.bytesPerPixel = 4; 235 break; 236 237 case SurfaceFormat::R16G16B16A16F: 238 info.bytesPerPixel = 8; 239 break; 240 241 case SurfaceFormat::HSV: 242 case SurfaceFormat::Lab: 243 info.bytesPerPixel = 3 * sizeof(float); 244 break; 245 246 case SurfaceFormat::YUV420: 247 case SurfaceFormat::YUV420P10: 248 case SurfaceFormat::YUV422P10: 249 case SurfaceFormat::NV12: 250 case SurfaceFormat::P016: 251 case SurfaceFormat::P010: 252 case SurfaceFormat::NV16: 253 case SurfaceFormat::YUY2: 254 case SurfaceFormat::UNKNOWN: 255 break; // No bytesPerPixel per se. 256 } 257 258 // - 259 260 if (aFormat == SurfaceFormat::UNKNOWN) { 261 return {}; 262 } 263 return info; 264 } 265 266 std::ostream& operator<<(std::ostream& aOut, const SurfaceFormat& aFormat); 267 268 // Represents the bit-shifts required to access color channels when the layout 269 // is viewed as a uint32_t value. 270 enum class SurfaceFormatBit : uint32_t { 271 #if MOZ_LITTLE_ENDIAN() 272 R8G8B8A8_R = 0, 273 R8G8B8A8_G = 8, 274 R8G8B8A8_B = 16, 275 R8G8B8A8_A = 24, 276 #elif MOZ_BIG_ENDIAN() 277 R8G8B8A8_A = 0, 278 R8G8B8A8_B = 8, 279 R8G8B8A8_G = 16, 280 R8G8B8A8_R = 24, 281 #else 282 # error "bad endianness" 283 #endif 284 285 // The following values are endian-independent for A8R8G8B8_UINT32. 286 A8R8G8B8_UINT32_B = 0, 287 A8R8G8B8_UINT32_G = 8, 288 A8R8G8B8_UINT32_R = 16, 289 A8R8G8B8_UINT32_A = 24, 290 291 // The following values are OS and endian-independent. 292 // 293 // TODO(aosmond): When everything blocking bug 1581828 has been resolved, we 294 // can make this use R8G8B8A8_X for non-Windows platforms. 295 OS_R = A8R8G8B8_UINT32_R, 296 OS_G = A8R8G8B8_UINT32_G, 297 OS_B = A8R8G8B8_UINT32_B, 298 OS_A = A8R8G8B8_UINT32_A, 299 }; 300 301 inline uint32_t operator<<(uint8_t a, SurfaceFormatBit b) { 302 return a << static_cast<uint32_t>(b); 303 } 304 305 inline uint32_t operator>>(uint32_t a, SurfaceFormatBit b) { 306 return a >> static_cast<uint32_t>(b); 307 } 308 309 static inline int BytesPerPixel(SurfaceFormat aFormat) { 310 // TODO: return Info(aFormat).value().bytesPerPixel.value(); 311 switch (aFormat) { 312 case SurfaceFormat::A8: 313 return 1; 314 case SurfaceFormat::R5G6B5_UINT16: 315 case SurfaceFormat::A16: 316 return 2; 317 case SurfaceFormat::R8G8B8: 318 case SurfaceFormat::B8G8R8: 319 return 3; 320 case SurfaceFormat::HSV: 321 case SurfaceFormat::Lab: 322 return 3 * sizeof(float); 323 case SurfaceFormat::Depth: 324 return sizeof(uint16_t); 325 case SurfaceFormat::B8G8R8A8: 326 case SurfaceFormat::B8G8R8X8: 327 case SurfaceFormat::R8G8B8A8: 328 case SurfaceFormat::R8G8B8X8: 329 case SurfaceFormat::A8R8G8B8: 330 case SurfaceFormat::X8R8G8B8: 331 case SurfaceFormat::R10G10B10A2_UINT32: 332 case SurfaceFormat::R10G10B10X2_UINT32: 333 case SurfaceFormat::R16G16: 334 return 4; 335 case SurfaceFormat::R16G16B16A16F: 336 return 8; 337 case SurfaceFormat::R8G8: 338 return 2; 339 case SurfaceFormat::YUV420: 340 case SurfaceFormat::YUV420P10: 341 case SurfaceFormat::YUV422P10: 342 case SurfaceFormat::NV12: 343 case SurfaceFormat::NV16: 344 case SurfaceFormat::YUY2: 345 // These formats are not easily described in terms of bytes per pixel, 346 // technically 1.5 bytes per pixel on average, which is guaranteed by the 347 // width and height being multiples of 2. 348 return 0; 349 case SurfaceFormat::P016: 350 case SurfaceFormat::P010: 351 // Similar to NV12 but uint16 pixels. 352 return 0; 353 case SurfaceFormat::UNKNOWN: 354 MOZ_ASSERT_UNREACHABLE("unhandled gfx::SurfaceFormat::UNKNOWN"); 355 return 4; 356 } 357 MOZ_ASSERT_UNREACHABLE("unhandled enum value for gfx::SurfaceFormat"); 358 return 4; 359 } 360 361 inline bool IsOpaque(SurfaceFormat aFormat) { 362 // TODO: return Info(aFormat).value().hasAlpha; 363 switch (aFormat) { 364 case SurfaceFormat::B8G8R8X8: 365 case SurfaceFormat::R8G8B8X8: 366 case SurfaceFormat::X8R8G8B8: 367 case SurfaceFormat::R5G6B5_UINT16: 368 case SurfaceFormat::R10G10B10X2_UINT32: 369 case SurfaceFormat::R8G8B8: 370 case SurfaceFormat::B8G8R8: 371 case SurfaceFormat::R8G8: 372 case SurfaceFormat::HSV: 373 case SurfaceFormat::Lab: 374 case SurfaceFormat::Depth: 375 case SurfaceFormat::YUV420: 376 case SurfaceFormat::NV12: 377 case SurfaceFormat::P010: 378 case SurfaceFormat::P016: 379 case SurfaceFormat::YUY2: 380 return true; 381 case SurfaceFormat::B8G8R8A8: 382 case SurfaceFormat::R8G8B8A8: 383 case SurfaceFormat::A8R8G8B8: 384 case SurfaceFormat::R10G10B10A2_UINT32: 385 case SurfaceFormat::R16G16B16A16F: 386 case SurfaceFormat::A8: 387 case SurfaceFormat::A16: 388 case SurfaceFormat::R16G16: 389 case SurfaceFormat::YUV420P10: 390 case SurfaceFormat::YUV422P10: 391 case SurfaceFormat::NV16: 392 case SurfaceFormat::UNKNOWN: 393 return false; 394 } 395 MOZ_ASSERT_UNREACHABLE("unhandled enum value for gfx::SurfaceFormat"); 396 return false; 397 } 398 399 // These are standardized Coding-independent Code Points 400 // See [Rec. ITU-T H.273 401 // (12/2016)](https://www.itu.int/rec/T-REC-H.273-201612-I/en) 402 // 403 // We deliberately use an unscoped enum with fixed uint8_t representation since 404 // all possible values [0, 255] are legal, but it's unwieldy to declare 200+ 405 // "RESERVED" enumeration values. Having a fixed underlying type avoids any 406 // potential UB and avoids the need for a cast when passing these values across 407 // FFI to functions like qcms_profile_create_cicp. 408 namespace CICP { 409 enum ColourPrimaries : uint8_t { 410 CP_RESERVED_MIN = 0, // 0, 3, [13, 21], [23, 255] are all reserved 411 CP_BT709 = 1, 412 CP_UNSPECIFIED = 2, 413 CP_BT470M = 4, 414 CP_BT470BG = 5, 415 CP_BT601 = 6, 416 CP_SMPTE240 = 7, 417 CP_GENERIC_FILM = 8, 418 CP_BT2020 = 9, 419 CP_XYZ = 10, 420 CP_SMPTE431 = 11, 421 CP_SMPTE432 = 12, 422 CP_EBU3213 = 22, 423 }; 424 425 inline bool IsReserved(ColourPrimaries aIn) { 426 switch (aIn) { 427 case CP_BT709: 428 case CP_UNSPECIFIED: 429 case CP_BT470M: 430 case CP_BT470BG: 431 case CP_BT601: 432 case CP_SMPTE240: 433 case CP_GENERIC_FILM: 434 case CP_BT2020: 435 case CP_XYZ: 436 case CP_SMPTE431: 437 case CP_SMPTE432: 438 case CP_EBU3213: 439 return false; 440 default: 441 return true; 442 } 443 } 444 445 enum TransferCharacteristics : uint8_t { 446 TC_RESERVED_MIN = 0, // 0, 3, [19, 255] are all reserved 447 TC_BT709 = 1, 448 TC_UNSPECIFIED = 2, 449 TC_BT470M = 4, 450 TC_BT470BG = 5, 451 TC_BT601 = 6, 452 TC_SMPTE240 = 7, 453 TC_LINEAR = 8, 454 TC_LOG_100 = 9, 455 TC_LOG_100_SQRT10 = 10, 456 TC_IEC61966 = 11, 457 TC_BT_1361 = 12, 458 TC_SRGB = 13, 459 TC_BT2020_10BIT = 14, 460 TC_BT2020_12BIT = 15, 461 TC_SMPTE2084 = 16, 462 TC_SMPTE428 = 17, 463 TC_HLG = 18, 464 }; 465 466 inline bool IsReserved(TransferCharacteristics aIn) { 467 switch (aIn) { 468 case TC_BT709: 469 case TC_UNSPECIFIED: 470 case TC_BT470M: 471 case TC_BT470BG: 472 case TC_BT601: 473 case TC_SMPTE240: 474 case TC_LINEAR: 475 case TC_LOG_100: 476 case TC_LOG_100_SQRT10: 477 case TC_IEC61966: 478 case TC_BT_1361: 479 case TC_SRGB: 480 case TC_BT2020_10BIT: 481 case TC_BT2020_12BIT: 482 case TC_SMPTE2084: 483 case TC_SMPTE428: 484 case TC_HLG: 485 return false; 486 default: 487 return true; 488 } 489 } 490 491 enum MatrixCoefficients : uint8_t { 492 MC_IDENTITY = 0, 493 MC_BT709 = 1, 494 MC_UNSPECIFIED = 2, 495 MC_RESERVED_MIN = 3, // 3, [15, 255] are all reserved 496 MC_FCC = 4, 497 MC_BT470BG = 5, 498 MC_BT601 = 6, 499 MC_SMPTE240 = 7, 500 MC_YCGCO = 8, 501 MC_BT2020_NCL = 9, 502 MC_BT2020_CL = 10, 503 MC_SMPTE2085 = 11, 504 MC_CHROMAT_NCL = 12, 505 MC_CHROMAT_CL = 13, 506 MC_ICTCP = 14, 507 }; 508 509 inline bool IsReserved(MatrixCoefficients aIn) { 510 switch (aIn) { 511 case MC_IDENTITY: 512 case MC_BT709: 513 case MC_UNSPECIFIED: 514 case MC_RESERVED_MIN: 515 case MC_FCC: 516 case MC_BT470BG: 517 case MC_BT601: 518 case MC_SMPTE240: 519 case MC_YCGCO: 520 case MC_BT2020_NCL: 521 case MC_BT2020_CL: 522 case MC_SMPTE2085: 523 case MC_CHROMAT_NCL: 524 case MC_CHROMAT_CL: 525 case MC_ICTCP: 526 return false; 527 default: 528 return true; 529 } 530 } 531 } // namespace CICP 532 533 // The matrix coeffiecients used for YUV to RGB conversion. 534 enum class YUVColorSpace : uint8_t { 535 BT601, 536 BT709, 537 BT2020, 538 Identity, // Todo: s/YUVColorSpace/ColorSpace/, s/Identity/SRGB/ 539 Default = BT709, 540 _First = BT601, 541 _Last = Identity, 542 }; 543 544 enum class ColorDepth : uint8_t { 545 COLOR_8, 546 COLOR_10, 547 COLOR_12, 548 COLOR_16, 549 _First = COLOR_8, 550 _Last = COLOR_16, 551 }; 552 553 std::ostream& operator<<(std::ostream& aOut, const ColorDepth& aColorDepth); 554 555 enum class TransferFunction : uint8_t { 556 BT709, 557 SRGB, 558 PQ, 559 HLG, 560 _First = BT709, 561 _Last = HLG, 562 Default = BT709, 563 }; 564 565 enum class ColorRange : uint8_t { 566 LIMITED, 567 FULL, 568 _First = LIMITED, 569 _Last = FULL, 570 }; 571 572 // Really "YcbcrColorColorSpace" 573 enum class YUVRangedColorSpace : uint8_t { 574 BT601_Narrow = 0, 575 BT601_Full, 576 BT709_Narrow, 577 BT709_Full, 578 BT2020_Narrow, 579 BT2020_Full, 580 GbrIdentity, 581 582 _First = BT601_Narrow, 583 _Last = GbrIdentity, 584 Default = BT709_Narrow, 585 }; 586 587 // I can either come up with a longer "very clever" name that doesn't conflict 588 // with FilterSupport.h, embrace and expand FilterSupport, or rename the old 589 // one. 590 // Some times Worse Is Better. 591 enum class ColorSpace2 : uint8_t { 592 Display, 593 UNKNOWN = Display, // We feel sufficiently bad about this TODO. 594 SRGB, 595 DISPLAY_P3, 596 BT601_525, // aka smpte170m NTSC 597 BT709, // Same gamut as SRGB, but different gamma. 598 BT601_625 = 599 BT709, // aka bt470bg PAL. Basically BT709, just Xg is 0.290 not 0.300. 600 BT2020, 601 _First = Display, 602 _Last = BT2020, 603 }; 604 605 inline ColorSpace2 ToColorSpace2(const YUVColorSpace in) { 606 switch (in) { 607 case YUVColorSpace::BT601: 608 return ColorSpace2::BT601_525; 609 case YUVColorSpace::BT709: 610 return ColorSpace2::BT709; 611 case YUVColorSpace::BT2020: 612 return ColorSpace2::BT2020; 613 case YUVColorSpace::Identity: 614 return ColorSpace2::SRGB; 615 } 616 MOZ_ASSERT_UNREACHABLE(); 617 } 618 619 inline YUVColorSpace ToYUVColorSpace(const ColorSpace2 in) { 620 switch (in) { 621 case ColorSpace2::BT601_525: 622 return YUVColorSpace::BT601; 623 case ColorSpace2::BT709: 624 return YUVColorSpace::BT709; 625 case ColorSpace2::BT2020: 626 return YUVColorSpace::BT2020; 627 case ColorSpace2::SRGB: 628 return YUVColorSpace::Identity; 629 630 case ColorSpace2::UNKNOWN: 631 case ColorSpace2::DISPLAY_P3: 632 MOZ_CRASH("Bad ColorSpace2 for ToYUVColorSpace"); 633 } 634 MOZ_ASSERT_UNREACHABLE(); 635 } 636 637 struct FromYUVRangedColorSpaceT final { 638 const YUVColorSpace space; 639 const ColorRange range; 640 }; 641 642 inline FromYUVRangedColorSpaceT FromYUVRangedColorSpace( 643 const YUVRangedColorSpace s) { 644 switch (s) { 645 case YUVRangedColorSpace::BT601_Narrow: 646 return {YUVColorSpace::BT601, ColorRange::LIMITED}; 647 case YUVRangedColorSpace::BT601_Full: 648 return {YUVColorSpace::BT601, ColorRange::FULL}; 649 650 case YUVRangedColorSpace::BT709_Narrow: 651 return {YUVColorSpace::BT709, ColorRange::LIMITED}; 652 case YUVRangedColorSpace::BT709_Full: 653 return {YUVColorSpace::BT709, ColorRange::FULL}; 654 655 case YUVRangedColorSpace::BT2020_Narrow: 656 return {YUVColorSpace::BT2020, ColorRange::LIMITED}; 657 case YUVRangedColorSpace::BT2020_Full: 658 return {YUVColorSpace::BT2020, ColorRange::FULL}; 659 660 case YUVRangedColorSpace::GbrIdentity: 661 return {YUVColorSpace::Identity, ColorRange::FULL}; 662 } 663 MOZ_CRASH("bad YUVRangedColorSpace"); 664 } 665 666 // Todo: This should go in the CPP. 667 inline YUVRangedColorSpace ToYUVRangedColorSpace(const YUVColorSpace space, 668 const ColorRange range) { 669 bool narrow; 670 switch (range) { 671 case ColorRange::FULL: 672 narrow = false; 673 break; 674 case ColorRange::LIMITED: 675 narrow = true; 676 break; 677 } 678 679 switch (space) { 680 case YUVColorSpace::Identity: 681 MOZ_ASSERT(range == ColorRange::FULL); 682 return YUVRangedColorSpace::GbrIdentity; 683 684 case YUVColorSpace::BT601: 685 return narrow ? YUVRangedColorSpace::BT601_Narrow 686 : YUVRangedColorSpace::BT601_Full; 687 688 case YUVColorSpace::BT709: 689 return narrow ? YUVRangedColorSpace::BT709_Narrow 690 : YUVRangedColorSpace::BT709_Full; 691 692 case YUVColorSpace::BT2020: 693 return narrow ? YUVRangedColorSpace::BT2020_Narrow 694 : YUVRangedColorSpace::BT2020_Full; 695 } 696 MOZ_CRASH("bad YUVColorSpace"); 697 } 698 699 template <typename DescriptorT> 700 inline YUVRangedColorSpace GetYUVRangedColorSpace(const DescriptorT& d) { 701 return ToYUVRangedColorSpace(d.yUVColorSpace(), d.colorRange()); 702 } 703 704 static inline SurfaceFormat SurfaceFormatForColorDepth(ColorDepth aColorDepth) { 705 SurfaceFormat format = SurfaceFormat::A8; 706 switch (aColorDepth) { 707 case ColorDepth::COLOR_8: 708 break; 709 case ColorDepth::COLOR_10: 710 case ColorDepth::COLOR_12: 711 case ColorDepth::COLOR_16: 712 format = SurfaceFormat::A16; 713 break; 714 } 715 return format; 716 } 717 718 static inline uint8_t BitDepthForColorDepth(ColorDepth aColorDepth) { 719 uint8_t depth = 8; 720 switch (aColorDepth) { 721 case ColorDepth::COLOR_8: 722 break; 723 case ColorDepth::COLOR_10: 724 depth = 10; 725 break; 726 case ColorDepth::COLOR_12: 727 depth = 12; 728 break; 729 case ColorDepth::COLOR_16: 730 depth = 16; 731 break; 732 } 733 return depth; 734 } 735 736 static inline ColorDepth ColorDepthForBitDepth(uint8_t aBitDepth) { 737 ColorDepth depth = ColorDepth::COLOR_8; 738 switch (aBitDepth) { 739 case 8: 740 break; 741 case 10: 742 depth = ColorDepth::COLOR_10; 743 break; 744 case 12: 745 depth = ColorDepth::COLOR_12; 746 break; 747 case 16: 748 depth = ColorDepth::COLOR_16; 749 break; 750 } 751 return depth; 752 } 753 754 // 10 and 12 bits color depth image are using 16 bits integers for storage 755 // As such we need to rescale the value from 10 or 12 bits to 16. 756 static inline uint32_t RescalingFactorForColorDepth(ColorDepth aColorDepth) { 757 uint32_t factor = 1; 758 switch (aColorDepth) { 759 case ColorDepth::COLOR_8: 760 break; 761 case ColorDepth::COLOR_10: 762 factor = 64; 763 break; 764 case ColorDepth::COLOR_12: 765 factor = 16; 766 break; 767 case ColorDepth::COLOR_16: 768 break; 769 } 770 return factor; 771 } 772 773 static inline bool IsHDRTransferFunction( 774 gfx::TransferFunction aTransferFunction) { 775 switch (aTransferFunction) { 776 case gfx::TransferFunction::PQ: 777 case gfx::TransferFunction::HLG: 778 return true; 779 case gfx::TransferFunction::BT709: 780 case gfx::TransferFunction::SRGB: 781 return false; 782 } 783 MOZ_CRASH("bad TransferFunction"); 784 } 785 786 enum class ChromaSubsampling : uint8_t { 787 FULL, 788 HALF_WIDTH, 789 HALF_WIDTH_AND_HEIGHT, 790 _First = FULL, 791 _Last = HALF_WIDTH_AND_HEIGHT, 792 }; 793 794 template <typename T> 795 static inline T ChromaSize(const T& aYSize, ChromaSubsampling aSubsampling) { 796 switch (aSubsampling) { 797 case ChromaSubsampling::FULL: 798 return aYSize; 799 case ChromaSubsampling::HALF_WIDTH: 800 return T((aYSize.width + 1) / 2, aYSize.height); 801 case ChromaSubsampling::HALF_WIDTH_AND_HEIGHT: 802 return T((aYSize.width + 1) / 2, (aYSize.height + 1) / 2); 803 } 804 MOZ_CRASH("bad ChromaSubsampling"); 805 } 806 807 enum class FilterType : int8_t { 808 BLEND = 0, 809 TRANSFORM, 810 MORPHOLOGY, 811 COLOR_MATRIX, 812 FLOOD, 813 TILE, 814 TABLE_TRANSFER, 815 DISCRETE_TRANSFER, 816 LINEAR_TRANSFER, 817 GAMMA_TRANSFER, 818 CONVOLVE_MATRIX, 819 DISPLACEMENT_MAP, 820 TURBULENCE, 821 ARITHMETIC_COMBINE, 822 COMPOSITE, 823 DIRECTIONAL_BLUR, 824 GAUSSIAN_BLUR, 825 POINT_DIFFUSE, 826 POINT_SPECULAR, 827 SPOT_DIFFUSE, 828 SPOT_SPECULAR, 829 DISTANT_DIFFUSE, 830 DISTANT_SPECULAR, 831 CROP, 832 PREMULTIPLY, 833 UNPREMULTIPLY, 834 OPACITY 835 }; 836 837 enum class DrawTargetType : int8_t { 838 SOFTWARE_RASTER = 0, 839 HARDWARE_RASTER, 840 VECTOR 841 }; 842 843 enum class BackendType : int8_t { 844 NONE = 0, 845 CAIRO, 846 SKIA, 847 RECORDING, 848 WEBRENDER_TEXT, 849 WEBGL, 850 851 // Add new entries above this line. 852 BACKEND_LAST 853 }; 854 855 enum class RecorderType : int8_t { 856 UNKNOWN, 857 PRIVATE, 858 MEMORY, 859 CANVAS, 860 PRFILEDESC, 861 WEBRENDER 862 }; 863 864 enum class FontType : int8_t { 865 DWRITE, 866 GDI, 867 MAC, 868 FONTCONFIG, 869 FREETYPE, 870 UNKNOWN 871 }; 872 873 enum class NativeSurfaceType : int8_t { 874 D3D10_TEXTURE, 875 CAIRO_CONTEXT, 876 CGCONTEXT, 877 CGCONTEXT_ACCELERATED, 878 OPENGL_TEXTURE, 879 WEBGL_CONTEXT 880 }; 881 882 enum class FontStyle : int8_t { NORMAL, ITALIC, BOLD, BOLD_ITALIC }; 883 884 enum class FontHinting : int8_t { NONE, LIGHT, NORMAL, FULL }; 885 886 enum class CompositionOp : int8_t { 887 OP_CLEAR, 888 OP_OVER, 889 OP_ADD, 890 OP_ATOP, 891 OP_OUT, 892 OP_IN, 893 OP_SOURCE, 894 OP_DEST_IN, 895 OP_DEST_OUT, 896 OP_DEST_OVER, 897 OP_DEST_ATOP, 898 OP_XOR, 899 OP_MULTIPLY, 900 OP_SCREEN, 901 OP_OVERLAY, 902 OP_DARKEN, 903 OP_LIGHTEN, 904 OP_COLOR_DODGE, 905 OP_COLOR_BURN, 906 OP_HARD_LIGHT, 907 OP_SOFT_LIGHT, 908 OP_DIFFERENCE, 909 OP_EXCLUSION, 910 OP_HUE, 911 OP_SATURATION, 912 OP_COLOR, 913 OP_LUMINOSITY, 914 OP_COUNT 915 }; 916 917 enum class Axis : int8_t { X_AXIS, Y_AXIS, BOTH }; 918 919 enum class ExtendMode : int8_t { 920 CLAMP, // Do not repeat 921 REPEAT, // Repeat in both axis 922 REPEAT_X, // Only X axis 923 REPEAT_Y, // Only Y axis 924 REFLECT // Mirror the image 925 }; 926 927 enum class FillRule : int8_t { FILL_WINDING, FILL_EVEN_ODD }; 928 929 enum class AntialiasMode : int8_t { NONE, GRAY, SUBPIXEL, DEFAULT }; 930 931 // See https://en.wikipedia.org/wiki/Texture_filtering 932 enum class SamplingFilter : int8_t { 933 GOOD, 934 LINEAR, 935 POINT, 936 SENTINEL // one past the last valid value 937 }; 938 939 std::ostream& operator<<(std::ostream& aOut, const SamplingFilter& aFilter); 940 941 // clang-format off 942 MOZ_DEFINE_ENUM_CLASS_WITH_BASE(PatternType, int8_t, ( 943 COLOR, 944 SURFACE, 945 LINEAR_GRADIENT, 946 RADIAL_GRADIENT, 947 CONIC_GRADIENT 948 )); 949 // clang-format on 950 951 enum class JoinStyle : int8_t { 952 BEVEL, 953 ROUND, 954 MITER, //!< Mitered if within the miter limit, else, if the backend supports 955 //!< it, the miter is clamped. If the backend does not support miter 956 //!< clamping the behavior is as for MITER_OR_BEVEL. 957 MITER_OR_BEVEL //!< Mitered if within the miter limit, else beveled. 958 }; 959 960 enum class CapStyle : int8_t { BUTT, ROUND, SQUARE }; 961 962 enum class SamplingBounds : int8_t { UNBOUNDED, BOUNDED }; 963 964 // Moz2d version for SVG mask types 965 enum class LuminanceType : int8_t { 966 LUMINANCE, 967 LINEARRGB, 968 }; 969 970 /* Color is stored in non-premultiplied form in sRGB color space */ 971 struct sRGBColor { 972 public: 973 constexpr sRGBColor() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {} 974 constexpr sRGBColor(Float aR, Float aG, Float aB, Float aA) 975 : r(aR), g(aG), b(aB), a(aA) {} 976 constexpr sRGBColor(Float aR, Float aG, Float aB) 977 : r(aR), g(aG), b(aB), a(1.0f) {} 978 979 static constexpr sRGBColor White(float aA) { 980 return sRGBColor(1.f, 1.f, 1.f, aA); 981 } 982 983 static constexpr sRGBColor Black(float aA) { 984 return sRGBColor(0.f, 0.f, 0.f, aA); 985 } 986 987 static constexpr sRGBColor OpaqueWhite() { return White(1.f); } 988 989 static constexpr sRGBColor OpaqueBlack() { return Black(1.f); } 990 991 static constexpr sRGBColor FromU8(uint8_t aR, uint8_t aG, uint8_t aB, 992 uint8_t aA) { 993 return sRGBColor(float(aR) / 255.f, float(aG) / 255.f, float(aB) / 255.f, 994 float(aA) / 255.f); 995 } 996 997 static constexpr sRGBColor FromABGR(uint32_t aColor) { 998 return sRGBColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f), 999 ((aColor >> 8) & 0xff) * (1.0f / 255.0f), 1000 ((aColor >> 16) & 0xff) * (1.0f / 255.0f), 1001 ((aColor >> 24) & 0xff) * (1.0f / 255.0f)); 1002 } 1003 1004 // The "Unusual" prefix is to avoid unintentionally using this function when 1005 // FromABGR(), which is much more common, is needed. 1006 static constexpr sRGBColor UnusualFromARGB(uint32_t aColor) { 1007 return sRGBColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f), 1008 ((aColor >> 8) & 0xff) * (1.0f / 255.0f), 1009 ((aColor >> 0) & 0xff) * (1.0f / 255.0f), 1010 ((aColor >> 24) & 0xff) * (1.0f / 255.0f)); 1011 } 1012 1013 constexpr uint32_t ToABGR() const { 1014 return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 | 1015 uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24; 1016 } 1017 1018 constexpr sRGBColor Premultiplied() const { 1019 return sRGBColor(r * a, g * a, b * a, a); 1020 } 1021 1022 constexpr sRGBColor Unpremultiplied() const { 1023 return a > 0.f ? sRGBColor(r / a, g / a, b / a, a) : *this; 1024 } 1025 1026 // The "Unusual" prefix is to avoid unintentionally using this function when 1027 // ToABGR(), which is much more common, is needed. 1028 uint32_t UnusualToARGB() const { 1029 return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 | 1030 uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24; 1031 } 1032 1033 bool operator==(const sRGBColor& aColor) const { 1034 return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a; 1035 } 1036 1037 bool operator!=(const sRGBColor& aColor) const { return !(*this == aColor); } 1038 1039 Float r, g, b, a; 1040 }; 1041 1042 /* Color is stored in non-premultiplied form in device color space */ 1043 struct DeviceColor { 1044 public: 1045 constexpr DeviceColor() : r(0.0f), g(0.0f), b(0.0f), a(0.0f) {} 1046 constexpr DeviceColor(Float aR, Float aG, Float aB, Float aA) 1047 : r(aR), g(aG), b(aB), a(aA) {} 1048 constexpr DeviceColor(Float aR, Float aG, Float aB) 1049 : r(aR), g(aG), b(aB), a(1.0f) {} 1050 1051 /* The following Mask* variants are helpers used to make it clear when a 1052 * particular color is being used for masking purposes. These masks should 1053 * never be colored managed. */ 1054 static DeviceColor Mask(float aC, float aA) { 1055 return DeviceColor(aC, aC, aC, aA); 1056 } 1057 1058 static DeviceColor MaskWhite(float aA) { return Mask(1.f, aA); } 1059 1060 static DeviceColor MaskBlack(float aA) { return Mask(0.f, aA); } 1061 1062 static DeviceColor MaskOpaqueWhite() { return MaskWhite(1.f); } 1063 1064 static DeviceColor MaskOpaqueBlack() { return MaskBlack(1.f); } 1065 1066 static DeviceColor FromU8(uint8_t aR, uint8_t aG, uint8_t aB, uint8_t aA) { 1067 return DeviceColor(float(aR) / 255.f, float(aG) / 255.f, float(aB) / 255.f, 1068 float(aA) / 255.f); 1069 } 1070 1071 static DeviceColor FromABGR(uint32_t aColor) { 1072 DeviceColor newColor(((aColor >> 0) & 0xff) * (1.0f / 255.0f), 1073 ((aColor >> 8) & 0xff) * (1.0f / 255.0f), 1074 ((aColor >> 16) & 0xff) * (1.0f / 255.0f), 1075 ((aColor >> 24) & 0xff) * (1.0f / 255.0f)); 1076 1077 return newColor; 1078 } 1079 1080 // The "Unusual" prefix is to avoid unintentionally using this function when 1081 // FromABGR(), which is much more common, is needed. 1082 static DeviceColor UnusualFromARGB(uint32_t aColor) { 1083 DeviceColor newColor(((aColor >> 16) & 0xff) * (1.0f / 255.0f), 1084 ((aColor >> 8) & 0xff) * (1.0f / 255.0f), 1085 ((aColor >> 0) & 0xff) * (1.0f / 255.0f), 1086 ((aColor >> 24) & 0xff) * (1.0f / 255.0f)); 1087 1088 return newColor; 1089 } 1090 1091 uint32_t ToABGR() const { 1092 return uint32_t(r * 255.0f) | uint32_t(g * 255.0f) << 8 | 1093 uint32_t(b * 255.0f) << 16 | uint32_t(a * 255.0f) << 24; 1094 } 1095 1096 // The "Unusual" prefix is to avoid unintentionally using this function when 1097 // ToABGR(), which is much more common, is needed. 1098 uint32_t UnusualToARGB() const { 1099 return uint32_t(b * 255.0f) | uint32_t(g * 255.0f) << 8 | 1100 uint32_t(r * 255.0f) << 16 | uint32_t(a * 255.0f) << 24; 1101 } 1102 1103 bool operator==(const DeviceColor& aColor) const { 1104 return r == aColor.r && g == aColor.g && b == aColor.b && a == aColor.a; 1105 } 1106 1107 bool operator!=(const DeviceColor& aColor) const { 1108 return !(*this == aColor); 1109 } 1110 1111 friend std::ostream& operator<<(std::ostream& aOut, 1112 const DeviceColor& aColor); 1113 1114 Float r, g, b, a; 1115 }; 1116 1117 struct GradientStop { 1118 bool operator<(const GradientStop& aOther) const { 1119 return offset < aOther.offset; 1120 } 1121 1122 Float offset; 1123 DeviceColor color; 1124 }; 1125 1126 enum class JobStatus { Complete, Wait, Yield, Error }; 1127 1128 enum class DeviceResetReason { 1129 OK = 0, // No reset. 1130 HUNG, // Windows specific, guilty device reset. 1131 REMOVED, // Windows specific, device removed or driver upgraded. 1132 RESET, // Guilty device reset. 1133 DRIVER_ERROR, // Innocent device reset. 1134 INVALID_CALL, // Windows specific, guilty device reset. 1135 OUT_OF_MEMORY, 1136 FORCED_RESET, // Simulated device reset. 1137 OTHER, // Unrecognized reason for device reset. 1138 NVIDIA_VIDEO, // Linux specific, NVIDIA video memory was reset. 1139 UNKNOWN, // GL specific, unknown if guilty or innocent. 1140 _First = OK, 1141 _Last = UNKNOWN, 1142 }; 1143 1144 enum class DeviceResetDetectPlace { 1145 WR_BEGIN_FRAME = 0, 1146 WR_WAIT_FOR_GPU, 1147 WR_POST_UPDATE, 1148 WR_SYNC_OBJRCT, 1149 WR_SIMULATE, 1150 WIDGET, 1151 CANVAS_TRANSLATOR, 1152 _First = WR_BEGIN_FRAME, 1153 _Last = CANVAS_TRANSLATOR, 1154 }; 1155 1156 enum class ForcedDeviceResetReason { 1157 OPENSHAREDHANDLE = 0, 1158 COMPOSITOR_UPDATED, 1159 }; 1160 1161 } // namespace gfx 1162 } // namespace mozilla 1163 1164 // XXX: temporary 1165 typedef mozilla::gfx::SurfaceFormat gfxImageFormat; 1166 1167 #if defined(XP_WIN) && defined(MOZ_GFX) 1168 # ifdef GFX2D_INTERNAL 1169 # define GFX2D_API __declspec(dllexport) 1170 # else 1171 # define GFX2D_API __declspec(dllimport) 1172 # endif 1173 #else 1174 # define GFX2D_API 1175 #endif 1176 1177 namespace mozilla { 1178 1179 // Side constants for use in various places. 1180 enum Side : uint8_t { eSideTop, eSideRight, eSideBottom, eSideLeft }; 1181 1182 std::ostream& operator<<(std::ostream&, const mozilla::Side&); 1183 1184 constexpr auto AllPhysicalSides() { 1185 return mozilla::MakeInclusiveEnumeratedRange(eSideTop, eSideLeft); 1186 } 1187 1188 enum class SideBits { 1189 eNone = 0, 1190 eTop = 1 << eSideTop, 1191 eRight = 1 << eSideRight, 1192 eBottom = 1 << eSideBottom, 1193 eLeft = 1 << eSideLeft, 1194 eTopBottom = SideBits::eTop | SideBits::eBottom, 1195 eLeftRight = SideBits::eLeft | SideBits::eRight, 1196 eAll = SideBits::eTopBottom | SideBits::eLeftRight 1197 }; 1198 1199 MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(SideBits) 1200 1201 inline constexpr SideBits SideToSideBit(mozilla::Side aSide) { 1202 return SideBits(1 << aSide); 1203 } 1204 1205 enum Corner : uint8_t { 1206 // This order is important! 1207 eCornerTopLeft = 0, 1208 eCornerTopRight = 1, 1209 eCornerBottomRight = 2, 1210 eCornerBottomLeft = 3 1211 }; 1212 1213 // RectCornerRadii::radii depends on this value. It is not being added to 1214 // Corner because we want to lift the responsibility to handle it in the 1215 // switch-case. 1216 constexpr int eCornerCount = 4; 1217 1218 constexpr auto AllPhysicalCorners() { 1219 return mozilla::MakeInclusiveEnumeratedRange(eCornerTopLeft, 1220 eCornerBottomLeft); 1221 } 1222 1223 // Indices into "half corner" arrays (nsStyleCorners e.g.) 1224 enum HalfCorner : uint8_t { 1225 // This order is important! 1226 eCornerTopLeftX = 0, 1227 eCornerTopLeftY = 1, 1228 eCornerTopRightX = 2, 1229 eCornerTopRightY = 3, 1230 eCornerBottomRightX = 4, 1231 eCornerBottomRightY = 5, 1232 eCornerBottomLeftX = 6, 1233 eCornerBottomLeftY = 7 1234 }; 1235 1236 constexpr auto AllPhysicalHalfCorners() { 1237 return mozilla::MakeInclusiveEnumeratedRange(eCornerTopLeftX, 1238 eCornerBottomLeftY); 1239 } 1240 1241 // The result of these conversion functions are exhaustively checked in 1242 // nsFrame.cpp, which also serves as usage examples. 1243 1244 constexpr bool HalfCornerIsX(HalfCorner aHalfCorner) { 1245 return !(aHalfCorner % 2); 1246 } 1247 1248 constexpr Corner HalfToFullCorner(HalfCorner aHalfCorner) { 1249 return Corner(aHalfCorner / 2); 1250 } 1251 1252 constexpr HalfCorner FullToHalfCorner(Corner aCorner, bool aIsVertical) { 1253 return HalfCorner(aCorner * 2 + aIsVertical); 1254 } 1255 1256 constexpr bool SideIsVertical(mozilla::Side aSide) { return aSide % 2; } 1257 1258 // @param aIsSecond when true, return the clockwise second of the two 1259 // corners associated with aSide. For example, with aSide = eSideBottom the 1260 // result is eCornerBottomRight when aIsSecond is false, and 1261 // eCornerBottomLeft when aIsSecond is true. 1262 constexpr Corner SideToFullCorner(mozilla::Side aSide, bool aIsSecond) { 1263 return Corner((aSide + aIsSecond) % 4); 1264 } 1265 1266 // @param aIsSecond see SideToFullCorner. 1267 // @param aIsParallel return the half-corner that is parallel with aSide 1268 // when aIsParallel is true. For example with aSide=eSideTop, aIsSecond=true 1269 // the result is eCornerTopRightX when aIsParallel is true, and 1270 // eCornerTopRightY when aIsParallel is false (because "X" is parallel with 1271 // eSideTop/eSideBottom, similarly "Y" is parallel with 1272 // eSideLeft/eSideRight) 1273 constexpr HalfCorner SideToHalfCorner(mozilla::Side aSide, bool aIsSecond, 1274 bool aIsParallel) { 1275 return HalfCorner(((aSide + aIsSecond) * 2 + (aSide + !aIsParallel) % 2) % 8); 1276 } 1277 1278 } // namespace mozilla 1279 1280 #endif /* MOZILLA_GFX_TYPES_H_ */