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

Support for GPOS table parsing #19

Closed
nktpro opened this issue Feb 11, 2014 · 29 comments
Closed

Support for GPOS table parsing #19

nktpro opened this issue Feb 11, 2014 · 29 comments

Comments

@nktpro
Copy link
Contributor

nktpro commented Feb 11, 2014

Most fonts from Google repo (http://www.google.com/fonts) use the GPOS table for kerning data, and many don't include the old "kern" section, which currently causes missing kerning data from opentype.js.

IMO this is an important feature to support. Safari and Firefox both turn on kerning by default for all text. Not being able to take kerning into account leads to:

  • Inconsistent drawing results between native text and custom ones on the canvas elements.
  • Inability to accurately measure the size of a piece of text with kerning = true, which prevents usage of opentype.js for layout calculation that relies on text measurement.
@fdb
Copy link
Contributor

fdb commented Feb 11, 2014

You're absolutely right, we need to support GPOS.

Thanks for the tip on suggesting the Google repo; that's a great set of test cases that I can use for regression tests.

@nktpro
Copy link
Contributor Author

nktpro commented Feb 24, 2014

I've been searching left and right, and it doesn't seem like there's any other working implementation in JavaScript for GPOS table. Having this in opentype.js will be extremely valuable for the JS community.

The most popular and mature library seems to be TTX/FontTools written in Python. Extracting GPOS table is a matter of executing:

ttx -t GPOS /path/to/font.ttf

And then convert the XML output to JS objects. Still, it sucks not being to do this in a pure JS stack at the moment.

Perhaps TTX/FontTools could serve as a good implementation reference?

@behdad
Copy link

behdad commented Feb 24, 2014

I highly recommend against reinvent a shaping engine in JavaScript. If you have to, check https://github.com/prezi/harfbuzz-js

For a JS-only solution to loading GPOS, check https://github.com/Pomax/A-binary-parser-generator by @Pomax

@davelab6
Copy link

I expect opentype.js just needs fontTools style access to the data, not
harfbuzz style interpretation of the data

But yes, pomax's solution is better than coding it directly :)

@nktpro
Copy link
Contributor Author

nktpro commented Feb 24, 2014

Thanks @behdad for pointing out @Pomax repo. Unfortunately his current OpenType.spec file doesn't have any definition for GPOS table (it's empty):

https://github.com/Pomax/A-binary-parser-generator/blob/master/OpenType.spec

I know I can try to dig up the spec and put in the missing piece, it's just a real PITA not having anything that works out of the box in JS.

@nktpro
Copy link
Contributor Author

nktpro commented Feb 24, 2014

Just want to add that the ability to measure text geometry (precisely with kerning) in pure JS is priceless for future web apps. (especially ones using Canvas / WebGL rendering)

Currently one can simply use native canvas measureText() for width. However the process has to be done in the main UI thread (no Canvas context access in Workers), and it's very slow for large amount of text.

Imagine being able to perform application layout in multi-threaded manner, with multiple independent chunks of texts being measured in parallel from multiple Workers.

opentype.js (and some other libraries) opens up the possibility to achieve that. The only missing piece I found was kerning data in GPOS table.

@davelab6
Copy link

Behdad, want to do it? :)

@Pomax
Copy link
Contributor

Pomax commented Feb 25, 2014

I'm currently busy with writing a glyphlet font generator (in a way that would be extensible to larger fonts in the future" but I might be able to revisit the parser generator after I'm done with that.

Getting in the spec model for the common table format script/feature/lookup will be a bit of a challenge =)

@davelab6
Copy link

What is a glyphlet font?
On 25 Feb 2014 16:00, "Mike Kamermans" [email protected] wrote:

I'm currently busy with writing a glyphlet font generator (in a way that
would be extensible to larger fonts in the future" but I might be able to
revisit the parser generator after I'm done with that.


Reply to this email directly or view it on GitHubhttps://github.com//issues/19#issuecomment-36023027
.

@Pomax
Copy link
Contributor

Pomax commented Feb 25, 2014

a font containing a single target glyph (not counting empty glyphs used to effect things like ligature substitution). In this case it's for dynamic fonts with a single outline define in SVG or Type2, and then the js builds it on page load for use as a tiny, tiny otf/woff

@behdad
Copy link

behdad commented Feb 25, 2014

opentype.js (and some other libraries) opens up the possibility to achieve that.
The only missing piece I found was kerning data in GPOS table.

Unfortunately you are wrong. The only missing piece is the equivalent of all of HarfBuzz. Unless you only care about simple scripts and no ligatures that is. This means, no Arabic, no Indic, etc.

@davelab6
Copy link

Like adobe blank but better in some way?
On 25 Feb 2014 16:42, "Mike Kamermans" [email protected] wrote:

a font containing a single target glyph (not counting empty glyphs used to
effect things like ligature substitution). In this case it's for dynamic
fonts with a single outline define in SVG or Type2, and then the js builds
it on page load for use as a tiny, tiny otf/woff


Reply to this email directly or view it on GitHubhttps://github.com//issues/19#issuecomment-36028026
.

@Pomax
Copy link
Contributor

Pomax commented Feb 25, 2014

adobe blank is an empty font for testing other-font-support with full unicode support, Think of glyphlet fonts more as subset fonts where the subset is a single character. It's a bypass to get a decorative graphic piece of "text" injected onto a page without needing to download a full font, and without needing to download a potentially large number of small files. (you give up some power in terms of kern/GPOS, but typically you're not using them inside running text so kerning is rarely an issue)

@davelab6
Copy link

So a 'glyphlet font generator' is a 'extreme subsetter'? :)

