gfx/thebes/gfxContext.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

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 */

mercurial