foliojs / fontkit

An advanced font engine for Node and the browser
1.46k stars 219 forks source link

How to use fontkit to add new words to the font? #231

Closed StringKe closed 4 years ago

StringKe commented 4 years ago

How to use fontkit to add new words to the font?

I need to add an extra character to the font to detect the maximum height of the font in canvas (toimagedata).

I checked the documentation and still do n’t know how to add a new word to the font file I have now

Pomax commented 4 years ago

Adding an artificial character to a font does not tell you anything about the maximum height of strings that can be typeset with the font - especially with GPOS compositioning, there is technically no height limit. You can keep stacking combining diacritics forever. So what do you actually need to do that you think requires knowing the height?

StringKe commented 4 years ago

There is no line break in svg text, I need to know the height of the font to handle the line height after line break

Pomax commented 4 years ago

In that case what you're looking for is the baseline-to-baseline distance, which is in font units, and can be converted to "real" em units using fontsize-in-em * computedBTBD / head.unitsPerEm.

However, note that if you're doing this in the browser, the easiest way by far is to just have JS generate an SVG document with your font with one bit of text without a break, and one piece of text with a break, and then just directly compute the pixel difference between those two, because that's your "true" baseline-to-baseline value:

<svg style="opacity:0"><text>a</text><text style="white-space:pre">a
b</text></svg>

<script>
  const textElements = Array.from(document.querySelectorAll('svg text'));
  const heights = textElements.map(t =>t.getBoundingClientRect().height);
  const btbd = heights[1] - heights[0];
  console.log(`line height: ${btbd}px`);
</script>

With that linebreak in the SVG code being intentional, of course.

And then you can set whatever font you want in CSS, no fontkit required:

svg text {
  font-family: "Impact";
  font-size: 21px;
}

That will give a BTBD of 25px, for example.

StringKe commented 4 years ago

In that case what you're looking for is the baseline-to-baseline distance, which is in font units, and can be converted to "real" em units using fontsize-in-em * computedBTBD / head.unitsPerEm.

However, note that if you're doing this in the browser, the easiest way by far is to just have JS generate an SVG document with your font with one bit of text without a break, and one piece of text with a break, and then just directly compute the pixel difference between those two, because that's your "true" baseline-to-baseline value:

<svg style="opacity:0"><text>a</text><text style="white-space:pre">a
b</text></svg>

<script>
  const textElements = Array.from(document.querySelectorAll('svg text'));
  const heights = textElements.map(t =>t.getBoundingClientRect().height);
  const btbd = heights[1] - heights[0];
  console.log(`line height: ${btbd}px`);
</script>

With that linebreak in the SVG code being intentional, of course.

And then you can set whatever font you want in CSS, no fontkit required:

svg text {
  font-family: "Impact";
  font-size: 21px;
}

That will give a BTBD of 25px, for example.

@Pomax Thank you, fontsize-in-em * computedBTBD / head.unitsPerEm. This formula can calculate the height of the font, is there another formula that can calculate the width of the text in the font (approximately), I have read many font specifications , Wiki, google did not find the relevant formula