@Pomax
Copy link
Contributor

Pomax commented Feb 25, 2014

haha, without a basefont to subset from, yes =P (especially with minimal:true and compliant:false, which rips out everything browsers don't look at, plus a few things browsers look at until OTS gets updated so they don't =)

@davelab6
Copy link

On 25 February 2014 18:16, Mike Kamermans [email protected] wrote:

haha, without a basefont to subset from, yes =P

So this is something like simpleSvgDrawing2CffFont.js ?

@Pomax
Copy link
Contributor

Pomax commented Feb 25, 2014

I'm not tying it down to an "anything" that isn't a glyphlet font generator =)The easiest POC while I work on it for testing etc. is using an svg path for the glyph outlines.

@Pomax
Copy link
Contributor

Pomax commented Feb 25, 2014

on a more thread-relevant note: for completion you probably want GSUB as well as GPOS, rather than merely GPOS. It uses the same OpenType "common table layout" for encoding the script/feature/lookup "tree" (just like GDEF, BASE and JSTF), so most of the work for GPOS automatically gives you most of the code for GSUB, too. Not sure if I'd go with the xml from TTX and then making objects out of that, given the highly connected graph that is the common table layout structs: you probably want to read the opentype spec on how those work and instead look at the .py code for the common table layouts. It's not one-on-one containment, making it quite messy if you're basing it on what TTX generates, rather than the structs it uses to generate.

@Pomax
Copy link
Contributor

Pomax commented Mar 3, 2014

So I finished part of the work I wanted to do with glyphlet fonts, yield code that is pretty compatible with opentype.js (although I rewrote my single file POC to a require.js module based codebase, which I can strongly recommend for opentype.js, too =). It has GSUB at the moment, but no GPOS (yet? although GPOS for a single glyph doesn't make the most sense of course); https://github.com/Pomax/CFF-glyphlet-fonts/blob/gh-pages/src/SFNT/tables/GSUB.js plus the structs from https://github.com/Pomax/CFF-glyphlet-fonts/tree/gh-pages/src/SFNT/tables/common and https://github.com/Pomax/CFF-glyphlet-fonts/tree/gh-pages/src/SFNT/tables/common/GSUB work together to generate GSUB tables, but there is a provision for a parse comment, which is more opentype.js's territory (although that said, I might simply write the parsing as generically as I can and see what that means for understanding what kind of syntax I need to make GSUB work as part of the .spec file for the binary parser generator project. Offsets to structs relative to "the most recent local field" are ... tricky)

@davelab6
Copy link

Isn't https://github.com/prezi/harfbuzz-js useful for this as Behdad said? Reading the tables is straightforward but interpreting them to know which glyphs to show is a huge task - done by harfbuzz

@fdb
Copy link
Contributor

fdb commented Mar 18, 2014

Thanks @Pomax! The declarative tables parsing was something that I used initially in opentype.js. I'll look into your work soon.

I have absolutely no feel for how many work it is to support GPOS and GSUB. Does it make sense to have simple, built-in support for Western fonts (basically the same data as I would get from the KERN table), and then use harfbuzz-js as an optional dependency for more complex scripts?

@Pomax
Copy link
Contributor

Pomax commented Mar 18, 2014

I'd say no to treating western as somehow special just because that's what you're used to in your browsing experience (it's certainly mine, but I try to stay far away from treating latin as somehow special).

Also, to using harfbuzz: yes and no. Harfbuzz.js definitely sounds like the way to go for "proper full blown parsing", but I had a look at trying to use it, and it has essentially no documentation, so if we want harfbuzz uptake it's going to need some docs that don't require people to build harfbuzz.js and the docs from source. It needs to be an actual JS library with an API instead of something that can be compiled out of regular harfbuzz.

@moyogo
Copy link
Contributor

moyogo commented Mar 18, 2014

Besides Latin, Greek and Cyrillic scripts are more complex than you think. Some languages or uses need relatively complex GPOS and GSUB.

@fpirsch
Copy link
Collaborator

fpirsch commented Mar 26, 2014

@fdb

Does it make sense to have simple, built-in support for Western fonts (basically the same data as I would get from the KERN table), and then use harfbuzz-js as an optional dependency for more complex scripts?

Being able to extract from the GPOS table the same data there is in the kern table would certainly be a good start. Full support could be a second step, maybe with the help of an external dependency.

@Pomax
Copy link
Contributor

Pomax commented Mar 26, 2014

that's not really how GPOS works though. GPOS is basically a generic set of datastructures, where the only reason it's latin is because the script tag happens to be "latn", so either you pretty much already have your full GPOS, or you don't. The kern table is a lot simpler, but also increasingly less available as more fonts switch to GPOS

@fpirsch
Copy link
Collaborator

fpirsch commented Mar 26, 2014

I was just talking about getting the Pair Adjustment Positioning Subtables, format 1 and 2. I'm not talking about restricting to latin, which makes little sense, but restricting to the basic GPOS kerning feature. Other GPOS features and subtables could come later.

@fpirsch
Copy link
Collaborator

fpirsch commented Mar 28, 2014

Just submitted a PR : #20
The demo looks really better with Desyrel or EBGaramond fonts.
However GPOS support is still far from complete and there's a lot of room for improvement.

@davelab6
Copy link

davelab6 commented Nov 6, 2014

@nktpro does #20 resolve this to your satisfaction? If so this issue can be closed

@nktpro
Copy link
Contributor Author

nktpro commented Nov 7, 2014

@davelab6 Although full GPOS support is not yet complete, I think it's good enough for now. Let's close this and we can continue on a different issue # later on with more specific use cases. Great work guys!

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

7 participants