opentype.js icon indicating copy to clipboard operation
opentype.js copied to clipboard

Font.setKerningValue(l,r,v) method

Open mattlag opened this issue 10 years ago • 50 comments

Would be nice to have a method for setting kern pair values: Font.setKerningValue(leftglyph, rightglyph, value). It looks like this is possible by manually editing the Font.kerningPairs object... but i'm not sure if there is some other internal stuff (GposKerningValue?) that also needs to be updated.

mattlag avatar Feb 11 '15 22:02 mattlag

The Kern table is deprecated, GPOS kerning should be used instead :) On Feb 11, 2015 5:29 PM, "Matt LaGrandeur" [email protected] wrote:

Would be nice to have a method for setting kern pair values: Font.setKerningValue(leftglyph, rightglyph, value). It looks like this is possible by manually editing the Font.kerningPairs object... but i'm not sure if there is some other internal stuff (GposKerningValue?) that also needs to be updated.

— Reply to this email directly or view it on GitHub https://github.com/nodebox/opentype.js/issues/95.

davelab6 avatar Feb 11 '15 23:02 davelab6

I'm looking through the opentype.Font object, there doesn't seem to be a GposKerning object (only a getGposKerningValue method). There is a kerningPairs object that appears to hold kern values. But i'm not sure how internally that maps to exported font features.

I'm going to try directly accessing it.. but like I said, it would be better if there was some sort of official method, as opposed to me just poking around :-)

mattlag avatar Feb 11 '15 23:02 mattlag

Kerning values can be stored in two ways, either through the (deprecated) kern table or the (complicated) GPOS table. Currently we only have read support for both.

There is no way to set them so they will be saved, since we simply have no write support for GPOS. It should be added, but I haven't found the time yet.

@mattlag On a related note, last year I've been able to implement font writing in opentype.js through the Prototypo Kickstarter project. I'm open to discuss sponsored development of specific features.

fdb avatar Feb 12 '15 14:02 fdb

Thanks for the kerning info, @fdb. At the moment, Glyphr Studio is a spare time project, and doesn't have any sponsoring capability :-)

mattlag avatar Feb 12 '15 17:02 mattlag

@fdb do you prefer cash to sponsor it, or do you prefer someone else to develop it and make a pull request?

davelab6 avatar Feb 12 '15 20:02 davelab6

@mattlag no problem at all. opentype.js is currently a spare time project as well :-)

@davelab6 both suggestions work for me! Since I have a job in academia, I can do sponsored development during the summer holiday, which is between July and August.

fdb avatar Feb 12 '15 20:02 fdb

@felipesanches are you interested?

davelab6 avatar Feb 12 '15 21:02 davelab6

Yes, I'm interested in working on this. I'll take a look at this today and see if I can do it or if I have any technical question.

felipesanches avatar Jun 26 '15 15:06 felipesanches

@felipesanches to be clear, this means implementing write support for the GPOS table.

https://github.com/behdad/fonttools/ has support for this in python, so basically the feature request is to port the fontTools code to opentype.js

davelab6 avatar Jun 26 '15 15:06 davelab6

great!

felipesanches avatar Jun 26 '15 15:06 felipesanches

Awesome :+1:

fdb avatar Jun 26 '15 15:06 fdb

:smile: :tada:

mattlag avatar Jun 26 '15 18:06 mattlag

I see that https://github.com/nodebox/opentype.js/issues/112 and https://github.com/mapbox/node-fontnik/issues/85 are related

davelab6 avatar Jun 27 '15 03:06 davelab6

Ok... I've been reading the specs and getting used to the source code and now things are a bit clearer.

For starters, the proposed setKerningValue method will probably require the user to pass a 2-dimensional vector (dx, dy) because the kerning adjustment can also happen in the Y-axis.

We may accept both types of data, defaulting dy to zero if a single value is passed instead of the pair of offsets.

felipesanches avatar Jun 30 '15 02:06 felipesanches

In order to implement the makeGposTable function (that encodes the GPOS table) we need access to the relevant data. Given that our current GPOS parser is incomplete, the output GPOS table will be incomplete as well.

felipesanches avatar Jun 30 '15 02:06 felipesanches

While we may be happy about parsing only a portion of the table, the opposite may not be true. I guess that OTF files with incomplete GPOS tables might annoy the parsers of other programs. Anyone here knows if this is the case?

We may consider improving the parser before actually implementing the encoder.

felipesanches avatar Jun 30 '15 02:06 felipesanches

Even if we decide to implement the encoder without improving the parser first, the current parsing code will have to be modified. That's because currently it exposes the kerning values by dinamically creating a getKerningValue function that operates on the parsed data that is only accessible to this function because it is trapped in its bound subtables variable (by creating a closure).

In order to output the table we need direct access to the parsed data.

felipesanches avatar Jun 30 '15 02:06 felipesanches

I'm working on an implementation of the GPOS encoder at this feature branch: https://github.com/felipesanches/opentype.js/tree/makeGposTable

I'll keep ammending that in the upcoming days until I reach a state that I consider acceptable for a pull-request.

felipesanches avatar Jun 30 '15 02:06 felipesanches

Are you sure 2d vectors? I thought it was either h or v, not both at once, but might be wrong.

I recommend looking at fontTools to make output you are aiming for and checking it against ots if you aren't sure if ever you'll do is valid

I also don't think you need to support all feature and lookup types, just the ones for Latin to start

davelab6 avatar Jun 30 '15 02:06 davelab6

yes, I've been studying fontTools as well.

Regarding the Latin features, I agree that's a good start. My point is that perhaps void featureList and scriptList entries may lead to programs considering the file corrupt. Or even crashing perhaps. I have no idea. Would be good to know if it is safe to output a GPOS table without those entries.

felipesanches avatar Jun 30 '15 02:06 felipesanches

I don't know but I guess you can ttx a font and remove these parts and see how it goes

Also: Check the adobe fdk feature file syntax too :)

davelab6 avatar Jun 30 '15 02:06 davelab6

Regarding 2d verctors...

"To properly render Urdu, a text-processing client must modify both the horizontal (X) and vertical (Y) positions of each glyph." https://www.microsoft.com/typography/OTSPEC/gpos.htm

felipesanches avatar Jun 30 '15 22:06 felipesanches

Are you sure 2d vectors? I thought it was either h or v, not both at once, but might be wrong.

You have horizontal and vertical advances and offsets, so 4 possible values to modify and all can be set at once.

khaledhosny avatar Jul 01 '15 01:07 khaledhosny

Cool :)

davelab6 avatar Jul 01 '15 01:07 davelab6

@khaledhosny what is the difference between an advance and an offset?

mattlag avatar Jul 01 '15 02:07 mattlag

The offset affects the X and Y position where the glyph is drawn (without affecting the position of the next glyph). The advance controls how much the line advances after the glyph i.e. controlling where the next glyph will be drawn.

khaledhosny avatar Jul 01 '15 10:07 khaledhosny

I'm not sure i'd expect to set a glyph's advance through a kerning function - correct? Probably just x and y offsets (with zero as the default).

If the Kerning value between two glyphs is reduce by, say, 100, the advance width of the left glyph overlaps with that of the right glyph. It's not like the right hand glyph gets drawn at -100, but the two advance widths are still added as if no kerning took place. The overall net of both advance widths is also -100.

In my mind the advance width is a property of a glyph. And contextual spacing between glyphs is Kerning. But there is no such thing as contextual advance widths (or maybe i'm wrong, i'm not super familiar with all the OpenType features)

mattlag avatar Jul 01 '15 17:07 mattlag

This is advance width adjustment for specific context e.g. a kerning pair, not the actual glyph advance which is stored elsewhere in the font. Actually Latin kerning is simply changing the advance width of the first glyph in the kerning pair.

OpenType have even more generalised contextual positioning which can be used for kerning as well, pairwise positioning is just a kind of shortcut for the common case.

khaledhosny avatar Jul 01 '15 18:07 khaledhosny

"A pair adjustment positioning subtable (PairPos) is used to adjust the positions of two glyphs in relation to one another-for instance, to specify kerning data for pairs of glyphs. Compared to a typical kerning table, however, a PairPos subtable offers more flexiblity and precise control over glyph positioning. The PairPos subtable can adjust each glyph in a pair independently in both the X and Y directions"

felipesanches avatar Jul 02 '15 20:07 felipesanches

Interesting, so the full arguments would be something like (Glyph1x, Glyph1y, Glyph2x, Glyph2y) with the basic Kerning scenario only requiring Glyph2x, and default to 0 for everything else.

mattlag avatar Jul 02 '15 20:07 mattlag