mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 22:08:11 +08:00
Implement Bezier scale and offset (#718)
* Implement scale and offset * Add tests for offset and reduce * Added scale to documentation page * address comments Co-authored-by: Hannah Li <hannahli2010@gmail.com> Co-authored-by: Thomas Cheng <Androxium@users.noreply.github.com> Co-authored-by: Rob Nadal <RobNadal@users.noreply.github.com>
This commit is contained in:
co-authored by
Thomas Cheng
Rob Nadal
parent
06524bac8d
commit
b4070f9c90
@@ -25,7 +25,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, markRaw } from "vue";
|
||||
|
||||
import { drawText, drawPoint, drawBezier, drawLine, getContextFromCanvas, drawBezierHelper, COLORS } from "@/utils/drawing";
|
||||
import { drawBezier, drawBezierHelper, drawCurve, drawLine, drawPoint, drawText, getContextFromCanvas, COLORS } from "@/utils/drawing";
|
||||
import { BezierCurveType, Point, WasmBezierInstance, WasmSubpathInstance } from "@/utils/types";
|
||||
|
||||
import ExamplePane from "@/components/ExamplePane.vue";
|
||||
@@ -194,8 +194,8 @@ export default defineComponent({
|
||||
const normal = JSON.parse(bezier.normal(options.t));
|
||||
|
||||
const normalEnd = {
|
||||
x: intersection.x - normal.x * SCALE_UNIT_VECTOR_FACTOR,
|
||||
y: intersection.y - normal.y * SCALE_UNIT_VECTOR_FACTOR,
|
||||
x: intersection.x + normal.x * SCALE_UNIT_VECTOR_FACTOR,
|
||||
y: intersection.y + normal.y * SCALE_UNIT_VECTOR_FACTOR,
|
||||
};
|
||||
|
||||
drawPoint(context, intersection, 3, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
@@ -283,6 +283,31 @@ export default defineComponent({
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Bounding Box",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance): void => {
|
||||
const context = getContextFromCanvas(canvas);
|
||||
const bboxPoints: Point[] = JSON.parse(bezier.bounding_box());
|
||||
const minPoint = bboxPoints[0];
|
||||
const maxPoint = bboxPoints[1];
|
||||
drawLine(context, minPoint, { x: minPoint.x, y: maxPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
drawLine(context, minPoint, { x: maxPoint.x, y: minPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
drawLine(context, maxPoint, { x: minPoint.x, y: maxPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
drawLine(context, maxPoint, { x: maxPoint.x, y: minPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Inflections",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance): void => {
|
||||
const context = getContextFromCanvas(canvas);
|
||||
const inflections: number[] = JSON.parse(bezier.inflections());
|
||||
inflections.forEach((t) => {
|
||||
const point = JSON.parse(bezier.evaluate(t));
|
||||
drawPoint(context, point, 4, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
});
|
||||
},
|
||||
curveDegrees: new Set([BezierCurveType.Cubic]),
|
||||
},
|
||||
{
|
||||
name: "De Casteljau Points",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record<string, number>): void => {
|
||||
@@ -357,29 +382,32 @@ export default defineComponent({
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Bounding Box",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance): void => {
|
||||
name: "Offset",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance, options: Record<string, number>): void => {
|
||||
const context = getContextFromCanvas(canvas);
|
||||
const bboxPoints: Point[] = JSON.parse(bezier.bounding_box());
|
||||
const minPoint = bboxPoints[0];
|
||||
const maxPoint = bboxPoints[1];
|
||||
drawLine(context, minPoint, { x: minPoint.x, y: maxPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
drawLine(context, minPoint, { x: maxPoint.x, y: minPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
drawLine(context, maxPoint, { x: minPoint.x, y: maxPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
drawLine(context, maxPoint, { x: maxPoint.x, y: minPoint.y }, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Inflections",
|
||||
callback: (canvas: HTMLCanvasElement, bezier: WasmBezierInstance): void => {
|
||||
const context = getContextFromCanvas(canvas);
|
||||
const inflections: number[] = JSON.parse(bezier.inflections());
|
||||
inflections.forEach((t) => {
|
||||
const point = JSON.parse(bezier.evaluate(t));
|
||||
drawPoint(context, point, 4, COLORS.NON_INTERACTIVE.STROKE_1);
|
||||
const curves: Point[][] = JSON.parse(bezier.offset(options.distance));
|
||||
curves.forEach((points, index) => {
|
||||
if (points.length === 2) {
|
||||
drawLine(context, points[0], points[1], `hsl(${40 * index}, 100%, 50%)`);
|
||||
} else {
|
||||
drawCurve(context, points, `hsl(${40 * index}, 100%, 50%)`);
|
||||
}
|
||||
});
|
||||
drawPoint(context, curves[0][0], 4, "hsl(0, 100%, 50%)");
|
||||
drawPoint(context, curves[curves.length - 1][curves[0].length - 1], 4, `hsl(${40 * (curves.length - 1)}, 100%, 50%)`);
|
||||
},
|
||||
template: markRaw(SliderExample),
|
||||
templateOptions: {
|
||||
sliders: [
|
||||
{
|
||||
variable: "distance",
|
||||
min: -50,
|
||||
max: 50,
|
||||
step: 1,
|
||||
default: 20,
|
||||
},
|
||||
],
|
||||
},
|
||||
curveDegrees: new Set([BezierCurveType.Cubic]),
|
||||
},
|
||||
],
|
||||
subpathFeatures: [
|
||||
|
||||
Reference in New Issue
Block a user