mirror of
https://github.com/encounter/engine.git
synced 2026-03-30 11:09:55 -07:00
301 lines
9.5 KiB
C++
301 lines
9.5 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "flutter/lib/ui/painting/path.h"
|
|
|
|
#define _USE_MATH_DEFINES
|
|
#include <math.h>
|
|
|
|
#include "flutter/lib/ui/painting/matrix.h"
|
|
#include "third_party/tonic/converter/dart_converter.h"
|
|
#include "third_party/tonic/dart_args.h"
|
|
#include "third_party/tonic/dart_binding_macros.h"
|
|
#include "third_party/tonic/dart_library_natives.h"
|
|
|
|
using tonic::ToDart;
|
|
|
|
namespace flutter {
|
|
|
|
typedef CanvasPath Path;
|
|
|
|
static void Path_constructor(Dart_NativeArguments args) {
|
|
DartCallConstructor(&CanvasPath::Create, args);
|
|
}
|
|
|
|
IMPLEMENT_WRAPPERTYPEINFO(ui, Path);
|
|
|
|
#define FOR_EACH_BINDING(V) \
|
|
V(Path, addArc) \
|
|
V(Path, addOval) \
|
|
V(Path, addPath) \
|
|
V(Path, addPolygon) \
|
|
V(Path, addRect) \
|
|
V(Path, addRRect) \
|
|
V(Path, arcTo) \
|
|
V(Path, arcToPoint) \
|
|
V(Path, close) \
|
|
V(Path, conicTo) \
|
|
V(Path, contains) \
|
|
V(Path, cubicTo) \
|
|
V(Path, extendWithPath) \
|
|
V(Path, extendWithPathAndMatrix) \
|
|
V(Path, getFillType) \
|
|
V(Path, lineTo) \
|
|
V(Path, moveTo) \
|
|
V(Path, quadraticBezierTo) \
|
|
V(Path, relativeArcToPoint) \
|
|
V(Path, relativeConicTo) \
|
|
V(Path, relativeCubicTo) \
|
|
V(Path, relativeLineTo) \
|
|
V(Path, relativeMoveTo) \
|
|
V(Path, relativeQuadraticBezierTo) \
|
|
V(Path, reset) \
|
|
V(Path, setFillType) \
|
|
V(Path, shift) \
|
|
V(Path, transform) \
|
|
V(Path, getBounds) \
|
|
V(Path, addPathWithMatrix) \
|
|
V(Path, op) \
|
|
V(Path, clone)
|
|
|
|
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
|
|
|
|
void CanvasPath::RegisterNatives(tonic::DartLibraryNatives* natives) {
|
|
natives->Register({{"Path_constructor", Path_constructor, 1, true},
|
|
FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
|
|
}
|
|
|
|
CanvasPath::CanvasPath() {}
|
|
|
|
CanvasPath::~CanvasPath() {}
|
|
|
|
int CanvasPath::getFillType() {
|
|
return static_cast<int>(path_.getFillType());
|
|
}
|
|
|
|
void CanvasPath::setFillType(int fill_type) {
|
|
path_.setFillType(static_cast<SkPathFillType>(fill_type));
|
|
}
|
|
|
|
void CanvasPath::moveTo(float x, float y) {
|
|
path_.moveTo(x, y);
|
|
}
|
|
|
|
void CanvasPath::relativeMoveTo(float x, float y) {
|
|
path_.rMoveTo(x, y);
|
|
}
|
|
|
|
void CanvasPath::lineTo(float x, float y) {
|
|
path_.lineTo(x, y);
|
|
}
|
|
|
|
void CanvasPath::relativeLineTo(float x, float y) {
|
|
path_.rLineTo(x, y);
|
|
}
|
|
|
|
void CanvasPath::quadraticBezierTo(float x1, float y1, float x2, float y2) {
|
|
path_.quadTo(x1, y1, x2, y2);
|
|
}
|
|
|
|
void CanvasPath::relativeQuadraticBezierTo(float x1,
|
|
float y1,
|
|
float x2,
|
|
float y2) {
|
|
path_.rQuadTo(x1, y1, x2, y2);
|
|
}
|
|
|
|
void CanvasPath::cubicTo(float x1,
|
|
float y1,
|
|
float x2,
|
|
float y2,
|
|
float x3,
|
|
float y3) {
|
|
path_.cubicTo(x1, y1, x2, y2, x3, y3);
|
|
}
|
|
|
|
void CanvasPath::relativeCubicTo(float x1,
|
|
float y1,
|
|
float x2,
|
|
float y2,
|
|
float x3,
|
|
float y3) {
|
|
path_.rCubicTo(x1, y1, x2, y2, x3, y3);
|
|
}
|
|
|
|
void CanvasPath::conicTo(float x1, float y1, float x2, float y2, float w) {
|
|
path_.conicTo(x1, y1, x2, y2, w);
|
|
}
|
|
|
|
void CanvasPath::relativeConicTo(float x1,
|
|
float y1,
|
|
float x2,
|
|
float y2,
|
|
float w) {
|
|
path_.rConicTo(x1, y1, x2, y2, w);
|
|
}
|
|
|
|
void CanvasPath::arcTo(float left,
|
|
float top,
|
|
float right,
|
|
float bottom,
|
|
float startAngle,
|
|
float sweepAngle,
|
|
bool forceMoveTo) {
|
|
path_.arcTo(SkRect::MakeLTRB(left, top, right, bottom),
|
|
startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
|
|
forceMoveTo);
|
|
}
|
|
|
|
void CanvasPath::arcToPoint(float arcEndX,
|
|
float arcEndY,
|
|
float radiusX,
|
|
float radiusY,
|
|
float xAxisRotation,
|
|
bool isLargeArc,
|
|
bool isClockwiseDirection) {
|
|
const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
|
|
: SkPath::ArcSize::kSmall_ArcSize;
|
|
const auto direction =
|
|
isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
|
|
|
|
path_.arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX,
|
|
arcEndY);
|
|
}
|
|
|
|
void CanvasPath::relativeArcToPoint(float arcEndDeltaX,
|
|
float arcEndDeltaY,
|
|
float radiusX,
|
|
float radiusY,
|
|
float xAxisRotation,
|
|
bool isLargeArc,
|
|
bool isClockwiseDirection) {
|
|
const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
|
|
: SkPath::ArcSize::kSmall_ArcSize;
|
|
const auto direction =
|
|
isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
|
|
path_.rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction,
|
|
arcEndDeltaX, arcEndDeltaY);
|
|
}
|
|
|
|
void CanvasPath::addRect(float left, float top, float right, float bottom) {
|
|
path_.addRect(SkRect::MakeLTRB(left, top, right, bottom));
|
|
}
|
|
|
|
void CanvasPath::addOval(float left, float top, float right, float bottom) {
|
|
path_.addOval(SkRect::MakeLTRB(left, top, right, bottom));
|
|
}
|
|
|
|
void CanvasPath::addArc(float left,
|
|
float top,
|
|
float right,
|
|
float bottom,
|
|
float startAngle,
|
|
float sweepAngle) {
|
|
path_.addArc(SkRect::MakeLTRB(left, top, right, bottom),
|
|
startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
|
|
}
|
|
|
|
void CanvasPath::addPolygon(const tonic::Float32List& points, bool close) {
|
|
path_.addPoly(reinterpret_cast<const SkPoint*>(points.data()),
|
|
points.num_elements() / 2, close);
|
|
}
|
|
|
|
void CanvasPath::addRRect(const RRect& rrect) {
|
|
path_.addRRect(rrect.sk_rrect);
|
|
}
|
|
|
|
void CanvasPath::addPath(CanvasPath* path, double dx, double dy) {
|
|
if (!path)
|
|
Dart_ThrowException(ToDart("Path.addPath called with non-genuine Path."));
|
|
path_.addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode);
|
|
}
|
|
|
|
void CanvasPath::addPathWithMatrix(CanvasPath* path,
|
|
double dx,
|
|
double dy,
|
|
tonic::Float64List& matrix4) {
|
|
if (!path) {
|
|
Dart_ThrowException(
|
|
ToDart("Path.addPathWithMatrix called with non-genuine Path."));
|
|
}
|
|
|
|
SkMatrix matrix = ToSkMatrix(matrix4);
|
|
matrix.setTranslateX(matrix.getTranslateX() + dx);
|
|
matrix.setTranslateY(matrix.getTranslateY() + dy);
|
|
path_.addPath(path->path(), matrix, SkPath::kAppend_AddPathMode);
|
|
matrix4.Release();
|
|
}
|
|
|
|
void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) {
|
|
if (!path)
|
|
Dart_ThrowException(
|
|
ToDart("Path.extendWithPath called with non-genuine Path."));
|
|
path_.addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode);
|
|
}
|
|
|
|
void CanvasPath::extendWithPathAndMatrix(CanvasPath* path,
|
|
double dx,
|
|
double dy,
|
|
tonic::Float64List& matrix4) {
|
|
if (!path) {
|
|
Dart_ThrowException(
|
|
ToDart("Path.addPathWithMatrix called with non-genuine Path."));
|
|
}
|
|
|
|
SkMatrix matrix = ToSkMatrix(matrix4);
|
|
matrix.setTranslateX(matrix.getTranslateX() + dx);
|
|
matrix.setTranslateY(matrix.getTranslateY() + dy);
|
|
path_.addPath(path->path(), matrix, SkPath::kExtend_AddPathMode);
|
|
matrix4.Release();
|
|
}
|
|
|
|
void CanvasPath::close() {
|
|
path_.close();
|
|
}
|
|
|
|
void CanvasPath::reset() {
|
|
path_.reset();
|
|
}
|
|
|
|
bool CanvasPath::contains(double x, double y) {
|
|
return path_.contains(x, y);
|
|
}
|
|
|
|
fml::RefPtr<CanvasPath> CanvasPath::shift(double dx, double dy) {
|
|
fml::RefPtr<CanvasPath> path = CanvasPath::Create();
|
|
path_.offset(dx, dy, &path->path_);
|
|
return path;
|
|
}
|
|
|
|
fml::RefPtr<CanvasPath> CanvasPath::transform(tonic::Float64List& matrix4) {
|
|
fml::RefPtr<CanvasPath> path = CanvasPath::Create();
|
|
path_.transform(ToSkMatrix(matrix4), &path->path_);
|
|
matrix4.Release();
|
|
return path;
|
|
}
|
|
|
|
tonic::Float32List CanvasPath::getBounds() {
|
|
tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4));
|
|
const SkRect& bounds = path_.getBounds();
|
|
rect[0] = bounds.left();
|
|
rect[1] = bounds.top();
|
|
rect[2] = bounds.right();
|
|
rect[3] = bounds.bottom();
|
|
return rect;
|
|
}
|
|
|
|
bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) {
|
|
return Op(path1->path(), path2->path(), (SkPathOp)operation, &path_);
|
|
}
|
|
|
|
fml::RefPtr<CanvasPath> CanvasPath::clone() {
|
|
fml::RefPtr<CanvasPath> path = CanvasPath::Create();
|
|
// per Skia docs, this will create a fast copy
|
|
// data is shared until the source path or dest path are mutated
|
|
path->path_ = path_;
|
|
return path;
|
|
}
|
|
|
|
} // namespace flutter
|