[Rd] Tight bounding box around text in graphics?

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Tue Sep 26 14:53:00 CEST 2023


I've done some exploring, and things aren't working out as I would have 
expected.  Here's an example:

   library(grid)
   library(ragg)

   agg_png("test.png")
   pushViewport(viewport(gp = gpar(cex = 5)))
   y <-  c(0.2, 0.4, 0.6)

   texts <- c("東京", "Tokyo", "Tokyo 東京")

   convertHeight(stringDescent(texts), "npc")

   grid.text(texts,
             x = 0, y = y, just = c(0,0))
   grid.segments(x0 = 0, x1 = 1, y0 = y, y1 = y)

   popViewport()
   dev.off()

(In case it doesn't make it through in email, the texts are Tokyo 
written in kanji, then in roman letters, then in both.)

What I see is that the kanji string is being reported as having zero 
descent, but in the resulting test.png file, it's clear that it does 
descend below the baseline.

I can think of lots of reasons for this discrepancy; can you suggest 
which is likeliest?

  - I have some misconception about how this is supposed to work
  - The Kanji font on my system misreports some measurements
  - The ragg::agg_png() device misreports measurements
  - Some other bug somewhere.

Duncan


On 26/09/2023 5:57 a.m., Duncan Murdoch wrote:
> Thanks!  I said "base graphics" in my question, but I really have no
> objection to using grid graphics, so I'll explore those grid functions.
> 
> Duncan Murdoch
> 
> On 25/09/2023 3:53 p.m., Paul Murrell wrote:
>> Hi
>>
>> strheight(), which is based GEStrHeight(), is pretty crude, not only
>> ignoring descenders, but also only considering the ascent of the overall
>> font (capital "M").
>>
>> There is a GEStrMetric(), which returns character-specific ascent and
>> descent, but that is only currently exposed via grid::stringAscent() and
>> grid::stringDescent().  There is also grid::stringHeight(), which is as
>> unsubtle as strheight().
>>
>> For example, these are all the same (just font ascent) ...
>>
>>    > strheight("y", "in")
>> [1] 0.1248031
>>    > strheight("x", "in")
>> [1] 0.1248031
>>    > strheight("M", "in")
>> [1] 0.1248031
>>
>> ... and these are all the same ...
>>
>>    > convertHeight(stringHeight("y"), "in")
>> [1] 0.124803149606299inches
>>    > convertHeight(stringHeight("x"), "in")
>> [1] 0.124803149606299inches
>>    > convertHeight(stringAscent("M"), "in")
>> [1] 0.124803149606299inches
>>
>> ... but these have more detail ...
>>
>>    > convertHeight(stringAscent("y"), "in")
>> [1] 0.0936023622047244inches
>>    > convertHeight(stringDescent("y"), "in")
>> [1] 0.0416010498687664inches
>>    > convertHeight(stringAscent("x"), "in")
>> [1] 0.0936023622047244inches
>>    > convertHeight(stringDescent("x"), "in")
>> [1] 0inches
>>    > convertHeight(stringHeight("M"), "in")
>> [1] 0.124803149606299inches
>>    > convertHeight(stringDescent("M"), "in")
>> [1] 0inches
>>
>> In theory, it should not be difficult to add a graphics::strascent() and
>> graphics::strdescent() if that would help.
>>
>> Paul
>>
>> On 26/09/23 08:06, Duncan Murdoch wrote:
>>> I've mentioned in previous messages that I'm trying to redo rgl text.
>>>
>>> Part of what I need is to measure the size of strings in pixels when
>>> they are drawn by base graphics.
>>>
>>> It appears that
>>>
>>> strwidth(texts, "user", cex = cex, font = font, family = family)
>>>
>>> gives accurate measurements of the width in user coordinates. I've got
>>> those set up to match pixels, so I'm fine here.
>>>
>>> However, the equivalent call for strheight() only measures height above
>>> the baseline according to the docs, and indeed the number is smaller
>>> than the size of what's displayed. Descenders (e.g. the tail of "y")
>>> aren't counted.
>>>
>>> Is there a way to measure how far a character might descend? Is it
>>> valid to assume it won't descend more than a line height below the top
>>> of the char?
>>>
>>> I have a partial solution -- textshaping::shape_text gives a "height"
>>> value that includes lots of space below the character, and a
>>> "top_border" value that measures from the top of the textbox to the
>>> baseline. So I think `height - top_border` would give me what I'm
>>> asking for. But this only works with graphics devices in the ragg
>>> package. Is there a general solution?
>>>
>>> Duncan Murdoch
>>>
>>> ______________________________________________
>>> R-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
>>> <https://stat.ethz.ch/mailman/listinfo/r-devel>
>>
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.png
Type: image/png
Size: 11907 bytes
Desc: not available
URL: <https://stat.ethz.ch/pipermail/r-devel/attachments/20230926/854399a2/attachment.png>


More information about the R-devel mailing list