From 49868367a7d8462ef8dab722a19ad7b78c8674d8 Mon Sep 17 00:00:00 2001 From: djowel Date: Sun, 10 Mar 2024 21:52:43 +0800 Subject: [PATCH] Remove pre_scale. Use affine transforms instead to properly address device_to_user and user_to_device conversions. --- lib/impl/macos/quartz2d/canvas.mm | 17 +-------- lib/impl/skia/canvas.cpp | 61 +++++++++++++++++-------------- lib/include/artist/canvas.hpp | 3 -- 3 files changed, 36 insertions(+), 45 deletions(-) diff --git a/lib/impl/macos/quartz2d/canvas.mm b/lib/impl/macos/quartz2d/canvas.mm index 39b648f0..625d7018 100755 --- a/lib/impl/macos/quartz2d/canvas.mm +++ b/lib/impl/macos/quartz2d/canvas.mm @@ -233,20 +233,6 @@ void make_gradient(std::vector const& space, CGGradientRef& { } - void canvas::pre_scale(float sc) - { - // Quartz-2D does not need to be pre-scaled because it already does this - // when setting up its context. But see how we take the actual pre-scale - // in the constructor. - } - - float canvas::pre_scale() const - { - // Quartz-2D does not need to be pre-scaled because it already does this - // when setting up its context. - return 1.0; // Pre-scale is always 1.0 - } - void canvas::translate(point p) { CGContextTranslateCTM(CGContextRef(_context), p.x, p.y); @@ -621,8 +607,9 @@ void round_rect(canvas& c, rect bounds, float radius) void canvas::shadow_style(point offset, float blur, color c) { + auto [scx, scy] = device_to_user({1.0, 1.0}); CGContextSetShadowWithColor( - CGContextRef(_context), CGSizeMake(offset.x, -offset.y), blur, + CGContextRef(_context), CGSizeMake(offset.x/scx, -offset.y/scx), blur, [ [NSColor colorWithRed : c.red diff --git a/lib/impl/skia/canvas.cpp b/lib/impl/skia/canvas.cpp index b0e1ddfb..9394cb3a 100755 --- a/lib/impl/skia/canvas.cpp +++ b/lib/impl/skia/canvas.cpp @@ -47,8 +47,8 @@ namespace cycfi::artist void save(); void restore(); - - float _pre_scale = 1.0; + affine_transform get_inv_affine() const; + void set_inv_affine(affine_transform xf); static SkPaint& get_fill_paint(canvas const& cnv); @@ -79,6 +79,7 @@ namespace cycfi::artist state_info_stack _stack; SkPaint _clear_paint; + affine_transform _inv_affine; }; canvas::canvas_state::canvas_state() @@ -135,25 +136,25 @@ namespace cycfi::artist return cnv._state->fill_paint(); } - canvas::canvas(canvas_impl* context_) - : _context{context_} - , _state{std::make_unique()} + affine_transform canvas::canvas_state::get_inv_affine() const { + return _inv_affine; } - canvas::~canvas() + void canvas::canvas_state::set_inv_affine(affine_transform xf) { + _inv_affine = xf; } - void canvas::pre_scale(float sc) + canvas::canvas(canvas_impl* context_) + : _context{context_} + , _state{std::make_unique()} { - scale(sc, sc); - _state->_pre_scale = sc; + _state->set_inv_affine(transform().invert()); } - float canvas::pre_scale() const + canvas::~canvas() { - return _state->_pre_scale; } void canvas::translate(point p) @@ -178,21 +179,30 @@ namespace cycfi::artist point canvas::device_to_user(point p) { - auto scale = _state->_pre_scale; - auto mat = _context->getTotalMatrix(); - (void) mat.invert(&mat); - SkPoint skp; - mat.mapXY(p.x * scale, p.y * scale, &skp); - return {skp.x(), skp.y()}; + // Get the current transform + auto af = transform(); + + // Undo the initial transform + auto xaf = af * _state->get_inv_affine(); + + // Map the point to the inverted `xaf` transform + auto up = xaf.invert().apply(p); + + return {float(up.x), float(up.y)}; } point canvas::user_to_device(point p) { - auto scale = _state->_pre_scale; - auto mat = _context->getTotalMatrix(); - SkPoint skp; - mat.mapXY(p.x, p.y, &skp); - return {skp.x() / scale, skp.y() / scale}; + // Get the current transform + auto af = transform(); + + // Undo the initial transform + auto xaf = af * _state->get_inv_affine(); + + // Map the point to the `xaf` transform + auto up = xaf.apply(p); + + return {float(up.x), float(up.y)}; } affine_transform canvas::transform() const @@ -392,11 +402,8 @@ namespace cycfi::artist void canvas::shadow_style(point offset, float blur, color c) { - constexpr auto blur_factor = 0.4f; - - auto matrix = _context->getTotalMatrix(); - auto scx = matrix.getScaleX() / _state->_pre_scale; - auto scy = matrix.getScaleY() / _state->_pre_scale; + constexpr auto blur_factor = 1.0f; + auto [scx, scy] = device_to_user({1.0, 1.0}); auto shadow = SkImageFilters::DropShadow( offset.x / scx diff --git a/lib/include/artist/canvas.hpp b/lib/include/artist/canvas.hpp index add56783..029bdbe2 100755 --- a/lib/include/artist/canvas.hpp +++ b/lib/include/artist/canvas.hpp @@ -47,9 +47,6 @@ namespace cycfi::artist explicit operator bool() const; bool operator!() const; - void pre_scale(float sc); - float pre_scale() const; - /////////////////////////////////////////////////////////////////////////////////// // Transforms void translate(point p);