DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (5b81998bb7ab)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef MOZILLA_GFX_PATH_CAIRO_H_
#define MOZILLA_GFX_PATH_CAIRO_H_

#include "2D.h"
#include "cairo.h"

namespace mozilla {
namespace gfx {

class DrawTargetCairo;

// A reference to a cairo context that can maintain and set a path.
//
// This class exists to make it possible for us to not construct paths manually
// using cairo_path_t, which in the common case is a speed and memory
// optimization (as the cairo_t maintains the path for us, and we don't have to
// use cairo_append_path). Instead, we can share a cairo_t with a DrawTarget,
// and have it inform us when we need to make a copy of the path.
//
// Exactly one Path* object represents the current path on a given DrawTarget's
// context. That Path* object registers its CairoPathContext with the
// DrawTarget it's associated with. If that DrawTarget is going to change its
// path, it has to tell the CairoPathContext beforehand so the path can be
// saved off.
// The path ownership is transferred to every new instance of CairoPathContext
// in the constructor. We inform the draw target of the new context object,
// which causes us to save off a copy of the path, as we're not going to be
// informed upon changes any more.
// Any transformation on aCtx is not applied to this path, though a path can be
// transformed separately from its context by passing a matrix to the
// constructor.
class CairoPathContext : public RefCounted<CairoPathContext>
{
public:
  // Construct a new empty CairoPathContext that uses the given draw target and
  // its cairo context. Using the existing context may save having to copy the
  // path later.
  CairoPathContext(cairo_t* aCtx, DrawTargetCairo* aDrawTarget);

  // Copy the path.
  CairoPathContext(CairoPathContext& aPathContext);

  ~CairoPathContext();

  // Copy the path on mContext to be the path on aToContext, if they aren't the
  // same. At this point we set the fill rule for the destination context as
  // there is little point in doing this earlier.
  void CopyPathTo(cairo_t* aToContext, Matrix& aTransform);

  // This method must be called by the draw target before it changes the path
  // currently on the cairo context.
  void PathWillChange();

  // This method must be called as the draw target is dying. In this case, we
  // forget our reference to the draw target, and become the only reference to
  // our context.
  void ForgetDrawTarget();

  // Create a duplicate context, and copy this path to that context.
  void DuplicateContextAndPath();

  // Returns true if this CairoPathContext represents path.
  bool ContainsPath(const Path* path);

  cairo_t* GetContext() const { return mContext; }
  DrawTargetCairo* GetDrawTarget() const { return mDrawTarget; }
  operator cairo_t* () const { return mContext; }

private: // data
  cairo_t* mContext;
  // Not a RefPtr to avoid cycles.
  DrawTargetCairo* mDrawTarget;
};

class PathBuilderCairo : public PathBuilder
{
public:
  // Creates a new empty path. It also implicitly takes ownership of aCtx by
  // calling aDrawTarget->SetPathObserver(). Therefore, if the draw target has a
  // path observer, this constructor will cause it to copy out its path.
  PathBuilderCairo(cairo_t* aCtx, DrawTargetCairo* aDrawTarget, FillRule aFillRule);

  // Creates a path builder out of an existing CairoPathContext with a new fill
  // rule and transform.
  PathBuilderCairo(CairoPathContext* aContext, FillRule aFillRule, const Matrix& aTransform = Matrix());

  virtual void MoveTo(const Point &aPoint);
  virtual void LineTo(const Point &aPoint);
  virtual void BezierTo(const Point &aCP1,
                        const Point &aCP2,
                        const Point &aCP3);
  virtual void QuadraticBezierTo(const Point &aCP1,
                                 const Point &aCP2);
  virtual void Close();
  virtual void Arc(const Point &aOrigin, float aRadius, float aStartAngle,
                   float aEndAngle, bool aAntiClockwise = false);
  virtual Point CurrentPoint() const;
  virtual TemporaryRef<Path> Finish();

  TemporaryRef<CairoPathContext> GetPathContext();

private: // data
  void PrepareForWrite();

  RefPtr<CairoPathContext> mPathContext;
  Matrix mTransform;
  FillRule mFillRule;
};

class PathCairo : public Path
{
public:
  PathCairo(CairoPathContext* aPathContex, Matrix& aTransform, FillRule aFillRule);

  virtual BackendType GetBackendType() const { return BACKEND_CAIRO; }

  virtual TemporaryRef<PathBuilder> CopyToBuilder(FillRule aFillRule = FILL_WINDING) const;
  virtual TemporaryRef<PathBuilder> TransformedCopyToBuilder(const Matrix &aTransform,
                                                             FillRule aFillRule = FILL_WINDING) const;

  virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;

  virtual Rect GetBounds(const Matrix &aTransform = Matrix()) const;

  virtual Rect GetStrokedBounds(const StrokeOptions &aStrokeOptions,
                                const Matrix &aTransform = Matrix()) const;

  virtual FillRule GetFillRule() const { return mFillRule; }

  TemporaryRef<CairoPathContext> GetPathContext();

  // Set this path to be the current path for aContext (if it's not already
  // aContext's path). You must pass the draw target associated with the
  // context as aDrawTarget.
  void CopyPathTo(cairo_t* aContext, DrawTargetCairo* aDrawTarget);

private:
  RefPtr<CairoPathContext> mPathContext;
  Matrix mTransform;
  FillRule mFillRule;
};

}
}

#endif /* MOZILLA_GFX_PATH_CAIRO_H_ */