Line data Source code
1 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
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 "gfxTypes.h"
10 : #include "ImageTypes.h"
11 : #include "imgIContainer.h"
12 : #include "mozilla/gfx/2D.h"
13 : #include "mozilla/RefPtr.h"
14 : #include "mozilla/UniquePtr.h"
15 : #include "nsColor.h"
16 : #include "nsPrintfCString.h"
17 : #include "nsRegionFwd.h"
18 : #include "mozilla/gfx/Rect.h"
19 : #include "mozilla/CheckedInt.h"
20 : #include "mozilla/webrender/WebRenderTypes.h"
21 :
22 : class gfxASurface;
23 : class gfxDrawable;
24 : struct gfxQuad;
25 : class nsIInputStream;
26 : class nsIGfxInfo;
27 : class nsIPresShell;
28 :
29 : namespace mozilla {
30 : namespace layers {
31 : class WebRenderBridgeChild;
32 : class GlyphArray;
33 : struct PlanarYCbCrData;
34 : class WebRenderCommand;
35 : } // namespace layers
36 : namespace image {
37 : class ImageRegion;
38 : } // namespace image
39 : namespace wr {
40 : class DisplayListBuilder;
41 : } // namespace wr
42 : } // namespace mozilla
43 :
44 : class gfxUtils {
45 : public:
46 : typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
47 : typedef mozilla::gfx::DrawTarget DrawTarget;
48 : typedef mozilla::gfx::IntPoint IntPoint;
49 : typedef mozilla::gfx::Matrix Matrix;
50 : typedef mozilla::gfx::SourceSurface SourceSurface;
51 : typedef mozilla::gfx::SurfaceFormat SurfaceFormat;
52 : typedef mozilla::image::ImageRegion ImageRegion;
53 :
54 : /*
55 : * Premultiply or Unpremultiply aSourceSurface, writing the result
56 : * to aDestSurface or back into aSourceSurface if aDestSurface is null.
57 : *
58 : * If aDestSurface is given, it must have identical format, dimensions, and
59 : * stride as the source.
60 : *
61 : * If the source is not SurfaceFormat::A8R8G8B8_UINT32, no operation is performed. If
62 : * aDestSurface is given, the data is copied over.
63 : */
64 : static bool PremultiplyDataSurface(DataSourceSurface* srcSurf,
65 : DataSourceSurface* destSurf);
66 : static bool UnpremultiplyDataSurface(DataSourceSurface* srcSurf,
67 : DataSourceSurface* destSurf);
68 :
69 : static already_AddRefed<DataSourceSurface>
70 : CreatePremultipliedDataSurface(DataSourceSurface* srcSurf);
71 : static already_AddRefed<DataSourceSurface>
72 : CreateUnpremultipliedDataSurface(DataSourceSurface* srcSurf);
73 :
74 : static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength);
75 :
76 : /**
77 : * Draw something drawable while working around limitations like bad support
78 : * for EXTEND_PAD, lack of source-clipping, or cairo / pixman bugs with
79 : * extreme user-space-to-image-space transforms.
80 : *
81 : * The input parameters here usually come from the output of our image
82 : * snapping algorithm in nsLayoutUtils.cpp.
83 : * This method is split from nsLayoutUtils::DrawPixelSnapped to allow for
84 : * adjusting the parameters. For example, certain images with transparent
85 : * margins only have a drawable subimage. For those images, imgFrame::Draw
86 : * will tweak the rects and transforms that it gets from the pixel snapping
87 : * algorithm before passing them on to this method.
88 : */
89 : static void DrawPixelSnapped(gfxContext* aContext,
90 : gfxDrawable* aDrawable,
91 : const gfxSize& aImageSize,
92 : const ImageRegion& aRegion,
93 : const mozilla::gfx::SurfaceFormat aFormat,
94 : mozilla::gfx::SamplingFilter aSamplingFilter,
95 : uint32_t aImageFlags = imgIContainer::FLAG_NONE,
96 : gfxFloat aOpacity = 1.0);
97 :
98 : /**
99 : * Clip aContext to the region aRegion.
100 : */
101 : static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion);
102 :
103 : /**
104 : * Clip aTarget to the region aRegion.
105 : */
106 : static void ClipToRegion(mozilla::gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
107 :
108 : /*
109 : * Convert image format to depth value
110 : */
111 : static int ImageFormatToDepth(gfxImageFormat aFormat);
112 :
113 : /**
114 : * Return the transform matrix that maps aFrom to the rectangle defined by
115 : * aToTopLeft/aToTopRight/aToBottomRight. aFrom must be
116 : * nonempty and the destination rectangle must be axis-aligned.
117 : */
118 : static gfxMatrix TransformRectToRect(const gfxRect& aFrom,
119 : const gfxPoint& aToTopLeft,
120 : const gfxPoint& aToTopRight,
121 : const gfxPoint& aToBottomRight);
122 :
123 : static Matrix TransformRectToRect(const gfxRect& aFrom,
124 : const IntPoint& aToTopLeft,
125 : const IntPoint& aToTopRight,
126 : const IntPoint& aToBottomRight);
127 :
128 : /**
129 : * If aIn can be represented exactly using an gfx::IntRect (i.e.
130 : * integer-aligned edges and coordinates in the int32_t range) then we
131 : * set aOut to that rectangle, otherwise return failure.
132 : */
133 : static bool GfxRectToIntRect(const gfxRect& aIn, mozilla::gfx::IntRect* aOut);
134 :
135 : /* Conditions this border to Cairo's max coordinate space.
136 : * The caller can check IsEmpty() after Condition() -- if it's TRUE,
137 : * the caller can possibly avoid doing any extra rendering.
138 : */
139 : static void ConditionRect(gfxRect& aRect);
140 :
141 : /*
142 : * Transform this rectangle with aMatrix, resulting in a gfxQuad.
143 : */
144 : static gfxQuad TransformToQuad(const gfxRect& aRect,
145 : const mozilla::gfx::Matrix4x4& aMatrix);
146 :
147 : /**
148 : * Return the smallest power of kScaleResolution (2) greater than or equal to
149 : * aVal.
150 : */
151 : static gfxFloat ClampToScaleFactor(gfxFloat aVal);
152 :
153 : /**
154 : * Clears surface to aColor (which defaults to transparent black).
155 : */
156 : static void ClearThebesSurface(gfxASurface* aSurface);
157 :
158 : static const float* YuvToRgbMatrix4x3RowMajor(mozilla::YUVColorSpace aYUVColorSpace);
159 : static const float* YuvToRgbMatrix3x3ColumnMajor(mozilla::YUVColorSpace aYUVColorSpace);
160 :
161 : /**
162 : * Creates a copy of aSurface, but having the SurfaceFormat aFormat.
163 : *
164 : * This function always creates a new surface. Do not call it if aSurface's
165 : * format is the same as aFormat. Such a non-conversion would just be an
166 : * unnecessary and wasteful copy (this function asserts to prevent that).
167 : *
168 : * This function is intended to be called by code that needs to access the
169 : * pixel data of the surface, but doesn't want to have lots of branches
170 : * to handle different pixel data formats (code which would become out of
171 : * date if and when new formats are added). Callers can use this function
172 : * to copy the surface to a specified format so that they only have to
173 : * handle pixel data in that one format.
174 : *
175 : * WARNING: There are format conversions that will not be supported by this
176 : * function. It very much depends on what the Moz2D backends support. If
177 : * the temporary B8G8R8A8 DrawTarget that this function creates has a
178 : * backend that supports DrawSurface() calls passing a surface with
179 : * aSurface's format it will work. Otherwise it will not.
180 : *
181 : * *** IMPORTANT PERF NOTE ***
182 : *
183 : * This function exists partly because format conversion is fraught with
184 : * non-obvious performance hazards, so we don't want Moz2D consumers to be
185 : * doing their own format conversion. Do not try to do so, or at least read
186 : * the comments in this functions implemtation. That said, the copy that
187 : * this function carries out has a cost and, although this function tries
188 : * to avoid perf hazards such as expensive uploads to/readbacks from the
189 : * GPU, it can't guarantee that it always successfully does so. Perf
190 : * critical code that can directly handle the common formats that it
191 : * encounters in a way that is cheaper than a copy-with-format-conversion
192 : * should consider doing so, and only use this function as a fallback to
193 : * handle other formats.
194 : *
195 : * XXXjwatt it would be nice if SourceSurface::GetDataSurface took a
196 : * SurfaceFormat argument (with a default argument meaning "use the
197 : * existing surface's format") and returned a DataSourceSurface in that
198 : * format. (There would then be an issue of callers maybe failing to
199 : * realize format conversion may involve expensive copying/uploading/
200 : * readback.)
201 : */
202 : static already_AddRefed<DataSourceSurface>
203 : CopySurfaceToDataSourceSurfaceWithFormat(SourceSurface* aSurface,
204 : SurfaceFormat aFormat);
205 :
206 : /**
207 : * Return a color that can be used to identify a frame with a given frame number.
208 : * The colors will cycle after sNumFrameColors. You can query colors 0 .. sNumFrameColors-1
209 : * to get all the colors back.
210 : */
211 : static const mozilla::gfx::Color& GetColorForFrameNumber(uint64_t aFrameNumber);
212 : static const uint32_t sNumFrameColors;
213 :
214 :
215 : enum BinaryOrData {
216 : eBinaryEncode,
217 : eDataURIEncode
218 : };
219 :
220 : /**
221 : * Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder.
222 : *
223 : * @param aMimeType The MIME-type of the image type that the surface is to
224 : * be encoded to. Used to create an appropriate imgIEncoder instance to
225 : * do the encoding.
226 : *
227 : * @param aOutputOptions Passed directly to imgIEncoder::InitFromData as
228 : * the value of the |outputOptions| parameter. Callers are responsible
229 : * for making sure that this is a sane value for the passed MIME-type
230 : * (i.e. for the type of encoder that will be created).
231 : *
232 : * @aBinaryOrData Flag used to determine if the surface is simply encoded
233 : * to the requested binary image format, or if the binary image is
234 : * further converted to base-64 and written out as a 'data:' URI.
235 : *
236 : * @aFile If specified, the encoded data is written out to aFile, otherwise
237 : * it is copied to the clipboard.
238 : *
239 : * TODO: Copying to the clipboard as a binary file is not currently
240 : * supported.
241 : */
242 : static nsresult
243 : EncodeSourceSurface(SourceSurface* aSurface,
244 : const nsACString& aMimeType,
245 : const nsAString& aOutputOptions,
246 : BinaryOrData aBinaryOrData,
247 : FILE* aFile);
248 :
249 : /**
250 : * Write as a PNG file to the path aFile.
251 : */
252 : static void WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile);
253 : static void WriteAsPNG(SourceSurface* aSurface, const char* aFile);
254 : static void WriteAsPNG(DrawTarget* aDT, const nsAString& aFile);
255 : static void WriteAsPNG(DrawTarget* aDT, const char* aFile);
256 : static void WriteAsPNG(nsIPresShell* aShell, const char* aFile);
257 :
258 : /**
259 : * Dump as a PNG encoded Data URL to a FILE stream (using stdout by
260 : * default).
261 : *
262 : * Rather than giving aFile a default argument we have separate functions
263 : * to make them easier to use from a debugger.
264 : */
265 : static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile);
266 0 : static inline void DumpAsDataURI(SourceSurface* aSourceSurface) {
267 0 : DumpAsDataURI(aSourceSurface, stdout);
268 0 : }
269 : static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile);
270 0 : static inline void DumpAsDataURI(DrawTarget* aDT) {
271 0 : DumpAsDataURI(aDT, stdout);
272 0 : }
273 : static nsCString GetAsDataURI(SourceSurface* aSourceSurface);
274 : static nsCString GetAsDataURI(DrawTarget* aDT);
275 : static nsCString GetAsLZ4Base64Str(DataSourceSurface* aSourceSurface);
276 :
277 : static mozilla::UniquePtr<uint8_t[]> GetImageBuffer(DataSourceSurface* aSurface,
278 : bool aIsAlphaPremultiplied,
279 : int32_t* outFormat);
280 :
281 : static nsresult GetInputStream(DataSourceSurface* aSurface,
282 : bool aIsAlphaPremultiplied,
283 : const char* aMimeType,
284 : const char16_t* aEncoderOptions,
285 : nsIInputStream** outStream);
286 :
287 : static nsresult ThreadSafeGetFeatureStatus(const nsCOMPtr<nsIGfxInfo>& gfxInfo,
288 : int32_t feature,
289 : nsACString& failureId,
290 : int32_t* status);
291 :
292 : /**
293 : * Copy to the clipboard as a PNG encoded Data URL.
294 : */
295 : static void CopyAsDataURI(SourceSurface* aSourceSurface);
296 : static void CopyAsDataURI(DrawTarget* aDT);
297 :
298 : static bool DumpDisplayList();
299 :
300 : static FILE* sDumpPaintFile;
301 : };
302 :
303 : namespace mozilla {
304 : namespace gfx {
305 :
306 : /**
307 : * If the CMS mode is eCMSMode_All, these functions transform the passed
308 : * color to a device color using the transform returened by gfxPlatform::
309 : * GetCMSRGBTransform(). If the CMS mode is some other value, the color is
310 : * returned unchanged (other than a type change to Moz2D Color, if
311 : * applicable).
312 : */
313 : Color ToDeviceColor(Color aColor);
314 : Color ToDeviceColor(nscolor aColor);
315 :
316 : /**
317 : * Performs a checked multiply of the given width, height, and bytes-per-pixel
318 : * values.
319 : */
320 : static inline CheckedInt<uint32_t>
321 0 : SafeBytesForBitmap(uint32_t aWidth, uint32_t aHeight, unsigned aBytesPerPixel)
322 : {
323 0 : MOZ_ASSERT(aBytesPerPixel > 0);
324 0 : CheckedInt<uint32_t> width = uint32_t(aWidth);
325 0 : CheckedInt<uint32_t> height = uint32_t(aHeight);
326 0 : return width * height * aBytesPerPixel;
327 : }
328 :
329 : } // namespace gfx
330 : } // namespace mozilla
331 :
332 : #endif
|