From 91dd180225200efe28e9553ad495506ee96899c1 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Sun, 13 Oct 2024 17:17:30 +0200 Subject: [PATCH] coordinate: Add register function --- src/coordinate.typ | 9 ++++---- src/draw.typ | 2 +- src/draw/util.typ | 38 ++++++++++++++++++++++++++++++++ tests/coordinate/custom/test.typ | 5 +---- 4 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/coordinate.typ b/src/coordinate.typ index 382b2e9a2..725d4f9ae 100644 --- a/src/coordinate.typ +++ b/src/coordinate.typ @@ -322,11 +322,10 @@ /// - update (bool): Update the context's last position /// -> array #let resolve(ctx, ..coordinates, update: true) = { - let resolver = () - if type(ctx.resolve-coordinate) == array { - resolver += ctx.resolve-coordinate - } else if type(ctx.resolve-coordinate) == function { - resolver.push(ctx.resolve-coordinate) + let resolver = if type(ctx.resolve-coordinate) == array { + ctx.resolve-coordinate + } else { + () } let result = () diff --git a/src/draw.typ b/src/draw.typ index e46b87de9..cef4e6d2d 100644 --- a/src/draw.typ +++ b/src/draw.typ @@ -3,4 +3,4 @@ #import "draw/styling.typ": set-style, fill, stroke, register-mark #import "draw/shapes.typ": circle, circle-through, arc, arc-through, mark, line, grid, content, rect, bezier, bezier-through, catmull, hobby, merge-path #import "draw/projection.typ": ortho, on-xy, on-xz, on-yz -#import "draw/util.typ": assert-version +#import "draw/util.typ": assert-version, register-coordinate-resolver diff --git a/src/draw/util.typ b/src/draw/util.typ index 3f2c0d1df..3d4a99cb6 100644 --- a/src/draw/util.typ +++ b/src/draw/util.typ @@ -18,3 +18,41 @@ return (ctx: ctx) },) } + +/// Push a custom coordinate resolve function to the list of coordinate +/// resolvers. This resolver is scoped to the current context scope! +/// +/// A coordinate resolver must be a function of the format `(context, coordinate) => coordinate`. And must _always_ return a valid coordinate or panic, in case of an error. +/// +/// If multiple resolvers are registered, coordinates get passed through all +/// resolvers in reverse registering order. All coordinates get paased to cetz' +/// default coordinate resolvers. +/// +/// ```typc example +/// register-coordinate-resolver((ctx, c) => { +/// if type(c) == dictionary and "log" in c { +/// c = c.log.map(n => calc.log(n, base: 10)) +/// } +/// return c +/// }) +/// +/// circle((log: (10, 0)), radius: .25) +/// circle((log: (100, 0)), radius: .25) +/// circle((log: (1000, 0)), radius: .25) +/// ``` +/// +/// - resolver (function): The resolver function, taking a context and a single coordinate and returning a single coordinate +#let register-coordinate-resolver(resolver) = { + assert.eq(type(resolver), function, + message: "Coordinate resolver must be of type function (ctx, coordinate) => coordinate.") + + return (ctx => { + if type(ctx.resolve-coordinate) == array { + ctx.resolve-coordinate.push(resolver) + } else { + ctx.resolve-coordinate = (resolver,) + } + + return (ctx: ctx) + },) +} diff --git a/tests/coordinate/custom/test.typ b/tests/coordinate/custom/test.typ index 930f6c00b..0c2137946 100644 --- a/tests/coordinate/custom/test.typ +++ b/tests/coordinate/custom/test.typ @@ -15,10 +15,7 @@ return coordinate } - set-ctx(ctx => { - ctx.resolve-coordinate = log-resolver - return ctx - }) + register-coordinate-resolver(log-resolver) set-style(circle: (radius: .1)) for i in (.1, 1, 10, 100, 1000, 10000) {