Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correctly handle transforms in SVG arcTo #13640

Merged
merged 1 commit into from Jan 7, 2024

Conversation

ianthomas23
Copy link
Member

Fixes #12699.

Rects with rounded corners are currently rendered incorrectly using the SVG output backend. This is due to a bug in SVGRenderingContext2D.arcTo which is called once for each rounded corner. The calculations in arcTo make use of the last rendered point which is in the member variable __currentPosition and is updated at the beginning and end of every SVG path rendered. The bug is that __currentPosition is stored after being transformed by the current transform stack (SVGRenderingContext2D._transform) whereas the arguments to arcTo are not transformed. Combining transformed and untransformed points can clearly give incorrect results. Up until recently this has not been a problem, but now we are using rects with rounded corners that may be rotated using the angle property or translated if they are part of a title.

The fix is to inverse transform the __currentPosition before using it in arcTo. I have added an inverse() function to AffineTransform that is implemented using DOMMatrix.inverse so that we don't have to implement our own maths. There are a number of existing visual tests that show this working correctly now. Note that even the unrotated visual image is altered as it now correctly has a half pixel offset that would not have been visible to the typical human eye. I've also added a unit test for AffineTransform.inverse.

Simple demonstration code:

from bokeh.layouts import row
from bokeh.plotting import figure, show

ps = []
for backend in ('canvas', 'svg'):
    p = figure(width=500, height=250, output_backend=backend, title=backend)
    ps.append(p)
    p.rect(x=[0, 1, 2, 3], y=0, width=0.8, height=0.4, angle=[0, 0.3, 0.6, 0.9],
           line_width=5, fill_color="orange", line_color="black", fill_alpha=0.8,
           border_radius=35)

show(row(ps))

which gives before this PR:
before
and after:
after

Copy link

codecov bot commented Jan 7, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Comparison is base (5854a25) 92.56% compared to head (f252952) 92.56%.

Additional details and impacted files
@@             Coverage Diff             @@
##           branch-3.4   #13640   +/-   ##
===========================================
  Coverage       92.56%   92.56%           
===========================================
  Files             323      323           
  Lines           20509    20509           
===========================================
  Hits            18985    18985           
  Misses           1524     1524           

@mattpap mattpap added this to the 3.4 milestone Jan 7, 2024
@ianthomas23 ianthomas23 merged commit 204ee13 into branch-3.4 Jan 7, 2024
29 of 30 checks passed
@ianthomas23 ianthomas23 deleted the ianthomas23/12699_svg_arcTo branch January 7, 2024 21:43
@mattpap mattpap mentioned this pull request Jan 7, 2024
22 tasks
mattpap added a commit that referenced this pull request Jan 8, 2024
* Add a regression test for issue #8890 (#13572)

* Don't register keyup twice in `AutocompleteInput` (#13577)

* Don't register keyup twice in AutocompleteInput

* Pin pytest-asyncio to version 0.21.1

* Link sub-coordinate and context dependent ranges in RangesUpdate (#13603)

* Fix support for global/local imported stylesheets (#13559)

* Compatibility with Chromium 110

* Robustify unit tests involving browser output (#13602)

* Multiple density estimate plot (#13527)

* added sample data

* created density plot

* added gallery images and json

* sorted import order

* clarified plot description

* refactored plotting file

* changed tick formatting style

* deleted unused import

* deleted whitespace

* additional file refactoring

* pyramid example plot (#13596)

* added sample data

* created plot and added plot  description

* added gallery image

* minor edits

* modified plot title

* added bar labels to plot

* removed whitespace

* post-review

* changed color palette

* added plot image

* added extra tick markers

* Remove unnecessary arcTo calls in round_rect (#13627)

* Update license and copyright statements to 2024 (#13630)

* Use `ruff` to ban `typing_extensions` at the top-level (#13633)

* Upgrade to ruff 0.1.11

* Enable TID rules and disable TID252 for now

* Ban `typing_extensions` module at the top-level

* Remove test_no_typing_extensions_common

* Import `typing_extensions` under `TYPE_CHECKING` in `*.pyi`

* Correctly handle transforms in SVG arcTo (#13640)

* ban PIL and other imports with ruff (#13639)

* fix indentation in sphinx extentions (#13549)

* fix indentation in property mixins (#13514)

* fix indentation of default strings with dedent from textwrap

* add missing words in property_mixins.py

* fix indentation in tools.py

* remove dedent block and introduce ALPHA_DEFAULT_HELP and COLOR_DEFAULT_HELP

* change order of imports

* Restored broken API links (#13528)

* restored broken API links

* modified broken API path

* Allow newer tornado and pandas in test-minimal-deps (#13635)

* Add release notes

* Update switcher.json

* avoid_Sphinx ThemeError and set Sphinx to a minimum of 7.1.0 (#13560)

* fix some sphinx warnings (#13609)

* fix some sphinx warnings

* don't make the first line bold

* fix warnings caused by sampledata (#13613)

* add forensic glass and emissions to sampledata.rst (#13615)

---------

Co-authored-by: Azaya <99359668+Azaya89@users.noreply.github.com>
Co-authored-by: Ian Thomas <ianthomas23@gmail.com>
Co-authored-by: Bryan Van de Ven <bryan@bokeh.org>
Co-authored-by: Moritz Schreiber <68053396+mosc9575@users.noreply.github.com>
@mattpap mattpap modified the milestones: 3.4, 3.3.3 Jan 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ctx.arcTo() is broken in SVG backend
2 participants