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
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/
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
15 * The Original Code is Oracle Corporation code.
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.
22 * Stuart Parmenter <pavlov@pavlov.net>
23 * Vladimir Vukicevic <vladimir@pobox.com>
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.
37 * ***** END LICENSE BLOCK ***** */
44 #include "gfxASurface.h"
48 #include "gfxMatrix.h"
49 #include "gfxPattern.h"
52 typedef struct _cairo cairo_t
;
55 * This is the main class for doing actual drawing. It is initialized using
56 * a surface and can be drawn on. It manages various state information like
57 * a current transformation matrix (CTM), a current path, current color,
60 * All drawing happens by creating a path and then stroking or filling it.
61 * The functions like Rectangle and Arc do not do any drawing themselves.
62 * When a path is drawn (stroked or filled), it is filled/stroked with a
63 * pattern set by SetPattern, SetColor or SetSource.
65 * Note that the gfxContext takes coordinates in device pixels,
66 * as opposed to app units.
68 class THEBES_API gfxContext
{
69 THEBES_INLINE_DECL_REFCOUNTING(gfxContext
)
73 * Initialize this context from a surface.
75 gfxContext(gfxASurface
*surface
);
79 * Return the surface that this gfxContext was created with
81 gfxASurface
*OriginalSurface();
84 * Return the current transparency group target, if any, along
85 * with its device offsets from the top. If no group is
86 * active, returns the surface the gfxContext was created with,
89 already_AddRefed
<gfxASurface
> CurrentSurface(gfxFloat
*dx
, gfxFloat
*dy
);
90 already_AddRefed
<gfxASurface
> CurrentSurface() {
91 return CurrentSurface(NULL
, NULL
);
95 * Return the raw cairo_t object.
96 * XXX this should go away at some point.
98 cairo_t
*GetCairo() { return mCairo
; }
101 * Returns true if the cairo context is in an error state.
108 // XXX document exactly what bits are saved
117 * Stroke the current path using the current settings (such as line
119 * A path is set up using functions such as Line, Rectangle and Arc.
121 * Does not consume the current path.
125 * Fill the current path according to the current settings.
127 * Does not consume the current path.
132 * Forgets the current path.
137 * Closes the path, i.e. connects the last drawn point to the first one.
139 * Filling a path will implicitly close it.
144 * Copies the current path and returns the copy.
146 already_AddRefed
<gfxPath
> CopyPath() const;
149 * Appends the given path to the current path.
151 void AppendPath(gfxPath
* path
);
154 * Moves the pen to a new point without drawing a line.
156 void MoveTo(const gfxPoint
& pt
);
159 * Creates a new subpath starting at the current point.
160 * Equivalent to MoveTo(CurrentPoint()).
165 * Returns the current point in the current path.
167 gfxPoint
CurrentPoint() const;
170 * Draws a line from the current point to pt.
174 void LineTo(const gfxPoint
& pt
);
177 * Draws a cubic Bézier curve with control points pt1, pt2 and pt3.
179 void CurveTo(const gfxPoint
& pt1
, const gfxPoint
& pt2
, const gfxPoint
& pt3
);
182 * Draws a quadratic Bézier curve with control points pt1, pt2 and pt3.
184 void QuadraticCurveTo(const gfxPoint
& pt1
, const gfxPoint
& pt2
);
187 * Draws a clockwise arc (i.e. a circle segment).
188 * @param center The center of the circle
189 * @param radius The radius of the circle
190 * @param angle1 Starting angle for the segment
191 * @param angle2 Ending angle
193 void Arc(const gfxPoint
& center
, gfxFloat radius
,
194 gfxFloat angle1
, gfxFloat angle2
);
197 * Draws a counter-clockwise arc (i.e. a circle segment).
198 * @param center The center of the circle
199 * @param radius The radius of the circle
200 * @param angle1 Starting angle for the segment
201 * @param angle2 Ending angle
204 void NegativeArc(const gfxPoint
& center
, gfxFloat radius
,
205 gfxFloat angle1
, gfxFloat angle2
);
209 * Draws a line from start to end.
211 void Line(const gfxPoint
& start
, const gfxPoint
& end
); // XXX snapToPixels option?
214 * Draws the rectangle given by rect.
215 * @param snapToPixels ?
217 void Rectangle(const gfxRect
& rect
, PRBool snapToPixels
= PR_FALSE
);
220 * Draw an ellipse at the center corner with the given dimensions.
221 * It extends dimensions.width / 2.0 in the horizontal direction
222 * from the center, and dimensions.height / 2.0 in the vertical
225 void Ellipse(const gfxPoint
& center
, const gfxSize
& dimensions
);
228 * Draw a polygon from the given points
230 void Polygon(const gfxPoint
*points
, PRUint32 numPoints
);
233 * Draw a rounded rectangle, with the given outer rect and
234 * corners. The corners specify the radii of the two axes of an
235 * ellipse (the horizontal and vertical directions given by the
236 * width and height, respectively). By default the ellipse is
237 * drawn in a clockwise direction; if draw_clockwise is PR_FALSE,
238 * then it's drawn counterclockwise.
240 void RoundedRectangle(const gfxRect
& rect
,
241 const gfxCornerSizes
& corners
,
242 PRBool draw_clockwise
= PR_TRUE
);
245 ** Transformation Matrix manipulation
249 * Adds a translation to the current matrix. This translation takes place
250 * before the previously set transformations.
252 void Translate(const gfxPoint
& pt
);
255 * Adds a scale to the current matrix. This scaling takes place before the
256 * previously set transformations.
258 void Scale(gfxFloat x
, gfxFloat y
);
261 * Adds a rotation around the origin to the current matrix. This rotation
262 * takes place before the previously set transformations.
264 * @param angle The angle in radians.
266 void Rotate(gfxFloat angle
);
269 * Post-multiplies 'other' onto the current CTM, i.e. this
270 * matrix's transformation will take place before the previously set
273 void Multiply(const gfxMatrix
& other
);
276 * Replaces the current transformation matrix with matrix.
278 void SetMatrix(const gfxMatrix
& matrix
);
281 * Sets the transformation matrix to the identity matrix.
283 void IdentityMatrix();
286 * Returns the current transformation matrix.
288 gfxMatrix
CurrentMatrix() const;
291 * Converts a point from device to user coordinates using the inverse
292 * transformation matrix.
294 gfxPoint
DeviceToUser(const gfxPoint
& point
) const;
297 * Converts a size from device to user coordinates. This does not apply
298 * translation components of the matrix.
300 gfxSize
DeviceToUser(const gfxSize
& size
) const;
303 * Converts a rectangle from device to user coordinates; this has the
304 * same effect as using DeviceToUser on both the rectangle's point and
307 gfxRect
DeviceToUser(const gfxRect
& rect
) const;
310 * Converts a point from user to device coordinates using the inverse
311 * transformation matrix.
313 gfxPoint
UserToDevice(const gfxPoint
& point
) const;
316 * Converts a size from user to device coordinates. This does not apply
317 * translation components of the matrix.
319 gfxSize
UserToDevice(const gfxSize
& size
) const;
322 * Converts a rectangle from user to device coordinates; this has the
323 * same effect as using UserToDevice on both the rectangle's point and
326 gfxRect
UserToDevice(const gfxRect
& rect
) const;
329 * Takes the given rect and tries to align it to device pixels. If
330 * this succeeds, the method will return PR_TRUE, and the rect will
331 * be in device coordinates (already transformed by the CTM). If it
332 * fails, the method will return PR_FALSE, and the rect will not be
335 * If ignoreScale is PR_TRUE, then snapping will take place even if
336 * the CTM has a scale applied. Snapping never takes place if
337 * there is a rotation in the CTM.
339 PRBool
UserToDevicePixelSnapped(gfxRect
& rect
, PRBool ignoreScale
= PR_FALSE
) const;
342 * Takes the given point and tries to align it to device pixels. If
343 * this succeeds, the method will return PR_TRUE, and the point will
344 * be in device coordinates (already transformed by the CTM). If it
345 * fails, the method will return PR_FALSE, and the point will not be
348 * If ignoreScale is PR_TRUE, then snapping will take place even if
349 * the CTM has a scale applied. Snapping never takes place if
350 * there is a rotation in the CTM.
352 PRBool
UserToDevicePixelSnapped(gfxPoint
& pt
, PRBool ignoreScale
= PR_FALSE
) const;
355 * Attempts to pixel snap the rectangle, add it to the current
356 * path, and to set pattern as the current painting source. This
357 * should be used for drawing filled pixel-snapped rectangles (like
358 * images), because the CTM at the time of the SetPattern call needs
359 * to have a snapped translation, or you get smeared images.
361 void PixelSnappedRectangleAndSetPattern(const gfxRect
& rect
, gfxPattern
*pattern
);
368 * Set a solid color to use for drawing. This color is in the device color space
369 * and is not transformed.
371 void SetDeviceColor(const gfxRGBA
& c
);
374 * Gets the current color. It's returned in the device color space.
375 * returns PR_FALSE if there is something other than a color
376 * set as the current source (pattern, surface, etc)
378 PRBool
GetDeviceColor(gfxRGBA
& c
);
381 * Set a solid color in the sRGB color space to use for drawing.
382 * If CMS is not enabled, the color is treated as a device-space color
383 * and this call is identical to SetDeviceColor().
385 void SetColor(const gfxRGBA
& c
);
388 * Uses a surface for drawing. This is a shorthand for creating a
389 * pattern and setting it.
391 * @param offset from the source surface, to use only part of it.
392 * May need to make it negative.
394 void SetSource(gfxASurface
*surface
, const gfxPoint
& offset
= gfxPoint(0.0, 0.0));
397 * Uses a pattern for drawing.
399 void SetPattern(gfxPattern
*pattern
);
402 * Get the source pattern (solid color, normal pattern, surface, etc)
404 already_AddRefed
<gfxPattern
> GetPattern();
410 * Paints the current source surface/pattern everywhere in the current
413 void Paint(gfxFloat alpha
= 1.0);
416 ** Painting with a Mask
419 * Like Paint, except that it only draws the source where pattern is
422 void Mask(gfxPattern
*pattern
);
425 * Shorthand for creating a pattern and calling the pattern-taking
428 void Mask(gfxASurface
*surface
, const gfxPoint
& offset
= gfxPoint(0.0, 0.0));
435 * Creates a new path with a rectangle from 0,0 to size.w,size.h
436 * and calls cairo_fill.
438 void DrawSurface(gfxASurface
*surface
, const gfxSize
& size
);
450 void SetDash(gfxLineType ltype
);
451 void SetDash(gfxFloat
*dashes
, int ndash
, gfxFloat offset
);
452 //void getDash() const;
455 * Sets the line width that's used for line drawing.
457 void SetLineWidth(gfxFloat width
);
460 * Returns the currently set line width.
464 gfxFloat
CurrentLineWidth() const;
466 enum GraphicsLineCap
{
472 * Sets the line caps, i.e. how line endings are drawn.
474 void SetLineCap(GraphicsLineCap cap
);
475 GraphicsLineCap
CurrentLineCap() const;
477 enum GraphicsLineJoin
{
483 * Sets the line join, i.e. how the connection between two lines is
486 void SetLineJoin(GraphicsLineJoin join
);
487 GraphicsLineJoin
CurrentLineJoin() const;
489 void SetMiterLimit(gfxFloat limit
);
490 gfxFloat
CurrentMiterLimit() const;
500 void SetFillRule(FillRule rule
);
501 FillRule
CurrentFillRule() const;
504 ** Operators and Rendering control
507 // define enum for operators (clear, src, dst, etc)
508 enum GraphicsOperator
{
528 * Sets the operator used for all further drawing. The operator affects
529 * how drawing something will modify the destination. For example, the
530 * OVER operator will do alpha blending of source and destination, while
531 * SOURCE will replace the destination with the source.
533 * Note that if the flag FLAG_SIMPLIFY_OPERATORS is set on this
534 * gfxContext, the actual operator set might change for optimization
535 * purposes. Check the comments below around that flag.
537 void SetOperator(GraphicsOperator op
);
538 GraphicsOperator
CurrentOperator() const;
541 * MODE_ALIASED means that only pixels whose centers are in the drawn area
542 * should be modified, and they should be modified to take the value drawn
543 * at the pixel center.
549 void SetAntialiasMode(AntialiasMode mode
);
550 AntialiasMode
CurrentAntialiasMode() const;
557 * Clips all further drawing to the current path.
558 * This does not consume the current path.
563 * Undoes any clipping. Further drawings will only be restricted by the
564 * surface dimensions.
569 * Helper functions that will create a rect path and call Clip().
570 * Any current path will be destroyed by these functions!
572 void Clip(const gfxRect
& rect
); // will clip to a rect
575 * This will ensure that the surface actually has its clip set.
576 * Useful if you are doing native drawing.
578 void UpdateSurfaceClip();
581 * This will return the current bounds of the clip region.
583 gfxRect
GetClipExtents();
588 void PushGroup(gfxASurface::gfxContentType content
= gfxASurface::CONTENT_COLOR
);
589 already_AddRefed
<gfxPattern
> PopGroup();
590 void PopGroupToSource();
593 ** Hit Testing - check if given point is in the current path
595 PRBool
PointInFill(const gfxPoint
& pt
);
596 PRBool
PointInStroke(const gfxPoint
& pt
);
599 ** Extents - returns user space extent of current path
601 gfxRect
GetUserPathExtent();
602 gfxRect
GetUserFillExtent();
603 gfxRect
GetUserStrokeExtent();
606 ** Obtaining a "flattened" path - path converted to all line segments
608 already_AddRefed
<gfxFlattenedPath
> GetFlattenedPath();
615 /* If this flag is set, operators other than CLEAR, SOURCE, or
616 * OVER will be converted to OVER before being sent to cairo.
618 * This is most useful with a printing surface, where
619 * operators such as ADD are used to avoid seams for on-screen
620 * display, but where such errors aren't noticable in print.
621 * This approach is currently used in border rendering.
623 * However, when printing complex renderings such as SVG,
624 * care should be taken to clear this flag.
626 FLAG_SIMPLIFY_OPERATORS
= (1 << 0),
628 * When this flag is set, snapping to device pixels is disabled.
629 * It simply never does anything.
631 FLAG_DISABLE_SNAPPING
= (1 << 1),
633 * When this flag is set, rendering through this context
634 * is destined to be (eventually) drawn on the screen. It can be
635 * useful to know this, for example so that windowed plugins are
636 * not unnecessarily rendered (since they will already appear
637 * on the screen, thanks to their windows).
639 FLAG_DESTINED_FOR_SCREEN
= (1 << 2)
642 void SetFlag(PRInt32 aFlag
) { mFlags
|= aFlag
; }
643 void ClearFlag(PRInt32 aFlag
) { mFlags
&= ~aFlag
; }
644 PRInt32
GetFlags() const { return mFlags
; }
648 nsRefPtr
<gfxASurface
> mSurface
;
654 * Sentry helper class for functions with multiple return points that need to
655 * call Save() on a gfxContext and have Restore() called automatically on the
656 * gfxContext before they return.
658 class THEBES_API gfxContextAutoSaveRestore
661 gfxContextAutoSaveRestore() : mContext(nsnull
) {}
663 gfxContextAutoSaveRestore(gfxContext
*aContext
) : mContext(aContext
) {
667 ~gfxContextAutoSaveRestore() {
673 void SetContext(gfxContext
*aContext
) {
674 NS_ASSERTION(!mContext
, "Not going to call Restore() on some context!!!");
680 gfxContext
*mContext
;
684 * Sentry helper class for functions with multiple return points that need to
685 * back up the current path of a context and have it automatically restored
686 * before they return. This class assumes that the transformation matrix will
687 * be the same when Save and Restore are called. The calling function must
688 * ensure that this is the case or the path will be copied incorrectly.
690 class THEBES_API gfxContextPathAutoSaveRestore
693 gfxContextPathAutoSaveRestore() : mContext(nsnull
) {}
695 gfxContextPathAutoSaveRestore(gfxContext
*aContext
, PRBool aSave
= PR_TRUE
) : mContext(aContext
)
701 ~gfxContextPathAutoSaveRestore()
706 void SetContext(gfxContext
*aContext
, PRBool aSave
= PR_TRUE
)
714 * If a path is already saved, does nothing. Else copies the current path
715 * so that it may be restored.
719 if (!mPath
&& mContext
) {
720 mPath
= mContext
->CopyPath();
725 * If no path is saved, does nothing. Else replaces the context's path with
726 * a copy of the saved one, and clears the saved path.
732 mContext
->AppendPath(mPath
);
738 gfxContext
*mContext
;
740 nsRefPtr
<gfxPath
> mPath
;
744 * Sentry helper class for functions with multiple return points that need to
745 * back up the current matrix of a context and have it automatically restored
746 * before they return.
748 class THEBES_API gfxContextMatrixAutoSaveRestore
751 gfxContextMatrixAutoSaveRestore(gfxContext
*aContext
) :
752 mContext(aContext
), mMatrix(aContext
->CurrentMatrix())
756 ~gfxContextMatrixAutoSaveRestore()
758 mContext
->SetMatrix(mMatrix
);
761 const gfxMatrix
& Matrix()
767 gfxContext
*mContext
;
771 #endif /* GFX_CONTEXT_H */