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