diff options
Diffstat (limited to 'gfx/thebes/gfxUtils.h')
-rw-r--r-- | gfx/thebes/gfxUtils.h | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/gfx/thebes/gfxUtils.h b/gfx/thebes/gfxUtils.h new file mode 100644 index 0000000000..1edcf651bd --- /dev/null +++ b/gfx/thebes/gfxUtils.h @@ -0,0 +1,347 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef GFX_UTILS_H +#define GFX_UTILS_H + +#include "gfxMatrix.h" +#include "gfxRect.h" +#include "gfxTypes.h" +#include "ImageTypes.h" +#include "imgIContainer.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/RefPtr.h" +#include "mozilla/UniquePtr.h" +#include "nsColor.h" +#include "nsPrintfCString.h" +#include "nsRegionFwd.h" +#include "mozilla/gfx/Rect.h" +#include "mozilla/CheckedInt.h" +#include "mozilla/webrender/WebRenderTypes.h" + +class gfxASurface; +class gfxDrawable; +struct gfxQuad; +class nsIInputStream; +class nsIGfxInfo; + +namespace mozilla { +namespace dom { +class Element; +} +namespace layers { +class WebRenderBridgeChild; +class GlyphArray; +struct PlanarYCbCrData; +class WebRenderCommand; +} // namespace layers +namespace image { +class ImageRegion; +} // namespace image +namespace wr { +class DisplayListBuilder; +} // namespace wr +} // namespace mozilla + +enum class ImageType { + BMP, + ICO, + JPEG, + PNG, +}; + +class gfxUtils { + public: + typedef mozilla::gfx::DataSourceSurface DataSourceSurface; + typedef mozilla::gfx::DrawTarget DrawTarget; + typedef mozilla::gfx::IntPoint IntPoint; + typedef mozilla::gfx::Matrix Matrix; + typedef mozilla::gfx::SourceSurface SourceSurface; + typedef mozilla::gfx::SurfaceFormat SurfaceFormat; + typedef mozilla::image::ImageRegion ImageRegion; + + /* + * Premultiply or Unpremultiply aSourceSurface, writing the result + * to aDestSurface or back into aSourceSurface if aDestSurface is null. + * + * If aDestSurface is given, it must have identical format, dimensions, and + * stride as the source. + * + * If the source is not SurfaceFormat::A8R8G8B8_UINT32, no operation is + * performed. If aDestSurface is given, the data is copied over. + */ + static bool PremultiplyDataSurface(DataSourceSurface* srcSurf, + DataSourceSurface* destSurf); + static bool UnpremultiplyDataSurface(DataSourceSurface* srcSurf, + DataSourceSurface* destSurf); + + static already_AddRefed<DataSourceSurface> CreatePremultipliedDataSurface( + DataSourceSurface* srcSurf); + static already_AddRefed<DataSourceSurface> CreateUnpremultipliedDataSurface( + DataSourceSurface* srcSurf); + + static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength); + + /** + * Draw something drawable while working around limitations like bad support + * for EXTEND_PAD, lack of source-clipping, or cairo / pixman bugs with + * extreme user-space-to-image-space transforms. + * + * The input parameters here usually come from the output of our image + * snapping algorithm in nsLayoutUtils.cpp. + * This method is split from nsLayoutUtils::DrawPixelSnapped to allow for + * adjusting the parameters. For example, certain images with transparent + * margins only have a drawable subimage. For those images, imgFrame::Draw + * will tweak the rects and transforms that it gets from the pixel snapping + * algorithm before passing them on to this method. + */ + static void DrawPixelSnapped(gfxContext* aContext, gfxDrawable* aDrawable, + const gfxSize& aImageSize, + const ImageRegion& aRegion, + const mozilla::gfx::SurfaceFormat aFormat, + mozilla::gfx::SamplingFilter aSamplingFilter, + uint32_t aImageFlags = imgIContainer::FLAG_NONE, + gfxFloat aOpacity = 1.0, + bool aUseOptimalFillOp = true); + + /** + * Clip aContext to the region aRegion. + */ + static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion); + + /** + * Clip aTarget to the region aRegion. + */ + static void ClipToRegion(mozilla::gfx::DrawTarget* aTarget, + const nsIntRegion& aRegion); + + /* + * Convert image format to depth value + */ + static int ImageFormatToDepth(gfxImageFormat aFormat); + + /** + * Return the transform matrix that maps aFrom to the rectangle defined by + * aToTopLeft/aToTopRight/aToBottomRight. aFrom must be + * nonempty and the destination rectangle must be axis-aligned. + */ + static gfxMatrix TransformRectToRect(const gfxRect& aFrom, + const gfxPoint& aToTopLeft, + const gfxPoint& aToTopRight, + const gfxPoint& aToBottomRight); + + static Matrix TransformRectToRect(const gfxRect& aFrom, + const IntPoint& aToTopLeft, + const IntPoint& aToTopRight, + const IntPoint& aToBottomRight); + + /** + * If aIn can be represented exactly using an gfx::IntRect (i.e. + * integer-aligned edges and coordinates in the int32_t range) then we + * set aOut to that rectangle, otherwise return failure. + */ + static bool GfxRectToIntRect(const gfxRect& aIn, mozilla::gfx::IntRect* aOut); + + /* Conditions this border to Cairo's max coordinate space. + * The caller can check IsEmpty() after Condition() -- if it's TRUE, + * the caller can possibly avoid doing any extra rendering. + */ + static void ConditionRect(gfxRect& aRect); + + /* + * Transform this rectangle with aMatrix, resulting in a gfxQuad. + */ + static gfxQuad TransformToQuad(const gfxRect& aRect, + const mozilla::gfx::Matrix4x4& aMatrix); + + /** + * Return the smallest power of kScaleResolution (2) greater than or equal to + * aVal. If aRoundDown is specified, the power of 2 will rather be less than + * or equal to aVal. + */ + static float ClampToScaleFactor(float aVal, bool aRoundDown = false); + + /** + * Clears surface to aColor (which defaults to transparent black). + */ + static void ClearThebesSurface(gfxASurface* aSurface); + + static const float* YuvToRgbMatrix4x3RowMajor( + mozilla::gfx::YUVColorSpace aYUVColorSpace); + static const float* YuvToRgbMatrix3x3ColumnMajor( + mozilla::gfx::YUVColorSpace aYUVColorSpace); + static const float* YuvToRgbMatrix4x4ColumnMajor( + mozilla::gfx::YUVColorSpace aYUVColorSpace); + + /** + * Creates a copy of aSurface, but having the SurfaceFormat aFormat. + * + * This function always creates a new surface. Do not call it if aSurface's + * format is the same as aFormat. Such a non-conversion would just be an + * unnecessary and wasteful copy (this function asserts to prevent that). + * + * This function is intended to be called by code that needs to access the + * pixel data of the surface, but doesn't want to have lots of branches + * to handle different pixel data formats (code which would become out of + * date if and when new formats are added). Callers can use this function + * to copy the surface to a specified format so that they only have to + * handle pixel data in that one format. + * + * WARNING: There are format conversions that will not be supported by this + * function. It very much depends on what the Moz2D backends support. If + * the temporary B8G8R8A8 DrawTarget that this function creates has a + * backend that supports DrawSurface() calls passing a surface with + * aSurface's format it will work. Otherwise it will not. + * + * *** IMPORTANT PERF NOTE *** + * + * This function exists partly because format conversion is fraught with + * non-obvious performance hazards, so we don't want Moz2D consumers to be + * doing their own format conversion. Do not try to do so, or at least read + * the comments in this functions implemtation. That said, the copy that + * this function carries out has a cost and, although this function tries + * to avoid perf hazards such as expensive uploads to/readbacks from the + * GPU, it can't guarantee that it always successfully does so. Perf + * critical code that can directly handle the common formats that it + * encounters in a way that is cheaper than a copy-with-format-conversion + * should consider doing so, and only use this function as a fallback to + * handle other formats. + * + * XXXjwatt it would be nice if SourceSurface::GetDataSurface took a + * SurfaceFormat argument (with a default argument meaning "use the + * existing surface's format") and returned a DataSourceSurface in that + * format. (There would then be an issue of callers maybe failing to + * realize format conversion may involve expensive copying/uploading/ + * readback.) + */ + static already_AddRefed<DataSourceSurface> + CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface, + SurfaceFormat aFormat); + + /** + * Return a color that can be used to identify a frame with a given frame + * number. The colors will cycle after sNumFrameColors. You can query colors + * 0 .. sNumFrameColors-1 to get all the colors back. + */ + static const mozilla::gfx::DeviceColor& GetColorForFrameNumber( + uint64_t aFrameNumber); + static const uint32_t sNumFrameColors; + + enum BinaryOrData { eBinaryEncode, eDataURIEncode }; + + /** + * Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder. + * If both aFile and aString are null, the encoded data is copied to the + * clipboard. + * + * @param aImageType The image type that the surface is to be encoded to. + * Used to create an appropriate imgIEncoder instance to do the encoding. + * + * @param aOutputOptions Passed directly to imgIEncoder::InitFromData as + * the value of the |outputOptions| parameter. Callers are responsible + * for making sure that this is a sane value for the passed MIME-type + * (i.e. for the type of encoder that will be created). + * + * @aBinaryOrData Flag used to determine if the surface is simply encoded + * to the requested binary image format, or if the binary image is + * further converted to base-64 and written out as a 'data:' URI. + * + * @aFile If specified, the encoded data is written out to aFile. + * + * @aString If specified, the encoded data is written out to aString. + * + * TODO: Copying to the clipboard as a binary file is not currently + * supported. + */ + static nsresult EncodeSourceSurface(SourceSurface* aSurface, + const ImageType aImageType, + const nsAString& aOutputOptions, + BinaryOrData aBinaryOrData, FILE* aFile, + nsACString* aString = nullptr); + + /** + * Write as a PNG file to the path aFile. + */ + static void WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile); + static void WriteAsPNG(SourceSurface* aSurface, const char* aFile); + static void WriteAsPNG(DrawTarget* aDT, const nsAString& aFile); + static void WriteAsPNG(DrawTarget* aDT, const char* aFile); + + /** + * Dump as a PNG encoded Data URL to a FILE stream (using stdout by + * default). + * + * Rather than giving aFile a default argument we have separate functions + * to make them easier to use from a debugger. + */ + static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile); + static inline void DumpAsDataURI(SourceSurface* aSourceSurface) { + DumpAsDataURI(aSourceSurface, stdout); + } + static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile); + static inline void DumpAsDataURI(DrawTarget* aDT) { + DumpAsDataURI(aDT, stdout); + } + static nsCString GetAsDataURI(SourceSurface* aSourceSurface); + static nsCString GetAsDataURI(DrawTarget* aDT); + static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface); + + static mozilla::UniquePtr<uint8_t[]> GetImageBuffer( + DataSourceSurface* aSurface, bool aIsAlphaPremultiplied, + int32_t* outFormat); + + static nsresult GetInputStream(DataSourceSurface* aSurface, + bool aIsAlphaPremultiplied, + const char* aMimeType, + const nsAString& aEncoderOptions, + nsIInputStream** outStream); + + static void RemoveShaderCacheFromDiskIfNecessary(); + + /** + * Copy to the clipboard as a PNG encoded Data URL. + */ + static void CopyAsDataURI(SourceSurface* aSourceSurface); + static void CopyAsDataURI(DrawTarget* aDT); + + static bool DumpDisplayList(); + + static FILE* sDumpPaintFile; +}; + +namespace mozilla { + +struct StyleRGBA; + +namespace gfx { + +/** + * If the CMS mode is eCMSMode_All, these functions transform the passed + * color to a device color using the transform returened by gfxPlatform:: + * GetCMSRGBTransform(). If the CMS mode is some other value, the color is + * returned unchanged (other than a type change to Moz2D Color, if + * applicable). + */ +DeviceColor ToDeviceColor(const sRGBColor& aColor); +DeviceColor ToDeviceColor(const StyleRGBA& aColor); +DeviceColor ToDeviceColor(nscolor aColor); + +/** + * Performs a checked multiply of the given width, height, and bytes-per-pixel + * values. + */ +static inline CheckedInt<uint32_t> SafeBytesForBitmap(uint32_t aWidth, + uint32_t aHeight, + unsigned aBytesPerPixel) { + MOZ_ASSERT(aBytesPerPixel > 0); + CheckedInt<uint32_t> width = uint32_t(aWidth); + CheckedInt<uint32_t> height = uint32_t(aHeight); + return width * height * aBytesPerPixel; +} + +} // namespace gfx +} // namespace mozilla + +#endif |