зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1320743 - Delete PathCG. r=lsalzman
This commit is contained in:
Родитель
c01505d709
Коммит
bf9abf2c35
|
@ -9,7 +9,6 @@
|
|||
#include "nsDebug.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "ScaledFontMac.h"
|
||||
#include "PathCG.h"
|
||||
#include <dlfcn.h>
|
||||
|
||||
// This is used when we explicitly need CG to draw text to support things such
|
||||
|
|
|
@ -882,15 +882,28 @@ public:
|
|||
SkPath::Iter iter(aPath, true);
|
||||
SkPoint source[4];
|
||||
SkPath::Verb verb;
|
||||
RefPtr<PathBuilderCG> pathBuilder =
|
||||
new PathBuilderCG(GetFillRule(aPath.getFillType()));
|
||||
|
||||
if (!aPath.isFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPath.isEmpty()) {
|
||||
// Weirdly, CoreGraphics clips empty paths as all shown
|
||||
// but empty rects as all clipped. We detect this situation and
|
||||
// workaround it appropriately
|
||||
CGContextClipToRect(mCG, CGRectZero);
|
||||
return;
|
||||
}
|
||||
|
||||
CGMutablePathRef cgPath = CGPathCreateMutable();
|
||||
MOZ_ASSERT(cgPath);
|
||||
|
||||
while ((verb = iter.next(source)) != SkPath::kDone_Verb) {
|
||||
switch (verb) {
|
||||
case SkPath::kMove_Verb:
|
||||
{
|
||||
SkPoint dest = source[0];
|
||||
pathBuilder->MoveTo(Point(dest.fX, dest.fY));
|
||||
CGPathMoveToPoint(cgPath, nullptr, dest.fX, dest.fY);
|
||||
break;
|
||||
}
|
||||
case SkPath::kLine_Verb:
|
||||
|
@ -898,7 +911,8 @@ public:
|
|||
// The first point should be the end point of whatever
|
||||
// verb we got to get here.
|
||||
SkPoint second = source[1];
|
||||
pathBuilder->LineTo(Point(second.fX, second.fY));
|
||||
MOZ_ASSERT(!CGPathIsEmpty(cgPath));
|
||||
CGPathAddLineToPoint(cgPath, nullptr, second.fX, second.fY);
|
||||
break;
|
||||
}
|
||||
case SkPath::kQuad_Verb:
|
||||
|
@ -906,8 +920,10 @@ public:
|
|||
SkPoint second = source[1];
|
||||
SkPoint third = source[2];
|
||||
|
||||
pathBuilder->QuadraticBezierTo(Point(second.fX, second.fY),
|
||||
Point(third.fX, third.fY));
|
||||
MOZ_ASSERT(!CGPathIsEmpty(cgPath));
|
||||
CGPathAddQuadCurveToPoint(cgPath, nullptr,
|
||||
second.fX, second.fY,
|
||||
third.fX, third.fY);
|
||||
break;
|
||||
}
|
||||
case SkPath::kCubic_Verb:
|
||||
|
@ -916,14 +932,18 @@ public:
|
|||
SkPoint third = source[2];
|
||||
SkPoint fourth = source[2];
|
||||
|
||||
pathBuilder->BezierTo(Point(second.fX, second.fY),
|
||||
Point(third.fX, third.fY),
|
||||
Point(fourth.fX, fourth.fY));
|
||||
MOZ_ASSERT(!CGPathIsEmpty(cgPath));
|
||||
CGPathAddCurveToPoint(cgPath, nullptr,
|
||||
second.fX, second.fY,
|
||||
third.fX, third.fY,
|
||||
fourth.fX, fourth.fY);
|
||||
break;
|
||||
}
|
||||
case SkPath::kClose_Verb:
|
||||
{
|
||||
pathBuilder->Close();
|
||||
if (!CGPathIsEmpty(cgPath)) {
|
||||
CGPathCloseSubpath(cgPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -934,25 +954,19 @@ public:
|
|||
} // end switch
|
||||
} // end while
|
||||
|
||||
RefPtr<Path> path = pathBuilder->Finish();
|
||||
PathCG* cgPath = static_cast<PathCG*>(path.get());
|
||||
|
||||
// Weirdly, CoreGraphics clips empty paths as all shown
|
||||
// but empty rects as all clipped. We detect this situation and
|
||||
// workaround it appropriately
|
||||
if (CGPathIsEmpty(cgPath->GetPath())) {
|
||||
CGContextClipToRect(mCG, CGRectZero);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(!CGPathIsEmpty(cgPath));
|
||||
|
||||
CGContextBeginPath(mCG);
|
||||
CGContextAddPath(mCG, cgPath->GetPath());
|
||||
CGContextAddPath(mCG, cgPath);
|
||||
|
||||
if (cgPath->GetFillRule() == FillRule::FILL_EVEN_ODD) {
|
||||
FillRule fillRule = GetFillRule(aPath.getFillType());
|
||||
if (fillRule == FillRule::FILL_EVEN_ODD) {
|
||||
CGContextEOClip(mCG);
|
||||
} else {
|
||||
CGContextClip(mCG);
|
||||
}
|
||||
|
||||
CGPathRelease(cgPath);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,435 +0,0 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#include "PathCG.h"
|
||||
#include <math.h>
|
||||
#include "Logging.h"
|
||||
#include "PathHelpers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
static inline Rect
|
||||
CGRectToRect(CGRect rect)
|
||||
{
|
||||
return Rect(rect.origin.x,
|
||||
rect.origin.y,
|
||||
rect.size.width,
|
||||
rect.size.height);
|
||||
}
|
||||
|
||||
static inline Point
|
||||
CGPointToPoint(CGPoint point)
|
||||
{
|
||||
return Point(point.x, point.y);
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetStrokeOptions(CGContextRef cg, const StrokeOptions &aStrokeOptions)
|
||||
{
|
||||
switch (aStrokeOptions.mLineCap)
|
||||
{
|
||||
case CapStyle::BUTT:
|
||||
CGContextSetLineCap(cg, kCGLineCapButt);
|
||||
break;
|
||||
case CapStyle::ROUND:
|
||||
CGContextSetLineCap(cg, kCGLineCapRound);
|
||||
break;
|
||||
case CapStyle::SQUARE:
|
||||
CGContextSetLineCap(cg, kCGLineCapSquare);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (aStrokeOptions.mLineJoin)
|
||||
{
|
||||
case JoinStyle::BEVEL:
|
||||
CGContextSetLineJoin(cg, kCGLineJoinBevel);
|
||||
break;
|
||||
case JoinStyle::ROUND:
|
||||
CGContextSetLineJoin(cg, kCGLineJoinRound);
|
||||
break;
|
||||
case JoinStyle::MITER:
|
||||
case JoinStyle::MITER_OR_BEVEL:
|
||||
CGContextSetLineJoin(cg, kCGLineJoinMiter);
|
||||
break;
|
||||
}
|
||||
|
||||
CGContextSetLineWidth(cg, aStrokeOptions.mLineWidth);
|
||||
CGContextSetMiterLimit(cg, aStrokeOptions.mMiterLimit);
|
||||
|
||||
// XXX: rename mDashLength to dashLength
|
||||
if (aStrokeOptions.mDashLength > 0) {
|
||||
// we use a regular array instead of a std::vector here because we don't want to leak the <vector> include
|
||||
CGFloat *dashes = new CGFloat[aStrokeOptions.mDashLength];
|
||||
for (size_t i=0; i<aStrokeOptions.mDashLength; i++) {
|
||||
dashes[i] = aStrokeOptions.mDashPattern[i];
|
||||
}
|
||||
CGContextSetLineDash(cg, aStrokeOptions.mDashOffset, dashes, aStrokeOptions.mDashLength);
|
||||
delete[] dashes;
|
||||
}
|
||||
}
|
||||
|
||||
static inline CGAffineTransform
|
||||
GfxMatrixToCGAffineTransform(const Matrix &m)
|
||||
{
|
||||
CGAffineTransform t;
|
||||
t.a = m._11;
|
||||
t.b = m._12;
|
||||
t.c = m._21;
|
||||
t.d = m._22;
|
||||
t.tx = m._31;
|
||||
t.ty = m._32;
|
||||
return t;
|
||||
}
|
||||
|
||||
PathBuilderCG::~PathBuilderCG()
|
||||
{
|
||||
CGPathRelease(mCGPath);
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::MoveTo(const Point &aPoint)
|
||||
{
|
||||
if (!aPoint.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
CGPathMoveToPoint(mCGPath, nullptr, aPoint.x, aPoint.y);
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::LineTo(const Point &aPoint)
|
||||
{
|
||||
if (!aPoint.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CGPathIsEmpty(mCGPath))
|
||||
MoveTo(aPoint);
|
||||
else
|
||||
CGPathAddLineToPoint(mCGPath, nullptr, aPoint.x, aPoint.y);
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::BezierTo(const Point &aCP1,
|
||||
const Point &aCP2,
|
||||
const Point &aCP3)
|
||||
{
|
||||
if (!aCP1.IsFinite() || !aCP2.IsFinite() || !aCP3.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CGPathIsEmpty(mCGPath))
|
||||
MoveTo(aCP1);
|
||||
CGPathAddCurveToPoint(mCGPath, nullptr,
|
||||
aCP1.x, aCP1.y,
|
||||
aCP2.x, aCP2.y,
|
||||
aCP3.x, aCP3.y);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::QuadraticBezierTo(const Point &aCP1,
|
||||
const Point &aCP2)
|
||||
{
|
||||
if (!aCP1.IsFinite() || !aCP2.IsFinite()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (CGPathIsEmpty(mCGPath))
|
||||
MoveTo(aCP1);
|
||||
CGPathAddQuadCurveToPoint(mCGPath, nullptr,
|
||||
aCP1.x, aCP1.y,
|
||||
aCP2.x, aCP2.y);
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::Close()
|
||||
{
|
||||
if (!CGPathIsEmpty(mCGPath))
|
||||
CGPathCloseSubpath(mCGPath);
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::Arc(const Point &aOrigin, Float aRadius, Float aStartAngle,
|
||||
Float aEndAngle, bool aAntiClockwise)
|
||||
{
|
||||
if (!aOrigin.IsFinite() || !IsFinite(aRadius) ||
|
||||
!IsFinite(aStartAngle) || !IsFinite(aEndAngle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disabled for now due to a CG bug when using CGPathAddArc with stroke
|
||||
// dashing and rotation transforms that are multiples of 90 degrees. See:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=949661#c8
|
||||
#if 0
|
||||
// Core Graphic's initial coordinate system is y-axis up, whereas Moz2D's is
|
||||
// y-axis down. Core Graphics therefore considers "clockwise" to mean "sweep
|
||||
// in the direction of decreasing angle" whereas Moz2D considers it to mean
|
||||
// "sweep in the direction of increasing angle". In other words if this
|
||||
// Moz2D method is instructed to sweep anti-clockwise we need to tell
|
||||
// CGPathAddArc to sweep clockwise, and vice versa. Hence why we pass the
|
||||
// value of aAntiClockwise directly to CGPathAddArc's "clockwise" bool
|
||||
// parameter.
|
||||
CGPathAddArc(mCGPath, nullptr,
|
||||
aOrigin.x, aOrigin.y,
|
||||
aRadius,
|
||||
aStartAngle,
|
||||
aEndAngle,
|
||||
aAntiClockwise);
|
||||
#endif
|
||||
ArcToBezier(this, aOrigin, Size(aRadius, aRadius), aStartAngle, aEndAngle,
|
||||
aAntiClockwise);
|
||||
}
|
||||
|
||||
Point
|
||||
PathBuilderCG::CurrentPoint() const
|
||||
{
|
||||
Point ret;
|
||||
if (!CGPathIsEmpty(mCGPath)) {
|
||||
CGPoint pt = CGPathGetCurrentPoint(mCGPath);
|
||||
ret.MoveTo(pt.x, pt.y);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
PathBuilderCG::EnsureActive(const Point &aPoint)
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Path>
|
||||
PathBuilderCG::Finish()
|
||||
{
|
||||
return MakeAndAddRef<PathCG>(mCGPath, mFillRule);
|
||||
}
|
||||
|
||||
already_AddRefed<PathBuilder>
|
||||
PathCG::CopyToBuilder(FillRule aFillRule) const
|
||||
{
|
||||
CGMutablePathRef path = CGPathCreateMutableCopy(mPath);
|
||||
return MakeAndAddRef<PathBuilderCG>(path, aFillRule);
|
||||
}
|
||||
|
||||
|
||||
|
||||
already_AddRefed<PathBuilder>
|
||||
PathCG::TransformedCopyToBuilder(const Matrix &aTransform, FillRule aFillRule) const
|
||||
{
|
||||
// 10.7 adds CGPathCreateMutableCopyByTransformingPath it might be faster than doing
|
||||
// this by hand
|
||||
|
||||
struct TransformApplier {
|
||||
CGMutablePathRef path;
|
||||
CGAffineTransform transform;
|
||||
static void
|
||||
TranformCGPathApplierFunc(void *vinfo, const CGPathElement *element)
|
||||
{
|
||||
TransformApplier *info = reinterpret_cast<TransformApplier*>(vinfo);
|
||||
switch (element->type) {
|
||||
case kCGPathElementMoveToPoint:
|
||||
{
|
||||
CGPoint pt = element->points[0];
|
||||
CGPathMoveToPoint(info->path, &info->transform, pt.x, pt.y);
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddLineToPoint:
|
||||
{
|
||||
CGPoint pt = element->points[0];
|
||||
CGPathAddLineToPoint(info->path, &info->transform, pt.x, pt.y);
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddQuadCurveToPoint:
|
||||
{
|
||||
CGPoint cpt = element->points[0];
|
||||
CGPoint pt = element->points[1];
|
||||
CGPathAddQuadCurveToPoint(info->path, &info->transform, cpt.x, cpt.y, pt.x, pt.y);
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddCurveToPoint:
|
||||
{
|
||||
CGPoint cpt1 = element->points[0];
|
||||
CGPoint cpt2 = element->points[1];
|
||||
CGPoint pt = element->points[2];
|
||||
CGPathAddCurveToPoint(info->path, &info->transform, cpt1.x, cpt1.y, cpt2.x, cpt2.y, pt.x, pt.y);
|
||||
break;
|
||||
}
|
||||
case kCGPathElementCloseSubpath:
|
||||
{
|
||||
CGPathCloseSubpath(info->path);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TransformApplier ta;
|
||||
ta.path = CGPathCreateMutable();
|
||||
ta.transform = GfxMatrixToCGAffineTransform(aTransform);
|
||||
|
||||
CGPathApply(mPath, &ta, TransformApplier::TranformCGPathApplierFunc);
|
||||
return MakeAndAddRef<PathBuilderCG>(ta.path, aFillRule);
|
||||
}
|
||||
|
||||
static void
|
||||
StreamPathToSinkApplierFunc(void *vinfo, const CGPathElement *element)
|
||||
{
|
||||
PathSink *sink = reinterpret_cast<PathSink*>(vinfo);
|
||||
switch (element->type) {
|
||||
case kCGPathElementMoveToPoint:
|
||||
{
|
||||
CGPoint pt = element->points[0];
|
||||
sink->MoveTo(CGPointToPoint(pt));
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddLineToPoint:
|
||||
{
|
||||
CGPoint pt = element->points[0];
|
||||
sink->LineTo(CGPointToPoint(pt));
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddQuadCurveToPoint:
|
||||
{
|
||||
CGPoint cpt = element->points[0];
|
||||
CGPoint pt = element->points[1];
|
||||
sink->QuadraticBezierTo(CGPointToPoint(cpt),
|
||||
CGPointToPoint(pt));
|
||||
break;
|
||||
}
|
||||
case kCGPathElementAddCurveToPoint:
|
||||
{
|
||||
CGPoint cpt1 = element->points[0];
|
||||
CGPoint cpt2 = element->points[1];
|
||||
CGPoint pt = element->points[2];
|
||||
sink->BezierTo(CGPointToPoint(cpt1),
|
||||
CGPointToPoint(cpt2),
|
||||
CGPointToPoint(pt));
|
||||
break;
|
||||
}
|
||||
case kCGPathElementCloseSubpath:
|
||||
{
|
||||
sink->Close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PathCG::StreamToSink(PathSink *aSink) const
|
||||
{
|
||||
CGPathApply(mPath, aSink, StreamPathToSinkApplierFunc);
|
||||
}
|
||||
|
||||
bool
|
||||
PathCG::ContainsPoint(const Point &aPoint, const Matrix &aTransform) const
|
||||
{
|
||||
Matrix inverse = aTransform;
|
||||
inverse.Invert();
|
||||
Point transformedPoint = inverse.TransformPoint(aPoint);
|
||||
// We could probably drop the input transform and just transform the point at the caller?
|
||||
CGPoint point = {transformedPoint.x, transformedPoint.y};
|
||||
|
||||
// The transform parameter of CGPathContainsPoint doesn't seem to work properly on OS X 10.5
|
||||
// so we transform aPoint ourselves.
|
||||
return CGPathContainsPoint(mPath, nullptr, point, mFillRule == FillRule::FILL_EVEN_ODD);
|
||||
}
|
||||
|
||||
static size_t
|
||||
PutBytesNull(void *info, const void *buffer, size_t count)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
/* The idea of a scratch context comes from WebKit */
|
||||
static CGContextRef
|
||||
CreateScratchContext()
|
||||
{
|
||||
CGDataConsumerCallbacks callbacks = {PutBytesNull, nullptr};
|
||||
CGDataConsumerRef consumer = CGDataConsumerCreate(nullptr, &callbacks);
|
||||
CGContextRef cg = CGPDFContextCreate(consumer, nullptr, nullptr);
|
||||
CGDataConsumerRelease(consumer);
|
||||
return cg;
|
||||
}
|
||||
|
||||
static CGContextRef
|
||||
ScratchContext()
|
||||
{
|
||||
static CGContextRef cg = CreateScratchContext();
|
||||
return cg;
|
||||
}
|
||||
|
||||
bool
|
||||
PathCG::StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
|
||||
const Point &aPoint,
|
||||
const Matrix &aTransform) const
|
||||
{
|
||||
Matrix inverse = aTransform;
|
||||
inverse.Invert();
|
||||
Point transformedPoint = inverse.TransformPoint(aPoint);
|
||||
// We could probably drop the input transform and just transform the point at the caller?
|
||||
CGPoint point = {transformedPoint.x, transformedPoint.y};
|
||||
|
||||
CGContextRef cg = ScratchContext();
|
||||
|
||||
CGContextSaveGState(cg);
|
||||
|
||||
CGContextBeginPath(cg);
|
||||
CGContextAddPath(cg, mPath);
|
||||
|
||||
SetStrokeOptions(cg, aStrokeOptions);
|
||||
|
||||
CGContextReplacePathWithStrokedPath(cg);
|
||||
CGContextRestoreGState(cg);
|
||||
|
||||
CGPathRef sPath = CGContextCopyPath(cg);
|
||||
bool inStroke = CGPathContainsPoint(sPath, nullptr, point, false);
|
||||
CGPathRelease(sPath);
|
||||
|
||||
return inStroke;
|
||||
}
|
||||
|
||||
//XXX: what should these functions return for an empty path?
|
||||
// currently they return CGRectNull {inf,inf, 0, 0}
|
||||
Rect
|
||||
PathCG::GetBounds(const Matrix &aTransform) const
|
||||
{
|
||||
//XXX: are these bounds tight enough
|
||||
Rect bounds = CGRectToRect(CGPathGetBoundingBox(mPath));
|
||||
|
||||
//XXX: currently this returns the bounds of the transformed bounds
|
||||
// this is strictly looser than the bounds of the transformed path
|
||||
return aTransform.TransformBounds(bounds);
|
||||
}
|
||||
|
||||
Rect
|
||||
PathCG::GetStrokedBounds(const StrokeOptions &aStrokeOptions,
|
||||
const Matrix &aTransform) const
|
||||
{
|
||||
// 10.7 has CGPathCreateCopyByStrokingPath which we could use
|
||||
// instead of this scratch context business
|
||||
CGContextRef cg = ScratchContext();
|
||||
|
||||
CGContextSaveGState(cg);
|
||||
|
||||
CGContextBeginPath(cg);
|
||||
CGContextAddPath(cg, mPath);
|
||||
|
||||
SetStrokeOptions(cg, aStrokeOptions);
|
||||
|
||||
CGContextReplacePathWithStrokedPath(cg);
|
||||
Rect bounds = CGRectToRect(CGContextGetPathBoundingBox(cg));
|
||||
|
||||
CGContextRestoreGState(cg);
|
||||
|
||||
if (!bounds.IsFinite()) {
|
||||
return Rect();
|
||||
}
|
||||
|
||||
return aTransform.TransformBounds(bounds);
|
||||
}
|
||||
|
||||
|
||||
} // namespace gfx
|
||||
|
||||
} // namespace mozilla
|
114
gfx/2d/PathCG.h
114
gfx/2d/PathCG.h
|
@ -1,114 +0,0 @@
|
|||
/* -*- 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_PATHCG_H_
|
||||
#define MOZILLA_GFX_PATHCG_H_
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#else
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#endif
|
||||
|
||||
#include "2D.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class PathCG;
|
||||
|
||||
class PathBuilderCG : public PathBuilder
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderCG)
|
||||
// absorbs a reference of aPath
|
||||
PathBuilderCG(CGMutablePathRef aPath, FillRule aFillRule)
|
||||
: mFillRule(aFillRule)
|
||||
{
|
||||
mCGPath = aPath;
|
||||
}
|
||||
|
||||
explicit PathBuilderCG(FillRule aFillRule)
|
||||
: mFillRule(aFillRule)
|
||||
{
|
||||
mCGPath = CGPathCreateMutable();
|
||||
}
|
||||
|
||||
virtual ~PathBuilderCG();
|
||||
|
||||
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 already_AddRefed<Path> Finish();
|
||||
|
||||
virtual BackendType GetBackendType() const { return BackendType::SKIA; }
|
||||
|
||||
private:
|
||||
friend class PathCG;
|
||||
friend class ScaledFontMac;
|
||||
|
||||
void EnsureActive(const Point &aPoint);
|
||||
|
||||
CGMutablePathRef mCGPath;
|
||||
Point mCurrentPoint;
|
||||
Point mBeginPoint;
|
||||
FillRule mFillRule;
|
||||
};
|
||||
|
||||
class PathCG : public Path
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathCG)
|
||||
PathCG(CGMutablePathRef aPath, FillRule aFillRule)
|
||||
: mPath(aPath)
|
||||
, mFillRule(aFillRule)
|
||||
{
|
||||
CGPathRetain(mPath);
|
||||
}
|
||||
virtual ~PathCG() { CGPathRelease(mPath); }
|
||||
|
||||
// Paths will always return BackendType::COREGRAPHICS, but note that they
|
||||
// are compatible with BackendType::COREGRAPHICS_ACCELERATED backend.
|
||||
virtual BackendType GetBackendType() const { return BackendType::SKIA; }
|
||||
|
||||
virtual already_AddRefed<PathBuilder> CopyToBuilder(FillRule aFillRule) const;
|
||||
virtual already_AddRefed<PathBuilder> TransformedCopyToBuilder(const Matrix &aTransform,
|
||||
FillRule aFillRule) const;
|
||||
|
||||
virtual bool ContainsPoint(const Point &aPoint, const Matrix &aTransform) const;
|
||||
virtual bool StrokeContainsPoint(const StrokeOptions &aStrokeOptions,
|
||||
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 void StreamToSink(PathSink *aSink) const;
|
||||
|
||||
virtual FillRule GetFillRule() const { return mFillRule; }
|
||||
|
||||
CGMutablePathRef GetPath() const { return mPath; }
|
||||
|
||||
private:
|
||||
friend class DrawTargetCG;
|
||||
|
||||
CGMutablePathRef mPath;
|
||||
Point mEndPoint;
|
||||
FillRule mFillRule;
|
||||
};
|
||||
|
||||
} // namespace gfx
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -65,7 +65,6 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'uikit'):
|
|||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'NativeFontResourceMac.cpp',
|
||||
'PathCG.cpp',
|
||||
'ScaledFontMac.cpp',
|
||||
]
|
||||
elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
|
|
Загрузка…
Ссылка в новой задаче