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

Line breaks don't work #4

Closed
AllanCameron opened this issue Nov 16, 2021 · 5 comments
Closed

Line breaks don't work #4

AllanCameron opened this issue Nov 16, 2021 · 5 comments

Comments

@AllanCameron
Copy link
Owner

The current code doesn't allow for line breaks in text strings due to the string width calculations.

For example:

df <- data.frame(x = 1:1000, y = 1, z = "This is a perfectly\nflat label")

ggplot(df, aes(x, y, label = z)) +
  geom_textpath(size = 6, linewidth = 0)

image

Whereas, we probably want the equivalent of:

p <- ggplot(df1, aes(x, y, label = z)) +
  geom_textpath(size = 6, vjust = -0.2, linewidth = 0) +
  geom_textpath(size = 6, vjust = 1.2, data = df2, linewidth = 0)

Which gives us

p

image

and

p + coord_polar(start = pi)

image

This means that to implement line breaks, we probably need to find all instances of \n , \r and \r\n, split the text at those points and create multiple paths with individually calculated vjust values.

@teunbrand
Copy link
Collaborator

teunbrand commented Nov 16, 2021

I think if we switch to {textshaping} instead of using strwidth(), we automatically get this taken care of in the y_offset parameter. Plus, it should taking care of kerning so that text would look more natural.

library(textshaping)

txt <- "This is a perfectly\nflat label"

shape <- shape_text(txt)
cbind(shape$shape, letter = unlist(strsplit(txt, character())))
#>    glyph index metric_id string_id  x_offset y_offset x_midpoint letter
#> 1      0    55         1         1  0.000000 13.40625   3.656250      T
#> 2      1    75         1         1  7.328125 13.40625   3.328125      h
#> 3      2    76         1         1 14.000000 13.40625   1.328125      i
#> 4      3    86         1         1 16.671875 13.40625   3.000000      s
#> 5      4     3         1         1 22.671875 13.40625   1.656250       
#> 6      5    76         1         1 26.000000 13.40625   1.328125      i
#> 7      6    86         1         1 28.671875 13.40625   3.000000      s
#> 8      7     3         1         1 34.671875 13.40625   1.656250       
#> 9      8    68         1         1 38.000000 13.40625   3.328125      a
#> 10     9     3         1         1 44.671875 13.40625   1.656250       
#> 11    10    83         1         1 48.000000 13.40625   3.328125      p
#> 12    11    72         1         1 54.671875 13.40625   3.328125      e
#> 13    12    85         1         1 61.343750 13.40625   2.000000      r
#> 14    13    73         1         1 65.343750 13.40625   1.656250      f
#> 15    14    72         1         1 68.671875 13.40625   3.328125      e
#> 16    15    70         1         1 75.343750 13.40625   3.000000      c
#> 17    16    87         1         1 81.343750 13.40625   1.656250      t
#> 18    17    79         1         1 84.671875 13.40625   1.328125      l
#> 19    18    92         1         1 87.343750 13.40625   3.000000      y
#> 20    19     0         1         1 93.343750 13.40625   4.500000     \n
#> 21    20    73         1         1  0.000000  0.00000   1.656250      f
#> 22    21    79         1         1  3.328125  0.00000   1.328125      l
#> 23    22    68         1         1  6.000000  0.00000   3.328125      a
#> 24    23    87         1         1 12.671875  0.00000   1.656250      t
#> 25    24     3         1         1 16.000000  0.00000   1.656250       
#> 26    25    79         1         1 19.328125  0.00000   1.328125      l
#> 27    26    68         1         1 22.000000  0.00000   3.328125      a
#> 28    27    69         1         1 28.671875  0.00000   3.328125      b
#> 29    28    72         1         1 35.343750  0.00000   3.328125      e
#> 30    29    79         1         1 42.015625  0.00000   1.328125      l

Created on 2021-11-16 by the reprex package (v1.0.0)

@AllanCameron
Copy link
Owner Author

I'm keen to minimize dependencies, but this does look very useful. Getting kerning right will help , but our biggest issue is really "tracking" - i.e. making the general text spacing right. I don't think its possible to get this exactly right, since by definition if text is on a curve then the spacing between the tops of the letters will be different from the bottom of the letters. However, I think I more or less fixed the tracking on my previous merge - the spiral example on the readme looks much better now, with consistent spacing as the curvature changes along the path. Previously, the spacing was too large when the text was above a tight curve, and too small when it was below a tight curve.

@AllanCameron
Copy link
Owner Author

But yes, I'm happy to take a look at textshaping to get the string positioning better.

@teunbrand
Copy link
Collaborator

I just realised that textshaping::shape_text() is as good as identical to systemfonts::shape_text(), which seems like a more versatile dependency if we're to take one (it also has a tracking argument, which we could expose to the user if they wish to fiddle with it). I generally agree that we should keep dependencies to a minimum (dependencies of ggplot2 excepted), but I also don't want to become a professional typographer to build/maintain custom kerning and tracking functions.

@teunbrand teunbrand mentioned this issue Nov 18, 2021
8 tasks
@AllanCameron
Copy link
Owner Author

This feature is now implemented, though not working perfectly. To keep focused on fixing specifics, I'm closing this as a specific issue at the moment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants