-
Notifications
You must be signed in to change notification settings - Fork 487
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
Font.setKerningValue(l,r,v) method #95
Comments
The Kern table is deprecated, GPOS kerning should be used instead :)
|
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 :-) |
Kerning values can be stored in two ways, either through the (deprecated) There is no way to set them so they will be saved, since we simply have no write support for @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. |
Thanks for the kerning info, @fdb. At the moment, Glyphr Studio is a spare time project, and doesn't have any sponsoring capability :-) |
@fdb do you prefer cash to sponsor it, or do you prefer someone else to develop it and make a pull request? |
@felipesanches are you interested? |
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 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 |
great! |
Awesome 👍 |
😄 🎉 |
I see that #112 and mapbox/node-fontnik#85 are related |
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. |
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. |
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. |
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. |
I'm working on an implementation of the GPOS encoder at this feature branch: I'll keep ammending that in the upcoming days until I reach a state that I consider acceptable for a pull-request. |
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
|
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. |
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 :)
|
Regarding 2d verctors... "To properly render Urdu, a text-processing client must modify both the horizontal (X) and vertical (Y) positions of each glyph." |
You have horizontal and vertical advances and offsets, so 4 possible values to modify and all can be set at once. |
Cool :)
|
@khaledhosny what is the difference between an advance and an offset? |
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. |
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) |
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. |
"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" |
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. |
You need four values for each glyph in the pair (x offset, y offset, x advance adjustment, y advance adjustment). |
To model what most people recognize as kerning you just need the original proposed Font.setKerningValue(l,r,v). I don't think there's any point in supporting more advanced GPOS positioning using a simplified API like this. |
But that wouldn't support RTL kerning. OK may be the API can have an optional direction parameter and when it is RTL set both the X offset and advance adjustment of the first glyph in the pair. |
The API doesn't need a direction, whereas the code generating GPOS lookups from these numbers should take script direction into consideration when adding lookups to scripts. From an API point of view, there's no ambiguity what it means by leftGlyph, rightGlyph, and value. |
I’m not concerned about which is the left and which is the right glyph, but rather which PairPos values the function will set. For LTR kerning only the x advance adjustment of the first (left most glyph) need to be set, but in LTR kerning both the x advance adjustment and the x offset of the first (right most glyph) need to be set. So the API need to address this in a way or another. |
I understand that. But again, I don't think it needs to be reflected to the API. Look at it this way: to adjust the rsb of a glyph, you only change X advance. To adjust the lsb, you update both X advance and offset. This is a universal rule that can be deducted from the OpenType glyph model. Now, what this means for GPOS kerning is straightforward: if you are making changes to the left-side glyph, you update advance only. If you are changing the right-side glyph, you update both. My point: no need to reflect any of this in the API. |
But the fact that the glyph being adjusted will end up being the rightmost or leftmost glyph in this case is only known at the layout time when the glyph stream is reversed (the font developer knows this beforehand of course because he can tell which glyphs will be used in RTL context). Lets say I was to kern the Latin Now, lets kern the Arabic |
I think this is the core of the problem. Is it always possible to deduce the correct direction for a kerning pair? How does it work? |
@felipesanches you might like to review foliojs/fontkit#7 |
That would be wrong. The API specifically says that the first argument is leftGlyph, and second argument is rightGlyph.
The code generating the feature files MUST know that under 'arab' script, first glyph is the rightmost one. So when encoding a lookup to be used under 'arab', it encodes the rightGlyph first. That has nothing to do with the API. And I'm not going to repeat that again :). I'll add some more comments on unified-font-object/ufo-spec#16 with a more interesting examples (punctuation marks). |
Here: I hope I don't have to repeat myself more than this. :) |
Re "he can tell which glyphs will be used in RTL context" that's a completely different argument. For most glyphs the script is known to Unicode. For script=Common characters, sure, the user can give a hint as to which punctuation and other marks one wants to be included in kern table for each script. But all of these are really separate APIs. They do not justify the change suggested here. |
and
I hope I'm not too pesky here. But how does this API know which script applies for the call to It seems that the other APIs are not that separate at all. There must be somewhere the knowledge how to construct the right lookup style and you are missing to tell us where this should happen. All you say is "not here" BUT "the user can give a hint". Where can the user do so and how is that separate then? |
See my reply here: unified-font-object/ufo-spec#16 (comment) |
Did this ever go anywhere? I am building a font metrics-related web interface and it would be really useful to be able to render text with sidebearing and kerning values set on the fly (alternative suggestions welcome)! |
Doesn't matter if it's called the first glyph or the left/right/top/bottom glyph, just wish something were possible. This method would've been so useful. Is it not possible to set a simple kerning on a font using JS? |
Yeah, seems like there has been no movement here for 4 years... re-reading the thread, @felipesanches maybe was the last one to work on writing GPOS tables? It seems from #309 that some GSUB table writing is possible, maybe not through any API, but just constructing an array buffer from scratch yourself(?) I know this thread got complicated real quick, but some example of how to write basic latin ligature information would be very much appreciated! Maybe @Jolg42 can help? |
I hope I didn't react too annoyingly - was frustrated, because I've gotten quite far on a project and was so disappointed to reach this wall. Since I'm running on Google Cloud, it'd be possible to keep a VM with FontForge as a service just for kerning, but it seems so wasteful when the code looks so close to supporting kerning, something I'd think would be so standardized (and is so easy in deprecated SVG). But of course, I don't want to be the one to do it either X) Yes, please @Jolg42 or anyone! would love to have a simple left-to-right example I could toss into my code and rid the demons of server maintenance. |
Just for sake of clarity, the prototype might imitate the SVG hkern/vkern tags: Font.hkern( |
Following up on this another few years later, I am wondering if there has been any development on this in the recent years? It looks like there is still some development happening on opentype.js. I have a hard time finding a tool the allows me to draw/write a font within the browser (with all the latest opentype features and kerning). Most tools are focused on parsing fonts, which makes sense, as writing is a very rare use-case anyways i guess. I am working on simple tool to create fonts in the browser. I haven't find any other library that could help with that yet. |
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.
The text was updated successfully, but these errors were encountered: