|
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_CONTEXT_H |
|
7 #define GFX_CONTEXT_H |
|
8 |
|
9 #include "gfxTypes.h" |
|
10 |
|
11 #include "gfxASurface.h" |
|
12 #include "gfxPoint.h" |
|
13 #include "gfxRect.h" |
|
14 #include "gfxMatrix.h" |
|
15 #include "gfxPattern.h" |
|
16 #include "gfxPath.h" |
|
17 #include "nsTArray.h" |
|
18 #include "nsAutoPtr.h" |
|
19 |
|
20 #include "mozilla/gfx/2D.h" |
|
21 |
|
22 typedef struct _cairo cairo_t; |
|
23 struct GlyphBufferAzure; |
|
24 template <typename T> class FallibleTArray; |
|
25 |
|
26 /** |
|
27 * This is the main class for doing actual drawing. It is initialized using |
|
28 * a surface and can be drawn on. It manages various state information like |
|
29 * a current transformation matrix (CTM), a current path, current color, |
|
30 * etc. |
|
31 * |
|
32 * All drawing happens by creating a path and then stroking or filling it. |
|
33 * The functions like Rectangle and Arc do not do any drawing themselves. |
|
34 * When a path is drawn (stroked or filled), it is filled/stroked with a |
|
35 * pattern set by SetPattern, SetColor or SetSource. |
|
36 * |
|
37 * Note that the gfxContext takes coordinates in device pixels, |
|
38 * as opposed to app units. |
|
39 */ |
|
40 class gfxContext { |
|
41 NS_INLINE_DECL_REFCOUNTING(gfxContext) |
|
42 |
|
43 public: |
|
44 /** |
|
45 * Initialize this context from a surface. |
|
46 */ |
|
47 gfxContext(gfxASurface *surface); |
|
48 |
|
49 /** |
|
50 * Initialize this context from a DrawTarget. |
|
51 * Strips any transform from aTarget. |
|
52 * aTarget will be flushed in the gfxContext's destructor. |
|
53 */ |
|
54 gfxContext(mozilla::gfx::DrawTarget *aTarget, |
|
55 const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point()); |
|
56 |
|
57 ~gfxContext(); |
|
58 |
|
59 /** |
|
60 * Create a new gfxContext wrapping aTarget and preserving aTarget's |
|
61 * transform. Note that the transform is moved from aTarget to the resulting |
|
62 * gfxContext, aTarget will no longer have its transform. |
|
63 */ |
|
64 static already_AddRefed<gfxContext> ContextForDrawTarget(mozilla::gfx::DrawTarget* aTarget); |
|
65 |
|
66 /** |
|
67 * Return the surface that this gfxContext was created with |
|
68 */ |
|
69 gfxASurface *OriginalSurface(); |
|
70 |
|
71 /** |
|
72 * Return the current transparency group target, if any, along |
|
73 * with its device offsets from the top. If no group is |
|
74 * active, returns the surface the gfxContext was created with, |
|
75 * and 0,0 in dx,dy. |
|
76 */ |
|
77 already_AddRefed<gfxASurface> CurrentSurface(gfxFloat *dx, gfxFloat *dy); |
|
78 already_AddRefed<gfxASurface> CurrentSurface() { |
|
79 return CurrentSurface(nullptr, nullptr); |
|
80 } |
|
81 |
|
82 /** |
|
83 * Return the raw cairo_t object. |
|
84 * XXX this should go away at some point. |
|
85 */ |
|
86 cairo_t *GetCairo(); |
|
87 |
|
88 mozilla::gfx::DrawTarget *GetDrawTarget() { return mDT; } |
|
89 |
|
90 /** |
|
91 * Returns true if the cairo context is in an error state. |
|
92 */ |
|
93 bool HasError(); |
|
94 |
|
95 /** |
|
96 ** State |
|
97 **/ |
|
98 // XXX document exactly what bits are saved |
|
99 void Save(); |
|
100 void Restore(); |
|
101 |
|
102 /** |
|
103 ** Paths & Drawing |
|
104 **/ |
|
105 |
|
106 /** |
|
107 * Stroke the current path using the current settings (such as line |
|
108 * width and color). |
|
109 * A path is set up using functions such as Line, Rectangle and Arc. |
|
110 * |
|
111 * Does not consume the current path. |
|
112 */ |
|
113 void Stroke(); |
|
114 /** |
|
115 * Fill the current path according to the current settings. |
|
116 * |
|
117 * Does not consume the current path. |
|
118 */ |
|
119 void Fill(); |
|
120 |
|
121 /** |
|
122 * Fill the current path according to the current settings and |
|
123 * with |aOpacity|. |
|
124 * |
|
125 * Does not consume the current path. |
|
126 */ |
|
127 void FillWithOpacity(gfxFloat aOpacity); |
|
128 |
|
129 /** |
|
130 * Forgets the current path. |
|
131 */ |
|
132 void NewPath(); |
|
133 |
|
134 /** |
|
135 * Closes the path, i.e. connects the last drawn point to the first one. |
|
136 * |
|
137 * Filling a path will implicitly close it. |
|
138 */ |
|
139 void ClosePath(); |
|
140 |
|
141 /** |
|
142 * Copies the current path and returns the copy. |
|
143 */ |
|
144 already_AddRefed<gfxPath> CopyPath(); |
|
145 |
|
146 /** |
|
147 * Appends the given path to the current path. |
|
148 */ |
|
149 void SetPath(gfxPath* path); |
|
150 |
|
151 /** |
|
152 * Moves the pen to a new point without drawing a line. |
|
153 */ |
|
154 void MoveTo(const gfxPoint& pt); |
|
155 |
|
156 /** |
|
157 * Creates a new subpath starting at the current point. |
|
158 * Equivalent to MoveTo(CurrentPoint()). |
|
159 */ |
|
160 void NewSubPath(); |
|
161 |
|
162 /** |
|
163 * Returns the current point in the current path. |
|
164 */ |
|
165 gfxPoint CurrentPoint(); |
|
166 |
|
167 /** |
|
168 * Draws a line from the current point to pt. |
|
169 * |
|
170 * @see MoveTo |
|
171 */ |
|
172 void LineTo(const gfxPoint& pt); |
|
173 |
|
174 /** |
|
175 * Draws a cubic Bézier curve with control points pt1, pt2 and pt3. |
|
176 */ |
|
177 void CurveTo(const gfxPoint& pt1, const gfxPoint& pt2, const gfxPoint& pt3); |
|
178 |
|
179 /** |
|
180 * Draws a quadratic Bézier curve with control points pt1, pt2 and pt3. |
|
181 */ |
|
182 void QuadraticCurveTo(const gfxPoint& pt1, const gfxPoint& pt2); |
|
183 |
|
184 /** |
|
185 * Draws a clockwise arc (i.e. a circle segment). |
|
186 * @param center The center of the circle |
|
187 * @param radius The radius of the circle |
|
188 * @param angle1 Starting angle for the segment |
|
189 * @param angle2 Ending angle |
|
190 */ |
|
191 void Arc(const gfxPoint& center, gfxFloat radius, |
|
192 gfxFloat angle1, gfxFloat angle2); |
|
193 |
|
194 /** |
|
195 * Draws a counter-clockwise arc (i.e. a circle segment). |
|
196 * @param center The center of the circle |
|
197 * @param radius The radius of the circle |
|
198 * @param angle1 Starting angle for the segment |
|
199 * @param angle2 Ending angle |
|
200 */ |
|
201 |
|
202 void NegativeArc(const gfxPoint& center, gfxFloat radius, |
|
203 gfxFloat angle1, gfxFloat angle2); |
|
204 |
|
205 // path helpers |
|
206 /** |
|
207 * Draws a line from start to end. |
|
208 */ |
|
209 void Line(const gfxPoint& start, const gfxPoint& end); // XXX snapToPixels option? |
|
210 |
|
211 /** |
|
212 * Draws the rectangle given by rect. |
|
213 * @param snapToPixels ? |
|
214 */ |
|
215 void Rectangle(const gfxRect& rect, bool snapToPixels = false); |
|
216 void SnappedRectangle(const gfxRect& rect) { return Rectangle(rect, true); } |
|
217 |
|
218 /** |
|
219 * Draw an ellipse at the center corner with the given dimensions. |
|
220 * It extends dimensions.width / 2.0 in the horizontal direction |
|
221 * from the center, and dimensions.height / 2.0 in the vertical |
|
222 * direction. |
|
223 */ |
|
224 void Ellipse(const gfxPoint& center, const gfxSize& dimensions); |
|
225 |
|
226 /** |
|
227 * Draw a polygon from the given points |
|
228 */ |
|
229 void Polygon(const gfxPoint *points, uint32_t numPoints); |
|
230 |
|
231 /* |
|
232 * Draw a rounded rectangle, with the given outer rect and |
|
233 * corners. The corners specify the radii of the two axes of an |
|
234 * ellipse (the horizontal and vertical directions given by the |
|
235 * width and height, respectively). By default the ellipse is |
|
236 * drawn in a clockwise direction; if draw_clockwise is false, |
|
237 * then it's drawn counterclockwise. |
|
238 */ |
|
239 void RoundedRectangle(const gfxRect& rect, |
|
240 const gfxCornerSizes& corners, |
|
241 bool draw_clockwise = true); |
|
242 |
|
243 /** |
|
244 ** Transformation Matrix manipulation |
|
245 **/ |
|
246 |
|
247 /** |
|
248 * Adds a translation to the current matrix. This translation takes place |
|
249 * before the previously set transformations. |
|
250 */ |
|
251 void Translate(const gfxPoint& pt); |
|
252 |
|
253 /** |
|
254 * Adds a scale to the current matrix. This scaling takes place before the |
|
255 * previously set transformations. |
|
256 */ |
|
257 void Scale(gfxFloat x, gfxFloat y); |
|
258 |
|
259 /** |
|
260 * Adds a rotation around the origin to the current matrix. This rotation |
|
261 * takes place before the previously set transformations. |
|
262 * |
|
263 * @param angle The angle in radians. |
|
264 */ |
|
265 void Rotate(gfxFloat angle); |
|
266 |
|
267 /** |
|
268 * Post-multiplies 'other' onto the current CTM, i.e. this |
|
269 * matrix's transformation will take place before the previously set |
|
270 * transformations. |
|
271 */ |
|
272 void Multiply(const gfxMatrix& other); |
|
273 /** |
|
274 * As "Multiply", but also nudges any entries in the resulting matrix that |
|
275 * are close to an integer to that integer, to correct for |
|
276 * compounded rounding errors. |
|
277 */ |
|
278 void MultiplyAndNudgeToIntegers(const gfxMatrix& other); |
|
279 |
|
280 /** |
|
281 * Replaces the current transformation matrix with matrix. |
|
282 */ |
|
283 void SetMatrix(const gfxMatrix& matrix); |
|
284 |
|
285 /** |
|
286 * Sets the transformation matrix to the identity matrix. |
|
287 */ |
|
288 void IdentityMatrix(); |
|
289 |
|
290 /** |
|
291 * Returns the current transformation matrix. |
|
292 */ |
|
293 gfxMatrix CurrentMatrix() const; |
|
294 |
|
295 /** |
|
296 * Snap components of the current matrix that are close to integers |
|
297 * to integers. In particular, components that are integral when |
|
298 * converted to single precision are set to those integers. |
|
299 */ |
|
300 void NudgeCurrentMatrixToIntegers(); |
|
301 |
|
302 /** |
|
303 * Converts a point from device to user coordinates using the inverse |
|
304 * transformation matrix. |
|
305 */ |
|
306 gfxPoint DeviceToUser(const gfxPoint& point) const; |
|
307 |
|
308 /** |
|
309 * Converts a size from device to user coordinates. This does not apply |
|
310 * translation components of the matrix. |
|
311 */ |
|
312 gfxSize DeviceToUser(const gfxSize& size) const; |
|
313 |
|
314 /** |
|
315 * Converts a rectangle from device to user coordinates; this has the |
|
316 * same effect as using DeviceToUser on both the rectangle's point and |
|
317 * size. |
|
318 */ |
|
319 gfxRect DeviceToUser(const gfxRect& rect) const; |
|
320 |
|
321 /** |
|
322 * Converts a point from user to device coordinates using the transformation |
|
323 * matrix. |
|
324 */ |
|
325 gfxPoint UserToDevice(const gfxPoint& point) const; |
|
326 |
|
327 /** |
|
328 * Converts a size from user to device coordinates. This does not apply |
|
329 * translation components of the matrix. |
|
330 */ |
|
331 gfxSize UserToDevice(const gfxSize& size) const; |
|
332 |
|
333 /** |
|
334 * Converts a rectangle from user to device coordinates. The |
|
335 * resulting rectangle is the minimum device-space rectangle that |
|
336 * encloses the user-space rectangle given. |
|
337 */ |
|
338 gfxRect UserToDevice(const gfxRect& rect) const; |
|
339 |
|
340 /** |
|
341 * Takes the given rect and tries to align it to device pixels. If |
|
342 * this succeeds, the method will return true, and the rect will |
|
343 * be in device coordinates (already transformed by the CTM). If it |
|
344 * fails, the method will return false, and the rect will not be |
|
345 * changed. |
|
346 * |
|
347 * If ignoreScale is true, then snapping will take place even if |
|
348 * the CTM has a scale applied. Snapping never takes place if |
|
349 * there is a rotation in the CTM. |
|
350 */ |
|
351 bool UserToDevicePixelSnapped(gfxRect& rect, bool ignoreScale = false) const; |
|
352 |
|
353 /** |
|
354 * Takes the given point and tries to align it to device pixels. If |
|
355 * this succeeds, the method will return true, and the point will |
|
356 * be in device coordinates (already transformed by the CTM). If it |
|
357 * fails, the method will return false, and the point will not be |
|
358 * changed. |
|
359 * |
|
360 * If ignoreScale is true, then snapping will take place even if |
|
361 * the CTM has a scale applied. Snapping never takes place if |
|
362 * there is a rotation in the CTM. |
|
363 */ |
|
364 bool UserToDevicePixelSnapped(gfxPoint& pt, bool ignoreScale = false) const; |
|
365 |
|
366 /** |
|
367 * Attempts to pixel snap the rectangle, add it to the current |
|
368 * path, and to set pattern as the current painting source. This |
|
369 * should be used for drawing filled pixel-snapped rectangles (like |
|
370 * images), because the CTM at the time of the SetPattern call needs |
|
371 * to have a snapped translation, or you get smeared images. |
|
372 */ |
|
373 void PixelSnappedRectangleAndSetPattern(const gfxRect& rect, gfxPattern *pattern); |
|
374 |
|
375 /** |
|
376 ** Painting sources |
|
377 **/ |
|
378 |
|
379 /** |
|
380 * Set a solid color to use for drawing. This color is in the device color space |
|
381 * and is not transformed. |
|
382 */ |
|
383 void SetDeviceColor(const gfxRGBA& c); |
|
384 |
|
385 /** |
|
386 * Gets the current color. It's returned in the device color space. |
|
387 * returns false if there is something other than a color |
|
388 * set as the current source (pattern, surface, etc) |
|
389 */ |
|
390 bool GetDeviceColor(gfxRGBA& c); |
|
391 |
|
392 /** |
|
393 * Set a solid color in the sRGB color space to use for drawing. |
|
394 * If CMS is not enabled, the color is treated as a device-space color |
|
395 * and this call is identical to SetDeviceColor(). |
|
396 */ |
|
397 void SetColor(const gfxRGBA& c); |
|
398 |
|
399 /** |
|
400 * Uses a surface for drawing. This is a shorthand for creating a |
|
401 * pattern and setting it. |
|
402 * |
|
403 * @param offset from the source surface, to use only part of it. |
|
404 * May need to make it negative. |
|
405 */ |
|
406 void SetSource(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0)); |
|
407 |
|
408 /** |
|
409 * Uses a pattern for drawing. |
|
410 */ |
|
411 void SetPattern(gfxPattern *pattern); |
|
412 |
|
413 /** |
|
414 * Get the source pattern (solid color, normal pattern, surface, etc) |
|
415 */ |
|
416 already_AddRefed<gfxPattern> GetPattern(); |
|
417 |
|
418 /** |
|
419 ** Painting |
|
420 **/ |
|
421 /** |
|
422 * Paints the current source surface/pattern everywhere in the current |
|
423 * clip region. |
|
424 */ |
|
425 void Paint(gfxFloat alpha = 1.0); |
|
426 |
|
427 /** |
|
428 ** Painting with a Mask |
|
429 **/ |
|
430 /** |
|
431 * Like Paint, except that it only draws the source where pattern is |
|
432 * non-transparent. |
|
433 */ |
|
434 void Mask(gfxPattern *pattern); |
|
435 |
|
436 /** |
|
437 * Shorthand for creating a pattern and calling the pattern-taking |
|
438 * variant of Mask. |
|
439 */ |
|
440 void Mask(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0)); |
|
441 |
|
442 void Mask(mozilla::gfx::SourceSurface *surface, const mozilla::gfx::Point& offset = mozilla::gfx::Point()); |
|
443 |
|
444 /** |
|
445 ** Shortcuts |
|
446 **/ |
|
447 |
|
448 /** |
|
449 * Creates a new path with a rectangle from 0,0 to size.w,size.h |
|
450 * and calls cairo_fill. |
|
451 */ |
|
452 void DrawSurface(gfxASurface *surface, const gfxSize& size); |
|
453 |
|
454 /** |
|
455 ** Line Properties |
|
456 **/ |
|
457 |
|
458 typedef enum { |
|
459 gfxLineSolid, |
|
460 gfxLineDashed, |
|
461 gfxLineDotted |
|
462 } gfxLineType; |
|
463 |
|
464 void SetDash(gfxLineType ltype); |
|
465 void SetDash(gfxFloat *dashes, int ndash, gfxFloat offset); |
|
466 // Return true if dashing is set, false if it's not enabled or the |
|
467 // context is in an error state. |offset| can be nullptr to mean |
|
468 // "don't care". |
|
469 bool CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const; |
|
470 // Returns 0.0 if dashing isn't enabled. |
|
471 gfxFloat CurrentDashOffset() const; |
|
472 |
|
473 /** |
|
474 * Sets the line width that's used for line drawing. |
|
475 */ |
|
476 void SetLineWidth(gfxFloat width); |
|
477 |
|
478 /** |
|
479 * Returns the currently set line width. |
|
480 * |
|
481 * @see SetLineWidth |
|
482 */ |
|
483 gfxFloat CurrentLineWidth() const; |
|
484 |
|
485 enum GraphicsLineCap { |
|
486 LINE_CAP_BUTT, |
|
487 LINE_CAP_ROUND, |
|
488 LINE_CAP_SQUARE |
|
489 }; |
|
490 /** |
|
491 * Sets the line caps, i.e. how line endings are drawn. |
|
492 */ |
|
493 void SetLineCap(GraphicsLineCap cap); |
|
494 GraphicsLineCap CurrentLineCap() const; |
|
495 |
|
496 enum GraphicsLineJoin { |
|
497 LINE_JOIN_MITER, |
|
498 LINE_JOIN_ROUND, |
|
499 LINE_JOIN_BEVEL |
|
500 }; |
|
501 /** |
|
502 * Sets the line join, i.e. how the connection between two lines is |
|
503 * drawn. |
|
504 */ |
|
505 void SetLineJoin(GraphicsLineJoin join); |
|
506 GraphicsLineJoin CurrentLineJoin() const; |
|
507 |
|
508 void SetMiterLimit(gfxFloat limit); |
|
509 gfxFloat CurrentMiterLimit() const; |
|
510 |
|
511 /** |
|
512 ** Fill Properties |
|
513 **/ |
|
514 |
|
515 enum FillRule { |
|
516 FILL_RULE_WINDING, |
|
517 FILL_RULE_EVEN_ODD |
|
518 }; |
|
519 void SetFillRule(FillRule rule); |
|
520 FillRule CurrentFillRule() const; |
|
521 |
|
522 /** |
|
523 ** Operators and Rendering control |
|
524 **/ |
|
525 |
|
526 // define enum for operators (clear, src, dst, etc) |
|
527 enum GraphicsOperator { |
|
528 OPERATOR_CLEAR, |
|
529 OPERATOR_SOURCE, |
|
530 |
|
531 OPERATOR_OVER, |
|
532 OPERATOR_IN, |
|
533 OPERATOR_OUT, |
|
534 OPERATOR_ATOP, |
|
535 |
|
536 OPERATOR_DEST, |
|
537 OPERATOR_DEST_OVER, |
|
538 OPERATOR_DEST_IN, |
|
539 OPERATOR_DEST_OUT, |
|
540 OPERATOR_DEST_ATOP, |
|
541 |
|
542 OPERATOR_XOR, |
|
543 OPERATOR_ADD, |
|
544 OPERATOR_SATURATE, |
|
545 |
|
546 OPERATOR_MULTIPLY, |
|
547 OPERATOR_SCREEN, |
|
548 OPERATOR_OVERLAY, |
|
549 OPERATOR_DARKEN, |
|
550 OPERATOR_LIGHTEN, |
|
551 OPERATOR_COLOR_DODGE, |
|
552 OPERATOR_COLOR_BURN, |
|
553 OPERATOR_HARD_LIGHT, |
|
554 OPERATOR_SOFT_LIGHT, |
|
555 OPERATOR_DIFFERENCE, |
|
556 OPERATOR_EXCLUSION, |
|
557 OPERATOR_HUE, |
|
558 OPERATOR_SATURATION, |
|
559 OPERATOR_COLOR, |
|
560 OPERATOR_LUMINOSITY |
|
561 }; |
|
562 /** |
|
563 * Sets the operator used for all further drawing. The operator affects |
|
564 * how drawing something will modify the destination. For example, the |
|
565 * OVER operator will do alpha blending of source and destination, while |
|
566 * SOURCE will replace the destination with the source. |
|
567 * |
|
568 * Note that if the flag FLAG_SIMPLIFY_OPERATORS is set on this |
|
569 * gfxContext, the actual operator set might change for optimization |
|
570 * purposes. Check the comments below around that flag. |
|
571 */ |
|
572 void SetOperator(GraphicsOperator op); |
|
573 GraphicsOperator CurrentOperator() const; |
|
574 |
|
575 /** |
|
576 * MODE_ALIASED means that only pixels whose centers are in the drawn area |
|
577 * should be modified, and they should be modified to take the value drawn |
|
578 * at the pixel center. |
|
579 */ |
|
580 enum AntialiasMode { |
|
581 MODE_ALIASED, |
|
582 MODE_COVERAGE |
|
583 }; |
|
584 void SetAntialiasMode(AntialiasMode mode); |
|
585 AntialiasMode CurrentAntialiasMode() const; |
|
586 |
|
587 /** |
|
588 ** Clipping |
|
589 **/ |
|
590 |
|
591 /** |
|
592 * Clips all further drawing to the current path. |
|
593 * This does not consume the current path. |
|
594 */ |
|
595 void Clip(); |
|
596 |
|
597 /** |
|
598 * Undoes any clipping. Further drawings will only be restricted by the |
|
599 * surface dimensions. |
|
600 */ |
|
601 void ResetClip(); |
|
602 |
|
603 /** |
|
604 * Helper functions that will create a rect path and call Clip(). |
|
605 * Any current path will be destroyed by these functions! |
|
606 */ |
|
607 void Clip(const gfxRect& rect); // will clip to a rect |
|
608 |
|
609 /** |
|
610 * This will ensure that the surface actually has its clip set. |
|
611 * Useful if you are doing native drawing. |
|
612 */ |
|
613 void UpdateSurfaceClip(); |
|
614 |
|
615 /** |
|
616 * This will return the current bounds of the clip region in user |
|
617 * space. |
|
618 */ |
|
619 gfxRect GetClipExtents(); |
|
620 |
|
621 /** |
|
622 * Returns true if the given rectangle is fully contained in the current clip. |
|
623 * This is conservative; it may return false even when the given rectangle is |
|
624 * fully contained by the current clip. |
|
625 */ |
|
626 bool ClipContainsRect(const gfxRect& aRect); |
|
627 |
|
628 /** |
|
629 * Groups |
|
630 */ |
|
631 void PushGroup(gfxContentType content = gfxContentType::COLOR); |
|
632 /** |
|
633 * Like PushGroup, but if the current surface is gfxContentType::COLOR and |
|
634 * content is gfxContentType::COLOR_ALPHA, makes the pushed surface gfxContentType::COLOR |
|
635 * instead and copies the contents of the current surface to the pushed |
|
636 * surface. This is good for pushing opacity groups, since blending the |
|
637 * group back to the current surface with some alpha applied will give |
|
638 * the correct results and using an opaque pushed surface gives better |
|
639 * quality and performance. |
|
640 * This API really only makes sense if you do a PopGroupToSource and |
|
641 * immediate Paint with OPERATOR_OVER. |
|
642 */ |
|
643 void PushGroupAndCopyBackground(gfxContentType content = gfxContentType::COLOR); |
|
644 already_AddRefed<gfxPattern> PopGroup(); |
|
645 void PopGroupToSource(); |
|
646 |
|
647 /** |
|
648 ** Hit Testing - check if given point is in the current path |
|
649 **/ |
|
650 bool PointInFill(const gfxPoint& pt); |
|
651 bool PointInStroke(const gfxPoint& pt); |
|
652 |
|
653 /** |
|
654 ** Extents - returns user space extent of current path |
|
655 **/ |
|
656 gfxRect GetUserPathExtent(); |
|
657 gfxRect GetUserFillExtent(); |
|
658 gfxRect GetUserStrokeExtent(); |
|
659 |
|
660 mozilla::gfx::Point GetDeviceOffset() const; |
|
661 |
|
662 /** |
|
663 ** Flags |
|
664 **/ |
|
665 |
|
666 enum { |
|
667 /* If this flag is set, operators other than CLEAR, SOURCE, or |
|
668 * OVER will be converted to OVER before being sent to cairo. |
|
669 * |
|
670 * This is most useful with a printing surface, where |
|
671 * operators such as ADD are used to avoid seams for on-screen |
|
672 * display, but where such errors aren't noticeable in print. |
|
673 * This approach is currently used in border rendering. |
|
674 * |
|
675 * However, when printing complex renderings such as SVG, |
|
676 * care should be taken to clear this flag. |
|
677 */ |
|
678 FLAG_SIMPLIFY_OPERATORS = (1 << 0), |
|
679 /** |
|
680 * When this flag is set, snapping to device pixels is disabled. |
|
681 * It simply never does anything. |
|
682 */ |
|
683 FLAG_DISABLE_SNAPPING = (1 << 1), |
|
684 /** |
|
685 * Disable copying of backgrounds in PushGroupAndCopyBackground. |
|
686 */ |
|
687 FLAG_DISABLE_COPY_BACKGROUND = (1 << 2) |
|
688 }; |
|
689 |
|
690 void SetFlag(int32_t aFlag) { mFlags |= aFlag; } |
|
691 void ClearFlag(int32_t aFlag) { mFlags &= ~aFlag; } |
|
692 int32_t GetFlags() const { return mFlags; } |
|
693 |
|
694 bool IsCairo() const { return !mDT; } |
|
695 |
|
696 // Work out whether cairo will snap inter-glyph spacing to pixels. |
|
697 void GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY); |
|
698 |
|
699 #ifdef MOZ_DUMP_PAINTING |
|
700 /** |
|
701 * Debug functions to encode the current surface as a PNG and export it. |
|
702 */ |
|
703 |
|
704 /** |
|
705 * Writes a binary PNG file. |
|
706 */ |
|
707 void WriteAsPNG(const char* aFile); |
|
708 |
|
709 /** |
|
710 * Write as a PNG encoded Data URL to stdout. |
|
711 */ |
|
712 void DumpAsDataURL(); |
|
713 |
|
714 /** |
|
715 * Copy a PNG encoded Data URL to the clipboard. |
|
716 */ |
|
717 void CopyAsDataURL(); |
|
718 #endif |
|
719 |
|
720 static mozilla::gfx::UserDataKey sDontUseAsSourceKey; |
|
721 |
|
722 private: |
|
723 friend class GeneralPattern; |
|
724 friend struct GlyphBufferAzure; |
|
725 |
|
726 typedef mozilla::gfx::Matrix Matrix; |
|
727 typedef mozilla::gfx::DrawTarget DrawTarget; |
|
728 typedef mozilla::gfx::Color Color; |
|
729 typedef mozilla::gfx::StrokeOptions StrokeOptions; |
|
730 typedef mozilla::gfx::Float Float; |
|
731 typedef mozilla::gfx::Rect Rect; |
|
732 typedef mozilla::gfx::CompositionOp CompositionOp; |
|
733 typedef mozilla::gfx::Path Path; |
|
734 typedef mozilla::gfx::PathBuilder PathBuilder; |
|
735 typedef mozilla::gfx::SourceSurface SourceSurface; |
|
736 |
|
737 struct AzureState { |
|
738 AzureState() |
|
739 : op(mozilla::gfx::CompositionOp::OP_OVER) |
|
740 , opIsClear(false) |
|
741 , color(0, 0, 0, 1.0f) |
|
742 , clipWasReset(false) |
|
743 , fillRule(mozilla::gfx::FillRule::FILL_WINDING) |
|
744 , aaMode(mozilla::gfx::AntialiasMode::SUBPIXEL) |
|
745 , patternTransformChanged(false) |
|
746 {} |
|
747 |
|
748 mozilla::gfx::CompositionOp op; |
|
749 bool opIsClear; |
|
750 Color color; |
|
751 nsRefPtr<gfxPattern> pattern; |
|
752 nsRefPtr<gfxASurface> sourceSurfCairo; |
|
753 mozilla::RefPtr<SourceSurface> sourceSurface; |
|
754 mozilla::gfx::Point sourceSurfaceDeviceOffset; |
|
755 Matrix surfTransform; |
|
756 Matrix transform; |
|
757 struct PushedClip { |
|
758 mozilla::RefPtr<Path> path; |
|
759 Rect rect; |
|
760 Matrix transform; |
|
761 }; |
|
762 nsTArray<PushedClip> pushedClips; |
|
763 nsTArray<Float> dashPattern; |
|
764 bool clipWasReset; |
|
765 mozilla::gfx::FillRule fillRule; |
|
766 StrokeOptions strokeOptions; |
|
767 mozilla::RefPtr<DrawTarget> drawTarget; |
|
768 mozilla::RefPtr<DrawTarget> parentTarget; |
|
769 mozilla::gfx::AntialiasMode aaMode; |
|
770 bool patternTransformChanged; |
|
771 Matrix patternTransform; |
|
772 // This is used solely for using minimal intermediate surface size. |
|
773 mozilla::gfx::Point deviceOffset; |
|
774 }; |
|
775 |
|
776 // This ensures mPath contains a valid path (in user space!) |
|
777 void EnsurePath(); |
|
778 // This ensures mPathBuilder contains a valid PathBuilder (in user space!) |
|
779 void EnsurePathBuilder(); |
|
780 void FillAzure(mozilla::gfx::Float aOpacity); |
|
781 void PushClipsToDT(mozilla::gfx::DrawTarget *aDT); |
|
782 CompositionOp GetOp(); |
|
783 void ChangeTransform(const mozilla::gfx::Matrix &aNewMatrix, bool aUpdatePatternTransform = true); |
|
784 Rect GetAzureDeviceSpaceClipBounds(); |
|
785 Matrix GetDeviceTransform() const; |
|
786 Matrix GetDTTransform() const; |
|
787 void PushNewDT(gfxContentType content); |
|
788 |
|
789 bool mPathIsRect; |
|
790 bool mTransformChanged; |
|
791 Matrix mPathTransform; |
|
792 Rect mRect; |
|
793 mozilla::RefPtr<PathBuilder> mPathBuilder; |
|
794 mozilla::RefPtr<Path> mPath; |
|
795 Matrix mTransform; |
|
796 nsTArray<AzureState> mStateStack; |
|
797 |
|
798 AzureState &CurrentState() { return mStateStack[mStateStack.Length() - 1]; } |
|
799 const AzureState &CurrentState() const { return mStateStack[mStateStack.Length() - 1]; } |
|
800 |
|
801 cairo_t *mCairo; |
|
802 cairo_t *mRefCairo; |
|
803 nsRefPtr<gfxASurface> mSurface; |
|
804 int32_t mFlags; |
|
805 |
|
806 mozilla::RefPtr<DrawTarget> mDT; |
|
807 mozilla::RefPtr<DrawTarget> mOriginalDT; |
|
808 }; |
|
809 |
|
810 /** |
|
811 * Sentry helper class for functions with multiple return points that need to |
|
812 * call Save() on a gfxContext and have Restore() called automatically on the |
|
813 * gfxContext before they return. |
|
814 */ |
|
815 class gfxContextAutoSaveRestore |
|
816 { |
|
817 public: |
|
818 gfxContextAutoSaveRestore() : mContext(nullptr) {} |
|
819 |
|
820 gfxContextAutoSaveRestore(gfxContext *aContext) : mContext(aContext) { |
|
821 mContext->Save(); |
|
822 } |
|
823 |
|
824 ~gfxContextAutoSaveRestore() { |
|
825 if (mContext) { |
|
826 mContext->Restore(); |
|
827 } |
|
828 } |
|
829 |
|
830 void SetContext(gfxContext *aContext) { |
|
831 NS_ASSERTION(!mContext, "Not going to call Restore() on some context!!!"); |
|
832 mContext = aContext; |
|
833 mContext->Save(); |
|
834 } |
|
835 |
|
836 void Reset(gfxContext *aContext) { |
|
837 // Do the equivalent of destroying and re-creating this object. |
|
838 NS_PRECONDITION(aContext, "must provide a context"); |
|
839 if (mContext) { |
|
840 mContext->Restore(); |
|
841 } |
|
842 mContext = aContext; |
|
843 mContext->Save(); |
|
844 } |
|
845 |
|
846 private: |
|
847 gfxContext *mContext; |
|
848 }; |
|
849 |
|
850 /** |
|
851 * Sentry helper class for functions with multiple return points that need to |
|
852 * back up the current path of a context and have it automatically restored |
|
853 * before they return. This class assumes that the transformation matrix will |
|
854 * be the same when Save and Restore are called. The calling function must |
|
855 * ensure that this is the case or the path will be copied incorrectly. |
|
856 */ |
|
857 class gfxContextPathAutoSaveRestore |
|
858 { |
|
859 public: |
|
860 gfxContextPathAutoSaveRestore() : mContext(nullptr) {} |
|
861 |
|
862 gfxContextPathAutoSaveRestore(gfxContext *aContext, bool aSave = true) : mContext(aContext) |
|
863 { |
|
864 if (aSave) |
|
865 Save(); |
|
866 } |
|
867 |
|
868 ~gfxContextPathAutoSaveRestore() |
|
869 { |
|
870 Restore(); |
|
871 } |
|
872 |
|
873 void SetContext(gfxContext *aContext, bool aSave = true) |
|
874 { |
|
875 mContext = aContext; |
|
876 if (aSave) |
|
877 Save(); |
|
878 } |
|
879 |
|
880 /** |
|
881 * If a path is already saved, does nothing. Else copies the current path |
|
882 * so that it may be restored. |
|
883 */ |
|
884 void Save() |
|
885 { |
|
886 if (!mPath && mContext) { |
|
887 mPath = mContext->CopyPath(); |
|
888 } |
|
889 } |
|
890 |
|
891 /** |
|
892 * If no path is saved, does nothing. Else replaces the context's path with |
|
893 * a copy of the saved one, and clears the saved path. |
|
894 */ |
|
895 void Restore() |
|
896 { |
|
897 if (mPath) { |
|
898 mContext->SetPath(mPath); |
|
899 mPath = nullptr; |
|
900 } |
|
901 } |
|
902 |
|
903 private: |
|
904 gfxContext *mContext; |
|
905 |
|
906 nsRefPtr<gfxPath> mPath; |
|
907 }; |
|
908 |
|
909 /** |
|
910 * Sentry helper class for functions with multiple return points that need to |
|
911 * back up the current matrix of a context and have it automatically restored |
|
912 * before they return. |
|
913 */ |
|
914 class gfxContextMatrixAutoSaveRestore |
|
915 { |
|
916 public: |
|
917 gfxContextMatrixAutoSaveRestore() : |
|
918 mContext(nullptr) |
|
919 { |
|
920 } |
|
921 |
|
922 gfxContextMatrixAutoSaveRestore(gfxContext *aContext) : |
|
923 mContext(aContext), mMatrix(aContext->CurrentMatrix()) |
|
924 { |
|
925 } |
|
926 |
|
927 ~gfxContextMatrixAutoSaveRestore() |
|
928 { |
|
929 if (mContext) { |
|
930 mContext->SetMatrix(mMatrix); |
|
931 } |
|
932 } |
|
933 |
|
934 void SetContext(gfxContext *aContext) |
|
935 { |
|
936 NS_ASSERTION(!mContext, "Not going to restore the matrix on some context!"); |
|
937 mContext = aContext; |
|
938 mMatrix = aContext->CurrentMatrix(); |
|
939 } |
|
940 |
|
941 void Restore() |
|
942 { |
|
943 if (mContext) { |
|
944 mContext->SetMatrix(mMatrix); |
|
945 } |
|
946 } |
|
947 |
|
948 const gfxMatrix& Matrix() |
|
949 { |
|
950 MOZ_ASSERT(mContext, "mMatrix doesn't contain a useful matrix"); |
|
951 return mMatrix; |
|
952 } |
|
953 |
|
954 private: |
|
955 gfxContext *mContext; |
|
956 gfxMatrix mMatrix; |
|
957 }; |
|
958 |
|
959 |
|
960 class gfxContextAutoDisableSubpixelAntialiasing { |
|
961 public: |
|
962 gfxContextAutoDisableSubpixelAntialiasing(gfxContext *aContext, bool aDisable) |
|
963 { |
|
964 if (aDisable) { |
|
965 if (aContext->IsCairo()) { |
|
966 mSurface = aContext->CurrentSurface(); |
|
967 if (!mSurface) { |
|
968 return; |
|
969 } |
|
970 mSubpixelAntialiasingEnabled = mSurface->GetSubpixelAntialiasingEnabled(); |
|
971 mSurface->SetSubpixelAntialiasingEnabled(false); |
|
972 } else { |
|
973 mDT = aContext->GetDrawTarget(); |
|
974 |
|
975 mSubpixelAntialiasingEnabled = mDT->GetPermitSubpixelAA(); |
|
976 mDT->SetPermitSubpixelAA(false); |
|
977 } |
|
978 } |
|
979 } |
|
980 ~gfxContextAutoDisableSubpixelAntialiasing() |
|
981 { |
|
982 if (mSurface) { |
|
983 mSurface->SetSubpixelAntialiasingEnabled(mSubpixelAntialiasingEnabled); |
|
984 } else if (mDT) { |
|
985 mDT->SetPermitSubpixelAA(mSubpixelAntialiasingEnabled); |
|
986 } |
|
987 } |
|
988 |
|
989 private: |
|
990 nsRefPtr<gfxASurface> mSurface; |
|
991 mozilla::RefPtr<mozilla::gfx::DrawTarget> mDT; |
|
992 bool mSubpixelAntialiasingEnabled; |
|
993 }; |
|
994 |
|
995 #endif /* GFX_CONTEXT_H */ |