Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
6 #ifndef GFX_CONTEXT_H
7 #define GFX_CONTEXT_H
9 #include "gfxTypes.h"
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"
20 #include "mozilla/gfx/2D.h"
22 typedef struct _cairo cairo_t;
23 struct GlyphBufferAzure;
24 template <typename T> class FallibleTArray;
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)
43 public:
44 /**
45 * Initialize this context from a surface.
46 */
47 gfxContext(gfxASurface *surface);
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());
57 ~gfxContext();
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);
66 /**
67 * Return the surface that this gfxContext was created with
68 */
69 gfxASurface *OriginalSurface();
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 }
82 /**
83 * Return the raw cairo_t object.
84 * XXX this should go away at some point.
85 */
86 cairo_t *GetCairo();
88 mozilla::gfx::DrawTarget *GetDrawTarget() { return mDT; }
90 /**
91 * Returns true if the cairo context is in an error state.
92 */
93 bool HasError();
95 /**
96 ** State
97 **/
98 // XXX document exactly what bits are saved
99 void Save();
100 void Restore();
102 /**
103 ** Paths & Drawing
104 **/
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();
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);
129 /**
130 * Forgets the current path.
131 */
132 void NewPath();
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();
141 /**
142 * Copies the current path and returns the copy.
143 */
144 already_AddRefed<gfxPath> CopyPath();
146 /**
147 * Appends the given path to the current path.
148 */
149 void SetPath(gfxPath* path);
151 /**
152 * Moves the pen to a new point without drawing a line.
153 */
154 void MoveTo(const gfxPoint& pt);
156 /**
157 * Creates a new subpath starting at the current point.
158 * Equivalent to MoveTo(CurrentPoint()).
159 */
160 void NewSubPath();
162 /**
163 * Returns the current point in the current path.
164 */
165 gfxPoint CurrentPoint();
167 /**
168 * Draws a line from the current point to pt.
169 *
170 * @see MoveTo
171 */
172 void LineTo(const gfxPoint& pt);
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);
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);
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);
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 */
202 void NegativeArc(const gfxPoint& center, gfxFloat radius,
203 gfxFloat angle1, gfxFloat angle2);
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?
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); }
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);
226 /**
227 * Draw a polygon from the given points
228 */
229 void Polygon(const gfxPoint *points, uint32_t numPoints);
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);
243 /**
244 ** Transformation Matrix manipulation
245 **/
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);
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);
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);
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);
280 /**
281 * Replaces the current transformation matrix with matrix.
282 */
283 void SetMatrix(const gfxMatrix& matrix);
285 /**
286 * Sets the transformation matrix to the identity matrix.
287 */
288 void IdentityMatrix();
290 /**
291 * Returns the current transformation matrix.
292 */
293 gfxMatrix CurrentMatrix() const;
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();
302 /**
303 * Converts a point from device to user coordinates using the inverse
304 * transformation matrix.
305 */
306 gfxPoint DeviceToUser(const gfxPoint& point) const;
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;
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;
321 /**
322 * Converts a point from user to device coordinates using the transformation
323 * matrix.
324 */
325 gfxPoint UserToDevice(const gfxPoint& point) const;
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;
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;
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;
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;
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);
375 /**
376 ** Painting sources
377 **/
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);
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);
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);
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));
408 /**
409 * Uses a pattern for drawing.
410 */
411 void SetPattern(gfxPattern *pattern);
413 /**
414 * Get the source pattern (solid color, normal pattern, surface, etc)
415 */
416 already_AddRefed<gfxPattern> GetPattern();
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);
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);
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));
442 void Mask(mozilla::gfx::SourceSurface *surface, const mozilla::gfx::Point& offset = mozilla::gfx::Point());
444 /**
445 ** Shortcuts
446 **/
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);
454 /**
455 ** Line Properties
456 **/
458 typedef enum {
459 gfxLineSolid,
460 gfxLineDashed,
461 gfxLineDotted
462 } gfxLineType;
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;
473 /**
474 * Sets the line width that's used for line drawing.
475 */
476 void SetLineWidth(gfxFloat width);
478 /**
479 * Returns the currently set line width.
480 *
481 * @see SetLineWidth
482 */
483 gfxFloat CurrentLineWidth() const;
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;
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;
508 void SetMiterLimit(gfxFloat limit);
509 gfxFloat CurrentMiterLimit() const;
511 /**
512 ** Fill Properties
513 **/
515 enum FillRule {
516 FILL_RULE_WINDING,
517 FILL_RULE_EVEN_ODD
518 };
519 void SetFillRule(FillRule rule);
520 FillRule CurrentFillRule() const;
522 /**
523 ** Operators and Rendering control
524 **/
526 // define enum for operators (clear, src, dst, etc)
527 enum GraphicsOperator {
528 OPERATOR_CLEAR,
529 OPERATOR_SOURCE,
531 OPERATOR_OVER,
532 OPERATOR_IN,
533 OPERATOR_OUT,
534 OPERATOR_ATOP,
536 OPERATOR_DEST,
537 OPERATOR_DEST_OVER,
538 OPERATOR_DEST_IN,
539 OPERATOR_DEST_OUT,
540 OPERATOR_DEST_ATOP,
542 OPERATOR_XOR,
543 OPERATOR_ADD,
544 OPERATOR_SATURATE,
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;
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;
587 /**
588 ** Clipping
589 **/
591 /**
592 * Clips all further drawing to the current path.
593 * This does not consume the current path.
594 */
595 void Clip();
597 /**
598 * Undoes any clipping. Further drawings will only be restricted by the
599 * surface dimensions.
600 */
601 void ResetClip();
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
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();
615 /**
616 * This will return the current bounds of the clip region in user
617 * space.
618 */
619 gfxRect GetClipExtents();
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);
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();
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);
653 /**
654 ** Extents - returns user space extent of current path
655 **/
656 gfxRect GetUserPathExtent();
657 gfxRect GetUserFillExtent();
658 gfxRect GetUserStrokeExtent();
660 mozilla::gfx::Point GetDeviceOffset() const;
662 /**
663 ** Flags
664 **/
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 };
690 void SetFlag(int32_t aFlag) { mFlags |= aFlag; }
691 void ClearFlag(int32_t aFlag) { mFlags &= ~aFlag; }
692 int32_t GetFlags() const { return mFlags; }
694 bool IsCairo() const { return !mDT; }
696 // Work out whether cairo will snap inter-glyph spacing to pixels.
697 void GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY);
699 #ifdef MOZ_DUMP_PAINTING
700 /**
701 * Debug functions to encode the current surface as a PNG and export it.
702 */
704 /**
705 * Writes a binary PNG file.
706 */
707 void WriteAsPNG(const char* aFile);
709 /**
710 * Write as a PNG encoded Data URL to stdout.
711 */
712 void DumpAsDataURL();
714 /**
715 * Copy a PNG encoded Data URL to the clipboard.
716 */
717 void CopyAsDataURL();
718 #endif
720 static mozilla::gfx::UserDataKey sDontUseAsSourceKey;
722 private:
723 friend class GeneralPattern;
724 friend struct GlyphBufferAzure;
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;
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 {}
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 };
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);
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;
798 AzureState &CurrentState() { return mStateStack[mStateStack.Length() - 1]; }
799 const AzureState &CurrentState() const { return mStateStack[mStateStack.Length() - 1]; }
801 cairo_t *mCairo;
802 cairo_t *mRefCairo;
803 nsRefPtr<gfxASurface> mSurface;
804 int32_t mFlags;
806 mozilla::RefPtr<DrawTarget> mDT;
807 mozilla::RefPtr<DrawTarget> mOriginalDT;
808 };
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) {}
820 gfxContextAutoSaveRestore(gfxContext *aContext) : mContext(aContext) {
821 mContext->Save();
822 }
824 ~gfxContextAutoSaveRestore() {
825 if (mContext) {
826 mContext->Restore();
827 }
828 }
830 void SetContext(gfxContext *aContext) {
831 NS_ASSERTION(!mContext, "Not going to call Restore() on some context!!!");
832 mContext = aContext;
833 mContext->Save();
834 }
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 }
846 private:
847 gfxContext *mContext;
848 };
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) {}
862 gfxContextPathAutoSaveRestore(gfxContext *aContext, bool aSave = true) : mContext(aContext)
863 {
864 if (aSave)
865 Save();
866 }
868 ~gfxContextPathAutoSaveRestore()
869 {
870 Restore();
871 }
873 void SetContext(gfxContext *aContext, bool aSave = true)
874 {
875 mContext = aContext;
876 if (aSave)
877 Save();
878 }
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 }
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 }
903 private:
904 gfxContext *mContext;
906 nsRefPtr<gfxPath> mPath;
907 };
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 }
922 gfxContextMatrixAutoSaveRestore(gfxContext *aContext) :
923 mContext(aContext), mMatrix(aContext->CurrentMatrix())
924 {
925 }
927 ~gfxContextMatrixAutoSaveRestore()
928 {
929 if (mContext) {
930 mContext->SetMatrix(mMatrix);
931 }
932 }
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 }
941 void Restore()
942 {
943 if (mContext) {
944 mContext->SetMatrix(mMatrix);
945 }
946 }
948 const gfxMatrix& Matrix()
949 {
950 MOZ_ASSERT(mContext, "mMatrix doesn't contain a useful matrix");
951 return mMatrix;
952 }
954 private:
955 gfxContext *mContext;
956 gfxMatrix mMatrix;
957 };
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();
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 }
989 private:
990 nsRefPtr<gfxASurface> mSurface;
991 mozilla::RefPtr<mozilla::gfx::DrawTarget> mDT;
992 bool mSubpixelAntialiasingEnabled;
993 };
995 #endif /* GFX_CONTEXT_H */