gfx/thebes/gfxContext.h

changeset 0
6474c204b198
     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 */

mercurial