1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/thebes/gfxContext.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,995 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef GFX_CONTEXT_H 1.10 +#define GFX_CONTEXT_H 1.11 + 1.12 +#include "gfxTypes.h" 1.13 + 1.14 +#include "gfxASurface.h" 1.15 +#include "gfxPoint.h" 1.16 +#include "gfxRect.h" 1.17 +#include "gfxMatrix.h" 1.18 +#include "gfxPattern.h" 1.19 +#include "gfxPath.h" 1.20 +#include "nsTArray.h" 1.21 +#include "nsAutoPtr.h" 1.22 + 1.23 +#include "mozilla/gfx/2D.h" 1.24 + 1.25 +typedef struct _cairo cairo_t; 1.26 +struct GlyphBufferAzure; 1.27 +template <typename T> class FallibleTArray; 1.28 + 1.29 +/** 1.30 + * This is the main class for doing actual drawing. It is initialized using 1.31 + * a surface and can be drawn on. It manages various state information like 1.32 + * a current transformation matrix (CTM), a current path, current color, 1.33 + * etc. 1.34 + * 1.35 + * All drawing happens by creating a path and then stroking or filling it. 1.36 + * The functions like Rectangle and Arc do not do any drawing themselves. 1.37 + * When a path is drawn (stroked or filled), it is filled/stroked with a 1.38 + * pattern set by SetPattern, SetColor or SetSource. 1.39 + * 1.40 + * Note that the gfxContext takes coordinates in device pixels, 1.41 + * as opposed to app units. 1.42 + */ 1.43 +class gfxContext { 1.44 + NS_INLINE_DECL_REFCOUNTING(gfxContext) 1.45 + 1.46 +public: 1.47 + /** 1.48 + * Initialize this context from a surface. 1.49 + */ 1.50 + gfxContext(gfxASurface *surface); 1.51 + 1.52 + /** 1.53 + * Initialize this context from a DrawTarget. 1.54 + * Strips any transform from aTarget. 1.55 + * aTarget will be flushed in the gfxContext's destructor. 1.56 + */ 1.57 + gfxContext(mozilla::gfx::DrawTarget *aTarget, 1.58 + const mozilla::gfx::Point& aDeviceOffset = mozilla::gfx::Point()); 1.59 + 1.60 + ~gfxContext(); 1.61 + 1.62 + /** 1.63 + * Create a new gfxContext wrapping aTarget and preserving aTarget's 1.64 + * transform. Note that the transform is moved from aTarget to the resulting 1.65 + * gfxContext, aTarget will no longer have its transform. 1.66 + */ 1.67 + static already_AddRefed<gfxContext> ContextForDrawTarget(mozilla::gfx::DrawTarget* aTarget); 1.68 + 1.69 + /** 1.70 + * Return the surface that this gfxContext was created with 1.71 + */ 1.72 + gfxASurface *OriginalSurface(); 1.73 + 1.74 + /** 1.75 + * Return the current transparency group target, if any, along 1.76 + * with its device offsets from the top. If no group is 1.77 + * active, returns the surface the gfxContext was created with, 1.78 + * and 0,0 in dx,dy. 1.79 + */ 1.80 + already_AddRefed<gfxASurface> CurrentSurface(gfxFloat *dx, gfxFloat *dy); 1.81 + already_AddRefed<gfxASurface> CurrentSurface() { 1.82 + return CurrentSurface(nullptr, nullptr); 1.83 + } 1.84 + 1.85 + /** 1.86 + * Return the raw cairo_t object. 1.87 + * XXX this should go away at some point. 1.88 + */ 1.89 + cairo_t *GetCairo(); 1.90 + 1.91 + mozilla::gfx::DrawTarget *GetDrawTarget() { return mDT; } 1.92 + 1.93 + /** 1.94 + * Returns true if the cairo context is in an error state. 1.95 + */ 1.96 + bool HasError(); 1.97 + 1.98 + /** 1.99 + ** State 1.100 + **/ 1.101 + // XXX document exactly what bits are saved 1.102 + void Save(); 1.103 + void Restore(); 1.104 + 1.105 + /** 1.106 + ** Paths & Drawing 1.107 + **/ 1.108 + 1.109 + /** 1.110 + * Stroke the current path using the current settings (such as line 1.111 + * width and color). 1.112 + * A path is set up using functions such as Line, Rectangle and Arc. 1.113 + * 1.114 + * Does not consume the current path. 1.115 + */ 1.116 + void Stroke(); 1.117 + /** 1.118 + * Fill the current path according to the current settings. 1.119 + * 1.120 + * Does not consume the current path. 1.121 + */ 1.122 + void Fill(); 1.123 + 1.124 + /** 1.125 + * Fill the current path according to the current settings and 1.126 + * with |aOpacity|. 1.127 + * 1.128 + * Does not consume the current path. 1.129 + */ 1.130 + void FillWithOpacity(gfxFloat aOpacity); 1.131 + 1.132 + /** 1.133 + * Forgets the current path. 1.134 + */ 1.135 + void NewPath(); 1.136 + 1.137 + /** 1.138 + * Closes the path, i.e. connects the last drawn point to the first one. 1.139 + * 1.140 + * Filling a path will implicitly close it. 1.141 + */ 1.142 + void ClosePath(); 1.143 + 1.144 + /** 1.145 + * Copies the current path and returns the copy. 1.146 + */ 1.147 + already_AddRefed<gfxPath> CopyPath(); 1.148 + 1.149 + /** 1.150 + * Appends the given path to the current path. 1.151 + */ 1.152 + void SetPath(gfxPath* path); 1.153 + 1.154 + /** 1.155 + * Moves the pen to a new point without drawing a line. 1.156 + */ 1.157 + void MoveTo(const gfxPoint& pt); 1.158 + 1.159 + /** 1.160 + * Creates a new subpath starting at the current point. 1.161 + * Equivalent to MoveTo(CurrentPoint()). 1.162 + */ 1.163 + void NewSubPath(); 1.164 + 1.165 + /** 1.166 + * Returns the current point in the current path. 1.167 + */ 1.168 + gfxPoint CurrentPoint(); 1.169 + 1.170 + /** 1.171 + * Draws a line from the current point to pt. 1.172 + * 1.173 + * @see MoveTo 1.174 + */ 1.175 + void LineTo(const gfxPoint& pt); 1.176 + 1.177 + /** 1.178 + * Draws a cubic Bézier curve with control points pt1, pt2 and pt3. 1.179 + */ 1.180 + void CurveTo(const gfxPoint& pt1, const gfxPoint& pt2, const gfxPoint& pt3); 1.181 + 1.182 + /** 1.183 + * Draws a quadratic Bézier curve with control points pt1, pt2 and pt3. 1.184 + */ 1.185 + void QuadraticCurveTo(const gfxPoint& pt1, const gfxPoint& pt2); 1.186 + 1.187 + /** 1.188 + * Draws a clockwise arc (i.e. a circle segment). 1.189 + * @param center The center of the circle 1.190 + * @param radius The radius of the circle 1.191 + * @param angle1 Starting angle for the segment 1.192 + * @param angle2 Ending angle 1.193 + */ 1.194 + void Arc(const gfxPoint& center, gfxFloat radius, 1.195 + gfxFloat angle1, gfxFloat angle2); 1.196 + 1.197 + /** 1.198 + * Draws a counter-clockwise arc (i.e. a circle segment). 1.199 + * @param center The center of the circle 1.200 + * @param radius The radius of the circle 1.201 + * @param angle1 Starting angle for the segment 1.202 + * @param angle2 Ending angle 1.203 + */ 1.204 + 1.205 + void NegativeArc(const gfxPoint& center, gfxFloat radius, 1.206 + gfxFloat angle1, gfxFloat angle2); 1.207 + 1.208 + // path helpers 1.209 + /** 1.210 + * Draws a line from start to end. 1.211 + */ 1.212 + void Line(const gfxPoint& start, const gfxPoint& end); // XXX snapToPixels option? 1.213 + 1.214 + /** 1.215 + * Draws the rectangle given by rect. 1.216 + * @param snapToPixels ? 1.217 + */ 1.218 + void Rectangle(const gfxRect& rect, bool snapToPixels = false); 1.219 + void SnappedRectangle(const gfxRect& rect) { return Rectangle(rect, true); } 1.220 + 1.221 + /** 1.222 + * Draw an ellipse at the center corner with the given dimensions. 1.223 + * It extends dimensions.width / 2.0 in the horizontal direction 1.224 + * from the center, and dimensions.height / 2.0 in the vertical 1.225 + * direction. 1.226 + */ 1.227 + void Ellipse(const gfxPoint& center, const gfxSize& dimensions); 1.228 + 1.229 + /** 1.230 + * Draw a polygon from the given points 1.231 + */ 1.232 + void Polygon(const gfxPoint *points, uint32_t numPoints); 1.233 + 1.234 + /* 1.235 + * Draw a rounded rectangle, with the given outer rect and 1.236 + * corners. The corners specify the radii of the two axes of an 1.237 + * ellipse (the horizontal and vertical directions given by the 1.238 + * width and height, respectively). By default the ellipse is 1.239 + * drawn in a clockwise direction; if draw_clockwise is false, 1.240 + * then it's drawn counterclockwise. 1.241 + */ 1.242 + void RoundedRectangle(const gfxRect& rect, 1.243 + const gfxCornerSizes& corners, 1.244 + bool draw_clockwise = true); 1.245 + 1.246 + /** 1.247 + ** Transformation Matrix manipulation 1.248 + **/ 1.249 + 1.250 + /** 1.251 + * Adds a translation to the current matrix. This translation takes place 1.252 + * before the previously set transformations. 1.253 + */ 1.254 + void Translate(const gfxPoint& pt); 1.255 + 1.256 + /** 1.257 + * Adds a scale to the current matrix. This scaling takes place before the 1.258 + * previously set transformations. 1.259 + */ 1.260 + void Scale(gfxFloat x, gfxFloat y); 1.261 + 1.262 + /** 1.263 + * Adds a rotation around the origin to the current matrix. This rotation 1.264 + * takes place before the previously set transformations. 1.265 + * 1.266 + * @param angle The angle in radians. 1.267 + */ 1.268 + void Rotate(gfxFloat angle); 1.269 + 1.270 + /** 1.271 + * Post-multiplies 'other' onto the current CTM, i.e. this 1.272 + * matrix's transformation will take place before the previously set 1.273 + * transformations. 1.274 + */ 1.275 + void Multiply(const gfxMatrix& other); 1.276 + /** 1.277 + * As "Multiply", but also nudges any entries in the resulting matrix that 1.278 + * are close to an integer to that integer, to correct for 1.279 + * compounded rounding errors. 1.280 + */ 1.281 + void MultiplyAndNudgeToIntegers(const gfxMatrix& other); 1.282 + 1.283 + /** 1.284 + * Replaces the current transformation matrix with matrix. 1.285 + */ 1.286 + void SetMatrix(const gfxMatrix& matrix); 1.287 + 1.288 + /** 1.289 + * Sets the transformation matrix to the identity matrix. 1.290 + */ 1.291 + void IdentityMatrix(); 1.292 + 1.293 + /** 1.294 + * Returns the current transformation matrix. 1.295 + */ 1.296 + gfxMatrix CurrentMatrix() const; 1.297 + 1.298 + /** 1.299 + * Snap components of the current matrix that are close to integers 1.300 + * to integers. In particular, components that are integral when 1.301 + * converted to single precision are set to those integers. 1.302 + */ 1.303 + void NudgeCurrentMatrixToIntegers(); 1.304 + 1.305 + /** 1.306 + * Converts a point from device to user coordinates using the inverse 1.307 + * transformation matrix. 1.308 + */ 1.309 + gfxPoint DeviceToUser(const gfxPoint& point) const; 1.310 + 1.311 + /** 1.312 + * Converts a size from device to user coordinates. This does not apply 1.313 + * translation components of the matrix. 1.314 + */ 1.315 + gfxSize DeviceToUser(const gfxSize& size) const; 1.316 + 1.317 + /** 1.318 + * Converts a rectangle from device to user coordinates; this has the 1.319 + * same effect as using DeviceToUser on both the rectangle's point and 1.320 + * size. 1.321 + */ 1.322 + gfxRect DeviceToUser(const gfxRect& rect) const; 1.323 + 1.324 + /** 1.325 + * Converts a point from user to device coordinates using the transformation 1.326 + * matrix. 1.327 + */ 1.328 + gfxPoint UserToDevice(const gfxPoint& point) const; 1.329 + 1.330 + /** 1.331 + * Converts a size from user to device coordinates. This does not apply 1.332 + * translation components of the matrix. 1.333 + */ 1.334 + gfxSize UserToDevice(const gfxSize& size) const; 1.335 + 1.336 + /** 1.337 + * Converts a rectangle from user to device coordinates. The 1.338 + * resulting rectangle is the minimum device-space rectangle that 1.339 + * encloses the user-space rectangle given. 1.340 + */ 1.341 + gfxRect UserToDevice(const gfxRect& rect) const; 1.342 + 1.343 + /** 1.344 + * Takes the given rect and tries to align it to device pixels. If 1.345 + * this succeeds, the method will return true, and the rect will 1.346 + * be in device coordinates (already transformed by the CTM). If it 1.347 + * fails, the method will return false, and the rect will not be 1.348 + * changed. 1.349 + * 1.350 + * If ignoreScale is true, then snapping will take place even if 1.351 + * the CTM has a scale applied. Snapping never takes place if 1.352 + * there is a rotation in the CTM. 1.353 + */ 1.354 + bool UserToDevicePixelSnapped(gfxRect& rect, bool ignoreScale = false) const; 1.355 + 1.356 + /** 1.357 + * Takes the given point and tries to align it to device pixels. If 1.358 + * this succeeds, the method will return true, and the point will 1.359 + * be in device coordinates (already transformed by the CTM). If it 1.360 + * fails, the method will return false, and the point will not be 1.361 + * changed. 1.362 + * 1.363 + * If ignoreScale is true, then snapping will take place even if 1.364 + * the CTM has a scale applied. Snapping never takes place if 1.365 + * there is a rotation in the CTM. 1.366 + */ 1.367 + bool UserToDevicePixelSnapped(gfxPoint& pt, bool ignoreScale = false) const; 1.368 + 1.369 + /** 1.370 + * Attempts to pixel snap the rectangle, add it to the current 1.371 + * path, and to set pattern as the current painting source. This 1.372 + * should be used for drawing filled pixel-snapped rectangles (like 1.373 + * images), because the CTM at the time of the SetPattern call needs 1.374 + * to have a snapped translation, or you get smeared images. 1.375 + */ 1.376 + void PixelSnappedRectangleAndSetPattern(const gfxRect& rect, gfxPattern *pattern); 1.377 + 1.378 + /** 1.379 + ** Painting sources 1.380 + **/ 1.381 + 1.382 + /** 1.383 + * Set a solid color to use for drawing. This color is in the device color space 1.384 + * and is not transformed. 1.385 + */ 1.386 + void SetDeviceColor(const gfxRGBA& c); 1.387 + 1.388 + /** 1.389 + * Gets the current color. It's returned in the device color space. 1.390 + * returns false if there is something other than a color 1.391 + * set as the current source (pattern, surface, etc) 1.392 + */ 1.393 + bool GetDeviceColor(gfxRGBA& c); 1.394 + 1.395 + /** 1.396 + * Set a solid color in the sRGB color space to use for drawing. 1.397 + * If CMS is not enabled, the color is treated as a device-space color 1.398 + * and this call is identical to SetDeviceColor(). 1.399 + */ 1.400 + void SetColor(const gfxRGBA& c); 1.401 + 1.402 + /** 1.403 + * Uses a surface for drawing. This is a shorthand for creating a 1.404 + * pattern and setting it. 1.405 + * 1.406 + * @param offset from the source surface, to use only part of it. 1.407 + * May need to make it negative. 1.408 + */ 1.409 + void SetSource(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0)); 1.410 + 1.411 + /** 1.412 + * Uses a pattern for drawing. 1.413 + */ 1.414 + void SetPattern(gfxPattern *pattern); 1.415 + 1.416 + /** 1.417 + * Get the source pattern (solid color, normal pattern, surface, etc) 1.418 + */ 1.419 + already_AddRefed<gfxPattern> GetPattern(); 1.420 + 1.421 + /** 1.422 + ** Painting 1.423 + **/ 1.424 + /** 1.425 + * Paints the current source surface/pattern everywhere in the current 1.426 + * clip region. 1.427 + */ 1.428 + void Paint(gfxFloat alpha = 1.0); 1.429 + 1.430 + /** 1.431 + ** Painting with a Mask 1.432 + **/ 1.433 + /** 1.434 + * Like Paint, except that it only draws the source where pattern is 1.435 + * non-transparent. 1.436 + */ 1.437 + void Mask(gfxPattern *pattern); 1.438 + 1.439 + /** 1.440 + * Shorthand for creating a pattern and calling the pattern-taking 1.441 + * variant of Mask. 1.442 + */ 1.443 + void Mask(gfxASurface *surface, const gfxPoint& offset = gfxPoint(0.0, 0.0)); 1.444 + 1.445 + void Mask(mozilla::gfx::SourceSurface *surface, const mozilla::gfx::Point& offset = mozilla::gfx::Point()); 1.446 + 1.447 + /** 1.448 + ** Shortcuts 1.449 + **/ 1.450 + 1.451 + /** 1.452 + * Creates a new path with a rectangle from 0,0 to size.w,size.h 1.453 + * and calls cairo_fill. 1.454 + */ 1.455 + void DrawSurface(gfxASurface *surface, const gfxSize& size); 1.456 + 1.457 + /** 1.458 + ** Line Properties 1.459 + **/ 1.460 + 1.461 + typedef enum { 1.462 + gfxLineSolid, 1.463 + gfxLineDashed, 1.464 + gfxLineDotted 1.465 + } gfxLineType; 1.466 + 1.467 + void SetDash(gfxLineType ltype); 1.468 + void SetDash(gfxFloat *dashes, int ndash, gfxFloat offset); 1.469 + // Return true if dashing is set, false if it's not enabled or the 1.470 + // context is in an error state. |offset| can be nullptr to mean 1.471 + // "don't care". 1.472 + bool CurrentDash(FallibleTArray<gfxFloat>& dashes, gfxFloat* offset) const; 1.473 + // Returns 0.0 if dashing isn't enabled. 1.474 + gfxFloat CurrentDashOffset() const; 1.475 + 1.476 + /** 1.477 + * Sets the line width that's used for line drawing. 1.478 + */ 1.479 + void SetLineWidth(gfxFloat width); 1.480 + 1.481 + /** 1.482 + * Returns the currently set line width. 1.483 + * 1.484 + * @see SetLineWidth 1.485 + */ 1.486 + gfxFloat CurrentLineWidth() const; 1.487 + 1.488 + enum GraphicsLineCap { 1.489 + LINE_CAP_BUTT, 1.490 + LINE_CAP_ROUND, 1.491 + LINE_CAP_SQUARE 1.492 + }; 1.493 + /** 1.494 + * Sets the line caps, i.e. how line endings are drawn. 1.495 + */ 1.496 + void SetLineCap(GraphicsLineCap cap); 1.497 + GraphicsLineCap CurrentLineCap() const; 1.498 + 1.499 + enum GraphicsLineJoin { 1.500 + LINE_JOIN_MITER, 1.501 + LINE_JOIN_ROUND, 1.502 + LINE_JOIN_BEVEL 1.503 + }; 1.504 + /** 1.505 + * Sets the line join, i.e. how the connection between two lines is 1.506 + * drawn. 1.507 + */ 1.508 + void SetLineJoin(GraphicsLineJoin join); 1.509 + GraphicsLineJoin CurrentLineJoin() const; 1.510 + 1.511 + void SetMiterLimit(gfxFloat limit); 1.512 + gfxFloat CurrentMiterLimit() const; 1.513 + 1.514 + /** 1.515 + ** Fill Properties 1.516 + **/ 1.517 + 1.518 + enum FillRule { 1.519 + FILL_RULE_WINDING, 1.520 + FILL_RULE_EVEN_ODD 1.521 + }; 1.522 + void SetFillRule(FillRule rule); 1.523 + FillRule CurrentFillRule() const; 1.524 + 1.525 + /** 1.526 + ** Operators and Rendering control 1.527 + **/ 1.528 + 1.529 + // define enum for operators (clear, src, dst, etc) 1.530 + enum GraphicsOperator { 1.531 + OPERATOR_CLEAR, 1.532 + OPERATOR_SOURCE, 1.533 + 1.534 + OPERATOR_OVER, 1.535 + OPERATOR_IN, 1.536 + OPERATOR_OUT, 1.537 + OPERATOR_ATOP, 1.538 + 1.539 + OPERATOR_DEST, 1.540 + OPERATOR_DEST_OVER, 1.541 + OPERATOR_DEST_IN, 1.542 + OPERATOR_DEST_OUT, 1.543 + OPERATOR_DEST_ATOP, 1.544 + 1.545 + OPERATOR_XOR, 1.546 + OPERATOR_ADD, 1.547 + OPERATOR_SATURATE, 1.548 + 1.549 + OPERATOR_MULTIPLY, 1.550 + OPERATOR_SCREEN, 1.551 + OPERATOR_OVERLAY, 1.552 + OPERATOR_DARKEN, 1.553 + OPERATOR_LIGHTEN, 1.554 + OPERATOR_COLOR_DODGE, 1.555 + OPERATOR_COLOR_BURN, 1.556 + OPERATOR_HARD_LIGHT, 1.557 + OPERATOR_SOFT_LIGHT, 1.558 + OPERATOR_DIFFERENCE, 1.559 + OPERATOR_EXCLUSION, 1.560 + OPERATOR_HUE, 1.561 + OPERATOR_SATURATION, 1.562 + OPERATOR_COLOR, 1.563 + OPERATOR_LUMINOSITY 1.564 + }; 1.565 + /** 1.566 + * Sets the operator used for all further drawing. The operator affects 1.567 + * how drawing something will modify the destination. For example, the 1.568 + * OVER operator will do alpha blending of source and destination, while 1.569 + * SOURCE will replace the destination with the source. 1.570 + * 1.571 + * Note that if the flag FLAG_SIMPLIFY_OPERATORS is set on this 1.572 + * gfxContext, the actual operator set might change for optimization 1.573 + * purposes. Check the comments below around that flag. 1.574 + */ 1.575 + void SetOperator(GraphicsOperator op); 1.576 + GraphicsOperator CurrentOperator() const; 1.577 + 1.578 + /** 1.579 + * MODE_ALIASED means that only pixels whose centers are in the drawn area 1.580 + * should be modified, and they should be modified to take the value drawn 1.581 + * at the pixel center. 1.582 + */ 1.583 + enum AntialiasMode { 1.584 + MODE_ALIASED, 1.585 + MODE_COVERAGE 1.586 + }; 1.587 + void SetAntialiasMode(AntialiasMode mode); 1.588 + AntialiasMode CurrentAntialiasMode() const; 1.589 + 1.590 + /** 1.591 + ** Clipping 1.592 + **/ 1.593 + 1.594 + /** 1.595 + * Clips all further drawing to the current path. 1.596 + * This does not consume the current path. 1.597 + */ 1.598 + void Clip(); 1.599 + 1.600 + /** 1.601 + * Undoes any clipping. Further drawings will only be restricted by the 1.602 + * surface dimensions. 1.603 + */ 1.604 + void ResetClip(); 1.605 + 1.606 + /** 1.607 + * Helper functions that will create a rect path and call Clip(). 1.608 + * Any current path will be destroyed by these functions! 1.609 + */ 1.610 + void Clip(const gfxRect& rect); // will clip to a rect 1.611 + 1.612 + /** 1.613 + * This will ensure that the surface actually has its clip set. 1.614 + * Useful if you are doing native drawing. 1.615 + */ 1.616 + void UpdateSurfaceClip(); 1.617 + 1.618 + /** 1.619 + * This will return the current bounds of the clip region in user 1.620 + * space. 1.621 + */ 1.622 + gfxRect GetClipExtents(); 1.623 + 1.624 + /** 1.625 + * Returns true if the given rectangle is fully contained in the current clip. 1.626 + * This is conservative; it may return false even when the given rectangle is 1.627 + * fully contained by the current clip. 1.628 + */ 1.629 + bool ClipContainsRect(const gfxRect& aRect); 1.630 + 1.631 + /** 1.632 + * Groups 1.633 + */ 1.634 + void PushGroup(gfxContentType content = gfxContentType::COLOR); 1.635 + /** 1.636 + * Like PushGroup, but if the current surface is gfxContentType::COLOR and 1.637 + * content is gfxContentType::COLOR_ALPHA, makes the pushed surface gfxContentType::COLOR 1.638 + * instead and copies the contents of the current surface to the pushed 1.639 + * surface. This is good for pushing opacity groups, since blending the 1.640 + * group back to the current surface with some alpha applied will give 1.641 + * the correct results and using an opaque pushed surface gives better 1.642 + * quality and performance. 1.643 + * This API really only makes sense if you do a PopGroupToSource and 1.644 + * immediate Paint with OPERATOR_OVER. 1.645 + */ 1.646 + void PushGroupAndCopyBackground(gfxContentType content = gfxContentType::COLOR); 1.647 + already_AddRefed<gfxPattern> PopGroup(); 1.648 + void PopGroupToSource(); 1.649 + 1.650 + /** 1.651 + ** Hit Testing - check if given point is in the current path 1.652 + **/ 1.653 + bool PointInFill(const gfxPoint& pt); 1.654 + bool PointInStroke(const gfxPoint& pt); 1.655 + 1.656 + /** 1.657 + ** Extents - returns user space extent of current path 1.658 + **/ 1.659 + gfxRect GetUserPathExtent(); 1.660 + gfxRect GetUserFillExtent(); 1.661 + gfxRect GetUserStrokeExtent(); 1.662 + 1.663 + mozilla::gfx::Point GetDeviceOffset() const; 1.664 + 1.665 + /** 1.666 + ** Flags 1.667 + **/ 1.668 + 1.669 + enum { 1.670 + /* If this flag is set, operators other than CLEAR, SOURCE, or 1.671 + * OVER will be converted to OVER before being sent to cairo. 1.672 + * 1.673 + * This is most useful with a printing surface, where 1.674 + * operators such as ADD are used to avoid seams for on-screen 1.675 + * display, but where such errors aren't noticeable in print. 1.676 + * This approach is currently used in border rendering. 1.677 + * 1.678 + * However, when printing complex renderings such as SVG, 1.679 + * care should be taken to clear this flag. 1.680 + */ 1.681 + FLAG_SIMPLIFY_OPERATORS = (1 << 0), 1.682 + /** 1.683 + * When this flag is set, snapping to device pixels is disabled. 1.684 + * It simply never does anything. 1.685 + */ 1.686 + FLAG_DISABLE_SNAPPING = (1 << 1), 1.687 + /** 1.688 + * Disable copying of backgrounds in PushGroupAndCopyBackground. 1.689 + */ 1.690 + FLAG_DISABLE_COPY_BACKGROUND = (1 << 2) 1.691 + }; 1.692 + 1.693 + void SetFlag(int32_t aFlag) { mFlags |= aFlag; } 1.694 + void ClearFlag(int32_t aFlag) { mFlags &= ~aFlag; } 1.695 + int32_t GetFlags() const { return mFlags; } 1.696 + 1.697 + bool IsCairo() const { return !mDT; } 1.698 + 1.699 + // Work out whether cairo will snap inter-glyph spacing to pixels. 1.700 + void GetRoundOffsetsToPixels(bool *aRoundX, bool *aRoundY); 1.701 + 1.702 +#ifdef MOZ_DUMP_PAINTING 1.703 + /** 1.704 + * Debug functions to encode the current surface as a PNG and export it. 1.705 + */ 1.706 + 1.707 + /** 1.708 + * Writes a binary PNG file. 1.709 + */ 1.710 + void WriteAsPNG(const char* aFile); 1.711 + 1.712 + /** 1.713 + * Write as a PNG encoded Data URL to stdout. 1.714 + */ 1.715 + void DumpAsDataURL(); 1.716 + 1.717 + /** 1.718 + * Copy a PNG encoded Data URL to the clipboard. 1.719 + */ 1.720 + void CopyAsDataURL(); 1.721 +#endif 1.722 + 1.723 + static mozilla::gfx::UserDataKey sDontUseAsSourceKey; 1.724 + 1.725 +private: 1.726 + friend class GeneralPattern; 1.727 + friend struct GlyphBufferAzure; 1.728 + 1.729 + typedef mozilla::gfx::Matrix Matrix; 1.730 + typedef mozilla::gfx::DrawTarget DrawTarget; 1.731 + typedef mozilla::gfx::Color Color; 1.732 + typedef mozilla::gfx::StrokeOptions StrokeOptions; 1.733 + typedef mozilla::gfx::Float Float; 1.734 + typedef mozilla::gfx::Rect Rect; 1.735 + typedef mozilla::gfx::CompositionOp CompositionOp; 1.736 + typedef mozilla::gfx::Path Path; 1.737 + typedef mozilla::gfx::PathBuilder PathBuilder; 1.738 + typedef mozilla::gfx::SourceSurface SourceSurface; 1.739 + 1.740 + struct AzureState { 1.741 + AzureState() 1.742 + : op(mozilla::gfx::CompositionOp::OP_OVER) 1.743 + , opIsClear(false) 1.744 + , color(0, 0, 0, 1.0f) 1.745 + , clipWasReset(false) 1.746 + , fillRule(mozilla::gfx::FillRule::FILL_WINDING) 1.747 + , aaMode(mozilla::gfx::AntialiasMode::SUBPIXEL) 1.748 + , patternTransformChanged(false) 1.749 + {} 1.750 + 1.751 + mozilla::gfx::CompositionOp op; 1.752 + bool opIsClear; 1.753 + Color color; 1.754 + nsRefPtr<gfxPattern> pattern; 1.755 + nsRefPtr<gfxASurface> sourceSurfCairo; 1.756 + mozilla::RefPtr<SourceSurface> sourceSurface; 1.757 + mozilla::gfx::Point sourceSurfaceDeviceOffset; 1.758 + Matrix surfTransform; 1.759 + Matrix transform; 1.760 + struct PushedClip { 1.761 + mozilla::RefPtr<Path> path; 1.762 + Rect rect; 1.763 + Matrix transform; 1.764 + }; 1.765 + nsTArray<PushedClip> pushedClips; 1.766 + nsTArray<Float> dashPattern; 1.767 + bool clipWasReset; 1.768 + mozilla::gfx::FillRule fillRule; 1.769 + StrokeOptions strokeOptions; 1.770 + mozilla::RefPtr<DrawTarget> drawTarget; 1.771 + mozilla::RefPtr<DrawTarget> parentTarget; 1.772 + mozilla::gfx::AntialiasMode aaMode; 1.773 + bool patternTransformChanged; 1.774 + Matrix patternTransform; 1.775 + // This is used solely for using minimal intermediate surface size. 1.776 + mozilla::gfx::Point deviceOffset; 1.777 + }; 1.778 + 1.779 + // This ensures mPath contains a valid path (in user space!) 1.780 + void EnsurePath(); 1.781 + // This ensures mPathBuilder contains a valid PathBuilder (in user space!) 1.782 + void EnsurePathBuilder(); 1.783 + void FillAzure(mozilla::gfx::Float aOpacity); 1.784 + void PushClipsToDT(mozilla::gfx::DrawTarget *aDT); 1.785 + CompositionOp GetOp(); 1.786 + void ChangeTransform(const mozilla::gfx::Matrix &aNewMatrix, bool aUpdatePatternTransform = true); 1.787 + Rect GetAzureDeviceSpaceClipBounds(); 1.788 + Matrix GetDeviceTransform() const; 1.789 + Matrix GetDTTransform() const; 1.790 + void PushNewDT(gfxContentType content); 1.791 + 1.792 + bool mPathIsRect; 1.793 + bool mTransformChanged; 1.794 + Matrix mPathTransform; 1.795 + Rect mRect; 1.796 + mozilla::RefPtr<PathBuilder> mPathBuilder; 1.797 + mozilla::RefPtr<Path> mPath; 1.798 + Matrix mTransform; 1.799 + nsTArray<AzureState> mStateStack; 1.800 + 1.801 + AzureState &CurrentState() { return mStateStack[mStateStack.Length() - 1]; } 1.802 + const AzureState &CurrentState() const { return mStateStack[mStateStack.Length() - 1]; } 1.803 + 1.804 + cairo_t *mCairo; 1.805 + cairo_t *mRefCairo; 1.806 + nsRefPtr<gfxASurface> mSurface; 1.807 + int32_t mFlags; 1.808 + 1.809 + mozilla::RefPtr<DrawTarget> mDT; 1.810 + mozilla::RefPtr<DrawTarget> mOriginalDT; 1.811 +}; 1.812 + 1.813 +/** 1.814 + * Sentry helper class for functions with multiple return points that need to 1.815 + * call Save() on a gfxContext and have Restore() called automatically on the 1.816 + * gfxContext before they return. 1.817 + */ 1.818 +class gfxContextAutoSaveRestore 1.819 +{ 1.820 +public: 1.821 + gfxContextAutoSaveRestore() : mContext(nullptr) {} 1.822 + 1.823 + gfxContextAutoSaveRestore(gfxContext *aContext) : mContext(aContext) { 1.824 + mContext->Save(); 1.825 + } 1.826 + 1.827 + ~gfxContextAutoSaveRestore() { 1.828 + if (mContext) { 1.829 + mContext->Restore(); 1.830 + } 1.831 + } 1.832 + 1.833 + void SetContext(gfxContext *aContext) { 1.834 + NS_ASSERTION(!mContext, "Not going to call Restore() on some context!!!"); 1.835 + mContext = aContext; 1.836 + mContext->Save(); 1.837 + } 1.838 + 1.839 + void Reset(gfxContext *aContext) { 1.840 + // Do the equivalent of destroying and re-creating this object. 1.841 + NS_PRECONDITION(aContext, "must provide a context"); 1.842 + if (mContext) { 1.843 + mContext->Restore(); 1.844 + } 1.845 + mContext = aContext; 1.846 + mContext->Save(); 1.847 + } 1.848 + 1.849 +private: 1.850 + gfxContext *mContext; 1.851 +}; 1.852 + 1.853 +/** 1.854 + * Sentry helper class for functions with multiple return points that need to 1.855 + * back up the current path of a context and have it automatically restored 1.856 + * before they return. This class assumes that the transformation matrix will 1.857 + * be the same when Save and Restore are called. The calling function must 1.858 + * ensure that this is the case or the path will be copied incorrectly. 1.859 + */ 1.860 +class gfxContextPathAutoSaveRestore 1.861 +{ 1.862 +public: 1.863 + gfxContextPathAutoSaveRestore() : mContext(nullptr) {} 1.864 + 1.865 + gfxContextPathAutoSaveRestore(gfxContext *aContext, bool aSave = true) : mContext(aContext) 1.866 + { 1.867 + if (aSave) 1.868 + Save(); 1.869 + } 1.870 + 1.871 + ~gfxContextPathAutoSaveRestore() 1.872 + { 1.873 + Restore(); 1.874 + } 1.875 + 1.876 + void SetContext(gfxContext *aContext, bool aSave = true) 1.877 + { 1.878 + mContext = aContext; 1.879 + if (aSave) 1.880 + Save(); 1.881 + } 1.882 + 1.883 + /** 1.884 + * If a path is already saved, does nothing. Else copies the current path 1.885 + * so that it may be restored. 1.886 + */ 1.887 + void Save() 1.888 + { 1.889 + if (!mPath && mContext) { 1.890 + mPath = mContext->CopyPath(); 1.891 + } 1.892 + } 1.893 + 1.894 + /** 1.895 + * If no path is saved, does nothing. Else replaces the context's path with 1.896 + * a copy of the saved one, and clears the saved path. 1.897 + */ 1.898 + void Restore() 1.899 + { 1.900 + if (mPath) { 1.901 + mContext->SetPath(mPath); 1.902 + mPath = nullptr; 1.903 + } 1.904 + } 1.905 + 1.906 +private: 1.907 + gfxContext *mContext; 1.908 + 1.909 + nsRefPtr<gfxPath> mPath; 1.910 +}; 1.911 + 1.912 +/** 1.913 + * Sentry helper class for functions with multiple return points that need to 1.914 + * back up the current matrix of a context and have it automatically restored 1.915 + * before they return. 1.916 + */ 1.917 +class gfxContextMatrixAutoSaveRestore 1.918 +{ 1.919 +public: 1.920 + gfxContextMatrixAutoSaveRestore() : 1.921 + mContext(nullptr) 1.922 + { 1.923 + } 1.924 + 1.925 + gfxContextMatrixAutoSaveRestore(gfxContext *aContext) : 1.926 + mContext(aContext), mMatrix(aContext->CurrentMatrix()) 1.927 + { 1.928 + } 1.929 + 1.930 + ~gfxContextMatrixAutoSaveRestore() 1.931 + { 1.932 + if (mContext) { 1.933 + mContext->SetMatrix(mMatrix); 1.934 + } 1.935 + } 1.936 + 1.937 + void SetContext(gfxContext *aContext) 1.938 + { 1.939 + NS_ASSERTION(!mContext, "Not going to restore the matrix on some context!"); 1.940 + mContext = aContext; 1.941 + mMatrix = aContext->CurrentMatrix(); 1.942 + } 1.943 + 1.944 + void Restore() 1.945 + { 1.946 + if (mContext) { 1.947 + mContext->SetMatrix(mMatrix); 1.948 + } 1.949 + } 1.950 + 1.951 + const gfxMatrix& Matrix() 1.952 + { 1.953 + MOZ_ASSERT(mContext, "mMatrix doesn't contain a useful matrix"); 1.954 + return mMatrix; 1.955 + } 1.956 + 1.957 +private: 1.958 + gfxContext *mContext; 1.959 + gfxMatrix mMatrix; 1.960 +}; 1.961 + 1.962 + 1.963 +class gfxContextAutoDisableSubpixelAntialiasing { 1.964 +public: 1.965 + gfxContextAutoDisableSubpixelAntialiasing(gfxContext *aContext, bool aDisable) 1.966 + { 1.967 + if (aDisable) { 1.968 + if (aContext->IsCairo()) { 1.969 + mSurface = aContext->CurrentSurface(); 1.970 + if (!mSurface) { 1.971 + return; 1.972 + } 1.973 + mSubpixelAntialiasingEnabled = mSurface->GetSubpixelAntialiasingEnabled(); 1.974 + mSurface->SetSubpixelAntialiasingEnabled(false); 1.975 + } else { 1.976 + mDT = aContext->GetDrawTarget(); 1.977 + 1.978 + mSubpixelAntialiasingEnabled = mDT->GetPermitSubpixelAA(); 1.979 + mDT->SetPermitSubpixelAA(false); 1.980 + } 1.981 + } 1.982 + } 1.983 + ~gfxContextAutoDisableSubpixelAntialiasing() 1.984 + { 1.985 + if (mSurface) { 1.986 + mSurface->SetSubpixelAntialiasingEnabled(mSubpixelAntialiasingEnabled); 1.987 + } else if (mDT) { 1.988 + mDT->SetPermitSubpixelAA(mSubpixelAntialiasingEnabled); 1.989 + } 1.990 + } 1.991 + 1.992 +private: 1.993 + nsRefPtr<gfxASurface> mSurface; 1.994 + mozilla::RefPtr<mozilla::gfx::DrawTarget> mDT; 1.995 + bool mSubpixelAntialiasingEnabled; 1.996 +}; 1.997 + 1.998 +#endif /* GFX_CONTEXT_H */