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