I need some help to make truetype information available for a Ruby script/extension

Some months ago I created an extension to import SVG files into Sketchup. It works quite nice for the import of ‘normal 2D geometry’ (edges and faces on the groundplane (Z=0)). One of the outstanding issues that I still had with this extension was related to the import of SVG texts, and how they translate into 3D-text objects in Sketchup. A first problem was the absence of a font baseline in the Sketchup Ruby API, which led to unalligned text nodes on a single line of text. This is solved now.

The other outstanding issue with texts is related to the text sizes. In SVG textsize can be defined via multiple ‘units’ (pt, px, pc, em). All values expressed in these ‘units’ are converted into a kind of ‘virtual units’ (based on pixels). SVG is - by nature - ‘scaleable’, and thus ‘unit-less’.

Whatever units (if any) that are specified in the SVG files, NONE of these quantities resulted in a correct scaling of the fonts when the SVG file was imported into Sketchup. This became clear, after I drawed ‘bounding boxes’ surrounding the textblocks in a 2D SVG editor, then exporting the SVG with the 2D Editor, and finally running the SVG Importer in Sketchup.

The bounding boxes were correctly sized, but the ‘embedded’ texts in these bounding boxes did not correspond with the bounding box size (i.e. mostly the texts were oversized). The exported SVG was however correctly specified, since all other SVG client applications (browsers, online editors, …) showed all textblocks that fitted perfectly within the corresponding bounding boxes.

So, the Sketchup Importer didn’t work correctly for texts, and required an extra scaling transformation. Initially, I assumed that a scaling factor of 0.7500 did the job, but after creating texts with multiple fonts, it appeared that the applicable scaling factors varied between 0.40627 and 1.62120. So, a generic scaling by 0.75000 wasn’t the solution. Further analysis indicated that all glyphs and all sizes of a specific font always had the same scaling factor, also when shown on multiple displays with different form factors and resolutions.

As a last resort, I finally dived into the typography parameters of the ttf.-files for the various fonts on my pc. After a deep analysis and multiple tests, I found that the scaling factor that is apparently used by Sketchup for rendering its 3D texts (on Windows) is equal to the quotient of the sTypoAscender and the unitsPerEm values in the .ttf-file. The first value resides in the OS/2 and Windows Metrics Table (OS/2), and the second value is stored in the Font Header Table (head).

Unfortunately, it’s (way) beyond my skills to retrieve these values from the ttf-files, and make them available for further processing in my Ruby script. I’ve done the above analysis, so, I hope that somebody with experience in programming can help me with this problem. In case that any person who is willing to help, would need any further information about my analysis so far, please don’t hesitate to ask (but unsure whether I will be able to provide detailed answers that surpass my very limited technical capabilities…).

I ask the Gemini AI: Are there any Ruby gems to read TTF files? … the reply:

Yes, there are a few Ruby gems that can read and parse TTF files, with the most notable one being TTFunk .

TTFunk

TTFunk is a popular and well-maintained gem designed for parsing both TrueType and OpenType fonts. It’s written in pure Ruby[1], which means it doesn’t require any external libraries or dependencies outside of the Ruby ecosystem. It provides a simple and easy-to-use API to access the various “tables” within a font file.

Key Features

  • Font Information: You can easily extract metadata like the font’s name, family, ascent, and descent.
  • Character Mapping: It can read the character-to-glyph mappings, allowing you to determine which characters a font supports.
  • Font Subsetting: The gem has limited functionality for creating a smaller subset of a font file, which is useful for tasks like embedding only the necessary characters in a PDF.

It’s widely used as a core dependency in other projects, most notably the Prawn PDF generation library, which speaks to its reliability and robustness.


Generally, the SketchUp Extensibility Team requires that developers wrap a gem within there own namespace modules so that it will not interfere with other extensions, that might (for example) try to load a different version of the same gem.

So, you should package such gems with your extension (properly wrapped) rather than having Ruby install the gem from the Rubygems server.

Note concerning the Prawn gem (which is difficult to use with SketchUp,):

  • While it’s maintained by the same developers and is a core dependency for Prawn, TTFunk’s functionality for reading and parsing font files is completely independent. It does not require any of Prawn’s code to run, nor does it have Prawn as a dependency itself.

[1] Implemented in pure Ruby means you won’t need to deal with compiling for both Mac And Windows for every minor Ruby version used by SketchUp.

@Dan Rathbun, Thanks a lot for your proposed solution :+1: . I’m hopeful that it will allow me to finally fix the outstanding font scaling issue while importing SVG files. From a quick review of the Github code (and examples) for this gem, it appears to be ‘relatively straightforward’ to extract the required typographic parameters from the .ttf-files.

Of course, a properly installed gem is a prerequisite…

I’m not familiar with installing gems (never did it before). Therefore, I researched online how this must be done. In my previous post, I forgot to mention that I’m a user of Sketchup Make 2017. If I understand it correctly, the Ruby version of this old Sketchup version is 2.2.4? I therefore assume that it’s not possible to install the most recent versions of the TTFunk gem, but that I must ‘downgrade’ to version 1.5.1 of this gem? Can you please confirm whether my assumption is correct?

As I’m not familiar with installing Ruby gems, and all information that I can find about ‘installing Ruby gems’ comes from the Rubygems website, can you please clarify a bit what you mean with your remark that I should not install from the Rubygems server, but that I must do some ‘properly wrapped packaging with my extension’. Does this mean that I can’t just follow the installation procedures that are documented on the Rubygems website? If so, what’s the ‘right way of doing it’ in my situation then?

You may have missed what I said about installing gems in SketchUp’s shared ObjectSpace

Quoting myself:

If you are doing this importer for only yourself, you can use (or to start testing):

Gem::install("ttfunk", "1.5.1") # Should load version 1.5.1

REF: module Gem - Documentation for Ruby 3.2

Gem::install("ttfunk") # This gives me version 1.8.0

A conditional install would be:

if RUBY_VERSION.to_f >= 2.7
  Gem::install("ttfunk")
else
  Gem::install("ttfunk", "1.5.1")
end

Correct.

It appears so. The AI said …

The dependency on Ruby 2.7 came into play with the release of TTFunk version 1.6.0 in January 2020.

All versions in the 1.5.x series and earlier were compatible with older Ruby versions, including 2.2.4. When the project released version 1.6.0, it introduced a new minimum Ruby requirement of 2.7 due to the new syntax and features used in its code.


It also looks like it has a dependency with “bigdecimal” which is included in the standard library. It became a bundled gem in Ruby versions 2.7+. So you need not worry about deploying it.
But you do need to require it for TTFunk. Ie …

require 'bigdecimal'

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.