gfxUtils.h (24544B)
1 /* -*- Mode: C++; tab-width: 20; 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/. */ 5 6 #ifndef GFX_UTILS_H 7 #define GFX_UTILS_H 8 9 #include "gfxMatrix.h" 10 #include "gfxRect.h" 11 #include "gfxTypes.h" 12 #include "ImageTypes.h" 13 #include "imgIContainer.h" 14 #include "mozilla/gfx/2D.h" 15 #include "mozilla/Maybe.h" 16 #include "mozilla/UniquePtr.h" 17 #include "nsColor.h" 18 #include "nsContentUtils.h" 19 #include "nsPrintfCString.h" 20 #include "nsRegionFwd.h" 21 #include "mozilla/gfx/Rect.h" 22 #include "mozilla/CheckedInt.h" 23 #include "mozilla/webrender/WebRenderTypes.h" 24 #include "qcms.h" 25 26 class gfxASurface; 27 class gfxDrawable; 28 class gfxTextRun; 29 struct gfxQuad; 30 class nsICookieJarSettings; 31 class nsIInputStream; 32 class nsIGfxInfo; 33 34 namespace mozilla { 35 namespace dom { 36 class Element; 37 } // namespace dom 38 namespace layers { 39 class WebRenderBridgeChild; 40 class GlyphArray; 41 struct PlanarYCbCrData; 42 class WebRenderCommand; 43 } // namespace layers 44 namespace image { 45 class ImageRegion; 46 } // namespace image 47 namespace wr { 48 class DisplayListBuilder; 49 } // namespace wr 50 } // namespace mozilla 51 52 enum class ImageType { 53 BMP, 54 ICO, 55 JPEG, 56 PNG, 57 }; 58 59 class gfxUtils { 60 public: 61 typedef mozilla::gfx::DataSourceSurface DataSourceSurface; 62 typedef mozilla::gfx::DrawTarget DrawTarget; 63 typedef mozilla::gfx::IntPoint IntPoint; 64 typedef mozilla::gfx::Matrix Matrix; 65 typedef mozilla::gfx::Matrix4x4 Matrix4x4; 66 typedef mozilla::gfx::SourceSurface SourceSurface; 67 typedef mozilla::gfx::SurfaceFormat SurfaceFormat; 68 typedef mozilla::image::ImageRegion ImageRegion; 69 70 /* 71 * Premultiply or Unpremultiply aSourceSurface, writing the result 72 * to aDestSurface or back into aSourceSurface if aDestSurface is null. 73 * 74 * If aDestSurface is given, it must have identical format, dimensions, and 75 * stride as the source. 76 * 77 * If the source is not SurfaceFormat::A8R8G8B8_UINT32, no operation is 78 * performed. If aDestSurface is given, the data is copied over. 79 */ 80 static bool PremultiplyDataSurface(DataSourceSurface* srcSurf, 81 DataSourceSurface* destSurf); 82 static bool UnpremultiplyDataSurface(DataSourceSurface* srcSurf, 83 DataSourceSurface* destSurf); 84 85 static already_AddRefed<DataSourceSurface> CreatePremultipliedDataSurface( 86 DataSourceSurface* srcSurf); 87 static already_AddRefed<DataSourceSurface> CreateUnpremultipliedDataSurface( 88 DataSourceSurface* srcSurf); 89 90 static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength); 91 92 /** 93 * Draw something drawable while working around limitations like bad support 94 * for EXTEND_PAD, lack of source-clipping, or cairo / pixman bugs with 95 * extreme user-space-to-image-space transforms. 96 * 97 * The input parameters here usually come from the output of our image 98 * snapping algorithm in nsLayoutUtils.cpp. 99 * This method is split from nsLayoutUtils::DrawPixelSnapped to allow for 100 * adjusting the parameters. For example, certain images with transparent 101 * margins only have a drawable subimage. For those images, imgFrame::Draw 102 * will tweak the rects and transforms that it gets from the pixel snapping 103 * algorithm before passing them on to this method. 104 */ 105 static void DrawPixelSnapped(gfxContext* aContext, gfxDrawable* aDrawable, 106 const gfxSize& aImageSize, 107 const ImageRegion& aRegion, 108 const mozilla::gfx::SurfaceFormat aFormat, 109 mozilla::gfx::SamplingFilter aSamplingFilter, 110 uint32_t aImageFlags = imgIContainer::FLAG_NONE, 111 gfxFloat aOpacity = 1.0); 112 113 /** 114 * Clip aContext to the region aRegion. 115 */ 116 static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion); 117 118 /** 119 * Clip aTarget to the region aRegion. 120 */ 121 static void ClipToRegion(mozilla::gfx::DrawTarget* aTarget, 122 const nsIntRegion& aRegion); 123 124 /* 125 * Convert image format to depth value 126 */ 127 static int ImageFormatToDepth(gfxImageFormat aFormat); 128 129 /** 130 * Return the transform matrix that maps aFrom to the rectangle defined by 131 * aToTopLeft/aToTopRight/aToBottomRight. aFrom must be 132 * nonempty and the destination rectangle must be axis-aligned. 133 */ 134 static gfxMatrix TransformRectToRect(const gfxRect& aFrom, 135 const gfxPoint& aToTopLeft, 136 const gfxPoint& aToTopRight, 137 const gfxPoint& aToBottomRight); 138 139 static Matrix TransformRectToRect(const gfxRect& aFrom, 140 const IntPoint& aToTopLeft, 141 const IntPoint& aToTopRight, 142 const IntPoint& aToBottomRight); 143 144 /** 145 * If aIn can be represented exactly using an gfx::IntRect (i.e. 146 * integer-aligned edges and coordinates in the int32_t range) then we 147 * set aOut to that rectangle, otherwise return failure. 148 */ 149 static bool GfxRectToIntRect(const gfxRect& aIn, mozilla::gfx::IntRect* aOut); 150 151 /* Conditions this border to Cairo's max coordinate space. 152 * The caller can check IsEmpty() after Condition() -- if it's TRUE, 153 * the caller can possibly avoid doing any extra rendering. 154 */ 155 static void ConditionRect(gfxRect& aRect); 156 157 /* 158 * Transform this rectangle with aMatrix, resulting in a gfxQuad. 159 */ 160 static gfxQuad TransformToQuad(const gfxRect& aRect, 161 const mozilla::gfx::Matrix4x4& aMatrix); 162 163 /** 164 * Return the smallest power of kScaleResolution (2) greater than or equal to 165 * aVal. If aRoundDown is specified, the power of 2 will rather be less than 166 * or equal to aVal. 167 */ 168 static float ClampToScaleFactor(float aVal, bool aRoundDown = false); 169 170 /** 171 * We can snap layer transforms for two reasons: 172 * 1) To avoid unnecessary resampling when a transform is a translation 173 * by a non-integer number of pixels. 174 * Snapping the translation to an integer number of pixels avoids 175 * blurring the layer and can be faster to composite. 176 * 2) When a layer is used to render a rectangular object, we need to 177 * emulate the rendering of rectangular inactive content and snap the 178 * edges of the rectangle to pixel boundaries. This is both to ensure 179 * layer rendering is consistent with inactive content rendering, and to 180 * avoid seams. 181 * This function implements type 1 snapping. If aTransform is a 2D 182 * translation, and this layer's layer manager has enabled snapping 183 * (which is the default), return aTransform with the translation snapped 184 * to nearest pixels. Otherwise just return aTransform. Call this when the 185 * layer does not correspond to a single rectangular content object. 186 * This function does not try to snap if aTransform has a scale, because in 187 * that case resampling is inevitable and there's no point in trying to 188 * avoid it. In fact snapping can cause problems because pixel edges in the 189 * layer's content can be rendered unpredictably (jiggling) as the scale 190 * interacts with the snapping of the translation, especially with animated 191 * transforms. 192 * @param aResidualTransform a transform to apply before the result transform 193 * in order to get the results to completely match aTransform. 194 */ 195 static Matrix4x4 SnapTransformTranslation(const Matrix4x4& aTransform, 196 Matrix* aResidualTransform); 197 static Matrix SnapTransformTranslation(const Matrix& aTransform, 198 Matrix* aResidualTransform); 199 static Matrix4x4 SnapTransformTranslation3D(const Matrix4x4& aTransform, 200 Matrix* aResidualTransform); 201 /** 202 * See comment for SnapTransformTranslation. 203 * This function implements type 2 snapping. If aTransform is a translation 204 * and/or scale, transform aSnapRect by aTransform, snap to pixel boundaries, 205 * and return the transform that maps aSnapRect to that rect. Otherwise 206 * just return aTransform. 207 * @param aSnapRect a rectangle whose edges should be snapped to pixel 208 * boundaries in the destination surface. 209 * @param aResidualTransform a transform to apply before the result transform 210 * in order to get the results to completely match aTransform. 211 */ 212 static Matrix4x4 SnapTransform(const Matrix4x4& aTransform, 213 const gfxRect& aSnapRect, 214 Matrix* aResidualTransform); 215 static Matrix SnapTransform(const Matrix& aTransform, 216 const gfxRect& aSnapRect, 217 Matrix* aResidualTransform); 218 219 /** 220 * Clears surface to aColor (which defaults to transparent black). 221 */ 222 static void ClearThebesSurface(gfxASurface* aSurface); 223 224 static const float* YuvToRgbMatrix4x3RowMajor( 225 mozilla::gfx::YUVColorSpace aYUVColorSpace); 226 static const float* YuvToRgbMatrix3x3ColumnMajor( 227 mozilla::gfx::YUVColorSpace aYUVColorSpace); 228 static const float* YuvToRgbMatrix4x4ColumnMajor( 229 mozilla::gfx::YUVColorSpace aYUVColorSpace); 230 231 static mozilla::Maybe<mozilla::gfx::YUVColorSpace> CicpToColorSpace( 232 const mozilla::gfx::CICP::MatrixCoefficients, 233 const mozilla::gfx::CICP::ColourPrimaries, 234 mozilla::LazyLogModule& aLogger); 235 236 static mozilla::Maybe<mozilla::gfx::ColorSpace2> CicpToColorPrimaries( 237 const mozilla::gfx::CICP::ColourPrimaries, 238 mozilla::LazyLogModule& aLogger); 239 240 static mozilla::Maybe<mozilla::gfx::TransferFunction> CicpToTransferFunction( 241 const mozilla::gfx::CICP::TransferCharacteristics); 242 243 /** 244 * Creates a copy of aSurface, but having the SurfaceFormat aFormat. 245 * 246 * This function always creates a new surface. Do not call it if aSurface's 247 * format is the same as aFormat. Such a non-conversion would just be an 248 * unnecessary and wasteful copy (this function asserts to prevent that). 249 * 250 * This function is intended to be called by code that needs to access the 251 * pixel data of the surface, but doesn't want to have lots of branches 252 * to handle different pixel data formats (code which would become out of 253 * date if and when new formats are added). Callers can use this function 254 * to copy the surface to a specified format so that they only have to 255 * handle pixel data in that one format. 256 * 257 * WARNING: There are format conversions that will not be supported by this 258 * function. It very much depends on what the Moz2D backends support. If 259 * the temporary B8G8R8A8 DrawTarget that this function creates has a 260 * backend that supports DrawSurface() calls passing a surface with 261 * aSurface's format it will work. Otherwise it will not. 262 * 263 * *** IMPORTANT PERF NOTE *** 264 * 265 * This function exists partly because format conversion is fraught with 266 * non-obvious performance hazards, so we don't want Moz2D consumers to be 267 * doing their own format conversion. Do not try to do so, or at least read 268 * the comments in this functions implemtation. That said, the copy that 269 * this function carries out has a cost and, although this function tries 270 * to avoid perf hazards such as expensive uploads to/readbacks from the 271 * GPU, it can't guarantee that it always successfully does so. Perf 272 * critical code that can directly handle the common formats that it 273 * encounters in a way that is cheaper than a copy-with-format-conversion 274 * should consider doing so, and only use this function as a fallback to 275 * handle other formats. 276 * 277 * XXXjwatt it would be nice if SourceSurface::GetDataSurface took a 278 * SurfaceFormat argument (with a default argument meaning "use the 279 * existing surface's format") and returned a DataSourceSurface in that 280 * format. (There would then be an issue of callers maybe failing to 281 * realize format conversion may involve expensive copying/uploading/ 282 * readback.) 283 */ 284 static already_AddRefed<DataSourceSurface> 285 CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface, 286 SurfaceFormat aFormat); 287 288 // Scales a SourceSurface to the new requested size. 289 // 290 // Asserts when the requested size is equal to the current size of the 291 // surface. 292 static already_AddRefed<SourceSurface> ScaleSourceSurface( 293 SourceSurface& aSurface, const mozilla::gfx::IntSize& aTargetSize); 294 295 /** 296 * Return a color that can be used to identify a frame with a given frame 297 * number. The colors will cycle after sNumFrameColors. You can query colors 298 * 0 .. sNumFrameColors-1 to get all the colors back. 299 */ 300 static const mozilla::gfx::DeviceColor& GetColorForFrameNumber( 301 uint64_t aFrameNumber); 302 static const uint32_t sNumFrameColors; 303 304 enum BinaryOrData { eBinaryEncode, eDataURIEncode }; 305 306 /** 307 * Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder. 308 * If both aFile and aString are null, the encoded data is copied to the 309 * clipboard. 310 * 311 * @param aImageType The image type that the surface is to be encoded to. 312 * Used to create an appropriate imgIEncoder instance to do the encoding. 313 * 314 * @param aOutputOptions Passed directly to imgIEncoder::InitFromData as 315 * the value of the |outputOptions| parameter. Callers are responsible 316 * for making sure that this is a reasonable value for the passed MIME-type 317 * (i.e. for the type of encoder that will be created). 318 * 319 * @aBinaryOrData Flag used to determine if the surface is simply encoded 320 * to the requested binary image format, or if the binary image is 321 * further converted to base-64 and written out as a 'data:' URI. 322 * 323 * @aFile If specified, the encoded data is written out to aFile. 324 * 325 * @aString If specified, the encoded data is written out to aString. 326 * 327 * TODO: Copying to the clipboard as a binary file is not currently 328 * supported. 329 */ 330 static nsresult EncodeSourceSurface(SourceSurface* aSurface, 331 const ImageType aImageType, 332 const nsAString& aOutputOptions, 333 BinaryOrData aBinaryOrData, FILE* aFile, 334 nsACString* aString = nullptr); 335 336 /** 337 * Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder 338 * and returns the result as an nsIInputStream. 339 * 340 * @param aSurface The source surface to encode 341 * 342 * @param aImageType The image type that the surface is to be encoded to. 343 * Used to create an appropriate imgIEncoder instance to do the encoding. 344 * 345 * @param aOutputOptions Passed directly to imgIEncoder::InitFromData as 346 * the value of the |outputOptions| parameter. Callers are responsible 347 * for making sure that this is a reasonable value for the passed MIME-type 348 * (i.e. for the type of encoder that will be created). 349 * 350 * @param aOutStream pointer to the output stream 351 * 352 */ 353 static nsresult EncodeSourceSurfaceAsStream(SourceSurface* aSurface, 354 const ImageType aImageType, 355 const nsAString& aOutputOptions, 356 nsIInputStream** aOutStream); 357 358 /** 359 * Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder 360 * and returns the result as a vector of bytes 361 * 362 * @param aImageType The image type that the surface is to be encoded to. 363 * Used to create an appropriate imgIEncoder instance to do the encoding. 364 * 365 * @param aOutputOptions Passed directly to imgIEncoder::InitFromData as 366 * the value of the |outputOptions| parameter. Callers are responsible 367 * for making sure that this is a reasonable value for the passed MIME-type 368 * (i.e. for the type of encoder that will be created). 369 * 370 */ 371 static mozilla::Maybe<nsTArray<uint8_t>> EncodeSourceSurfaceAsBytes( 372 SourceSurface* aSurface, const ImageType aImageType, 373 const nsAString& aOutputOptions); 374 375 /** 376 * Write as a PNG file to the path aFile. 377 */ 378 static void WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile); 379 static void WriteAsPNG(SourceSurface* aSurface, const char* aFile); 380 static void WriteAsPNG(DrawTarget* aDT, const nsAString& aFile); 381 static void WriteAsPNG(DrawTarget* aDT, const char* aFile); 382 383 /** 384 * Dump as a PNG encoded Data URL to a FILE stream (using stdout by 385 * default). 386 * 387 * Rather than giving aFile a default argument we have separate functions 388 * to make them easier to use from a debugger. 389 */ 390 static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile); 391 static inline void DumpAsDataURI(SourceSurface* aSourceSurface) { 392 DumpAsDataURI(aSourceSurface, stdout); 393 } 394 static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile); 395 static inline void DumpAsDataURI(DrawTarget* aDT) { 396 DumpAsDataURI(aDT, stdout); 397 } 398 static nsCString GetAsDataURI(SourceSurface* aSourceSurface); 399 static nsCString GetAsDataURI(DrawTarget* aDT); 400 static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface); 401 402 static mozilla::UniquePtr<uint8_t[]> GetImageBuffer( 403 DataSourceSurface* aSurface, bool aIsAlphaPremultiplied, 404 int32_t* outFormat); 405 406 static mozilla::UniquePtr<uint8_t[]> GetImageBufferWithRandomNoise( 407 DataSourceSurface* aSurface, bool aIsAlphaPremultiplied, 408 nsICookieJarSettings* aCookieJarSettings, nsIPrincipal* aPrincipal, 409 int32_t* outFormat); 410 411 static nsresult GetInputStream(DataSourceSurface* aSurface, 412 bool aIsAlphaPremultiplied, 413 const char* aMimeType, 414 const nsAString& aEncoderOptions, 415 nsIInputStream** outStream); 416 417 static nsresult GetInputStreamWithRandomNoise( 418 DataSourceSurface* aSurface, bool aIsAlphaPremultiplied, 419 const char* aMimeType, const nsAString& aEncoderOptions, 420 nsICookieJarSettings* aCookieJarSettings, nsIPrincipal* aPrincipal, 421 nsIInputStream** outStream); 422 423 static void RemoveShaderCacheFromDiskIfNecessary(); 424 425 /** 426 * Copy to the clipboard as a PNG encoded Data URL. 427 */ 428 static void CopyAsDataURI(SourceSurface* aSourceSurface); 429 static void CopyAsDataURI(DrawTarget* aDT); 430 431 static bool DumpDisplayList(); 432 433 static FILE* sDumpPaintFile; 434 }; 435 436 namespace mozilla { 437 438 // Container for either a single element of type T, or an nsTArray<T>. 439 // Provides a minimal subset of nsTArray's API, just enough to support use 440 // by ContextState for the clipsAndTransforms list, and by gfxTextRun for 441 // its mGlyphRuns. 442 // Using this instead of a simple nsTArray avoids an extra allocation in the 443 // common case where no more than one element is ever added to the list. 444 // Unlike an AutoTArray<..., 1>, this class is memmovable and therefore can 445 // be used in ContextState without breaking its movability. 446 template <typename T> 447 class ElementOrArray { 448 union { 449 T mElement; 450 nsTArray<T> mArray; 451 }; 452 enum class Tag : uint8_t { 453 Element, 454 Array, 455 } mTag; 456 457 // gfxTextRun::SortGlyphRuns and SanitizeGlyphRuns directly access the array. 458 friend class ::gfxTextRun; 459 nsTArray<T>& Array() { 460 MOZ_DIAGNOSTIC_ASSERT(mTag == Tag::Array); 461 return mArray; 462 } 463 464 public: 465 // Construct as an empty array. 466 ElementOrArray() : mTag(Tag::Array) { new (&mArray) nsTArray<T>(); } 467 468 // For now, don't support copy/move. 469 ElementOrArray(const ElementOrArray&) = delete; 470 ElementOrArray(ElementOrArray&&) = delete; 471 472 ElementOrArray& operator=(const ElementOrArray&) = delete; 473 ElementOrArray& operator=(ElementOrArray&&) = delete; 474 475 // Destroy the appropriate variant. 476 ~ElementOrArray() { 477 switch (mTag) { 478 case Tag::Element: 479 mElement.~T(); 480 break; 481 case Tag::Array: 482 mArray.~nsTArray(); 483 break; 484 } 485 } 486 487 size_t Length() const { return mTag == Tag::Element ? 1 : mArray.Length(); } 488 489 T* AppendElement(const T& aElement) { 490 switch (mTag) { 491 case Tag::Element: { 492 // Move the existing element into an array, then append the new one. 493 T temp = std::move(mElement); 494 mElement.~T(); 495 mTag = Tag::Array; 496 new (&mArray) nsTArray<T>(); 497 mArray.AppendElement(std::move(temp)); 498 return mArray.AppendElement(aElement); 499 } 500 case Tag::Array: { 501 // If currently empty, just store the element directly. 502 if (mArray.IsEmpty()) { 503 mArray.~nsTArray(); 504 mTag = Tag::Element; 505 new (&mElement) T(aElement); 506 return &mElement; 507 } 508 // Otherwise, append it to the array. 509 return mArray.AppendElement(aElement); 510 } 511 default: 512 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("invalid tag"); 513 } 514 } 515 516 const T& LastElement() const { 517 return mTag == Tag::Element ? mElement : mArray.LastElement(); 518 } 519 520 T& LastElement() { 521 return mTag == Tag::Element ? mElement : mArray.LastElement(); 522 } 523 524 bool IsEmpty() const { 525 return mTag == Tag::Element ? false : mArray.IsEmpty(); 526 } 527 528 void TruncateLength(uint32_t aLength = 0) { 529 MOZ_DIAGNOSTIC_ASSERT(aLength <= Length()); 530 switch (mTag) { 531 case Tag::Element: 532 if (aLength == 0) { 533 // Destroy the single element, and convert to an empty array. 534 mElement.~T(); 535 mTag = Tag::Array; 536 new (&mArray) nsTArray<T>(); 537 } 538 break; 539 case Tag::Array: 540 mArray.TruncateLength(aLength); 541 break; 542 } 543 } 544 545 void Clear() { 546 switch (mTag) { 547 case Tag::Element: 548 mElement.~T(); 549 mTag = Tag::Array; 550 new (&mArray) nsTArray<T>(); 551 break; 552 case Tag::Array: 553 mArray.Clear(); 554 break; 555 } 556 } 557 558 // Convert from Array to Element storage. Only to be used when the current 559 // state is a single-element array! 560 void ConvertToElement() { 561 MOZ_DIAGNOSTIC_ASSERT(mTag == Tag::Array && mArray.Length() == 1); 562 T temp = std::move(mArray[0]); 563 mArray.~nsTArray(); 564 mTag = Tag::Element; 565 new (&mElement) T(std::move(temp)); 566 } 567 568 const T& operator[](uint32_t aIndex) const { 569 MOZ_DIAGNOSTIC_ASSERT(aIndex < Length()); 570 return mTag == Tag::Element ? mElement : mArray[aIndex]; 571 } 572 T& operator[](uint32_t aIndex) { 573 MOZ_DIAGNOSTIC_ASSERT(aIndex < Length()); 574 return mTag == Tag::Element ? mElement : mArray[aIndex]; 575 } 576 577 // Simple iterators to support range-for loops. 578 const T* begin() const { 579 return mTag == Tag::Array ? mArray.IsEmpty() ? nullptr : &*mArray.begin() 580 : &mElement; 581 } 582 T* begin() { 583 return mTag == Tag::Array ? mArray.IsEmpty() ? nullptr : &*mArray.begin() 584 : &mElement; 585 } 586 587 const T* end() const { 588 return mTag == Tag::Array ? begin() + mArray.Length() : &mElement + 1; 589 } 590 T* end() { 591 return mTag == Tag::Array ? begin() + mArray.Length() : &mElement + 1; 592 } 593 594 size_t ShallowSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) { 595 return mTag == Tag::Array ? mArray.ShallowSizeOfExcludingThis(aMallocSizeOf) 596 : 0; 597 } 598 }; 599 600 struct StyleAbsoluteColor; 601 602 namespace gfx { 603 604 /** 605 * If the CMS mode is CMSMode::All, these functions transform the passed 606 * color to a device color using the transform returned by 607 * gfxPlatform::GetCMSRGBTransform(). If the CMS mode is some other value, the 608 * color is returned unchanged (other than a type change to Moz2D Color, if 609 * applicable). 610 */ 611 DeviceColor ToDeviceColor(const sRGBColor&); 612 DeviceColor ToDeviceColor(const StyleAbsoluteColor&); 613 DeviceColor ToDeviceColor(nscolor); 614 615 sRGBColor ToSRGBColor(const StyleAbsoluteColor&); 616 617 /** 618 * Performs a checked multiply of the given width, height, and bytes-per-pixel 619 * values. 620 */ 621 static inline CheckedInt<uint32_t> SafeBytesForBitmap(uint32_t aWidth, 622 uint32_t aHeight, 623 unsigned aBytesPerPixel) { 624 MOZ_ASSERT(aBytesPerPixel > 0); 625 CheckedInt<uint32_t> width = uint32_t(aWidth); 626 CheckedInt<uint32_t> height = uint32_t(aHeight); 627 return width * height * aBytesPerPixel; 628 } 629 630 } // namespace gfx 631 } // namespace mozilla 632 633 #endif