UFO 4: object selectors?

86 views
Skip to first unread message

Adam Twardoch (List)

unread,
Mar 9, 2015, 10:42:36 AM3/9/15
to ufo-...@googlegroups.com
Dear all,

At Robothon, I have talked to Tal briefly about the PS hint representation. He said he still intends to propose a better representation. His concern is that the current representation is like FontLab "hints", i.e. you have hint positions and widths, while he'd somehow prefer FontLab "links", i.e. info about linking points (that would ultimately use the UFO3 object IDs and be a bit more abstract). I think, generally speaking, we have two ways to express PS hints: one which is rather close to the native representation (i.e. start positions and widths of the hints), and another which is a bit more related to points.

But I would say that anything that is related to point IDs would not really work for PS hinting. I mean, it is their nature that they can exist in a glyph where no points are to be seen within their "reach". It may be problematic or lead to unexpected results, but I think for PS hints, we need a way to represent that kind of situations. PS hinting is, after all, a bit "low level", they are (and should be) on the same level of abstraction as TrueType bytecode.

I think what is BEYOND doubt is that both the Adobe PS representation and other representations such as the FontLab TTH representation should adhere to the plist form. That's just how it is with UFO, and we should stick with it. I may not be a big fan of it aesthetically, but that's not reason enough to hijack it. The current situation, where vfb2ufo and Adobe autohint inject portions of custom XML into the lib is just bad — and base64-encoding it does not really solve anything (it is really quite silly). I'd much rather have plist XML that is "readable" than custom XML inside base64 :D

At Robothon, there's been a lot of talk about an abstracted format for TrueType hinting. Tal has talked about the basic types of high-level TT commands shared by many implementations: align, link, interpolate. Lucas has expressed desire for the ability to somehow "nest" some commands, most specifically, he'd like to be able to interpolate a FontLab double-link. Some other people have expressed their desire to be able to specify additional commands even if certain implementations wouldn't know what to do with it.

When it comes to the discussion about point numbers, identifiers and names, I think what is really meant is "selectors" akin to CSS selectors. In a way, the GLIF proper is like HTML and lots of stuff in the lib can be seen like CSS — additional data that does not necessarily represent value by itself but is somehow linked to some structures.

In UFO3, we have "identifier" attributes, like HTML element "id" attributes. They're supposed to be unique across the board (in the entire document, I presume, i.e. font -- or even font family).

Then, we have the "name" property. UFO 2.5 (i.e. the de facto implementation used by RoboFont) uses the "name" property so that it makes names out of sub-values and then sometimes treats these sub-values separately. This is actually very much akin to how the "class" attribute in HTML works.

The TTH markup implemented in vfb2ufo makes use of the "name" attribute, and does it in a way that is somewhat akin to usage of HTML "class" attribute. It tries to assign some "logical" or "descriptive" topological names, tries to make up the names so that they can "mean" something like "this is a point that is on top" or "this is a point that is in the middle". It's a commendable effort, but the "name" attribute isn't really made for that.

Ideally, I'd like to see a system where:

1. The objects that represent "primary data" and can be targets of some operations, such as points, guidelines, anchors or components can have an "id" or "identifier" attribute that is supposed to be very unique, but also can have a "tags" attribute that is like a class in HTML, i.e. it can contain multiple comma-separated keywords, and they do not need to be unique.

So we could have:

<point x="134" y="187" type="curve" smooth="yes"/ identifier="298301984" tags="midstem leftside">

2. Any kinds of "operations" or "relative data" which needs to refer to existing objects could use a very simplified mechanism to refer to these objects. Not the whole cascading thing like in HTML and CSS, but much simpler, yet drawing from CSS selectors as a principle.

The mechanism of referring to data objects could be as follows:

a) Data structures can use a string as a "reference" to other objects.

b) If the reference starts with a "#", the subsequent portion of the reference is interpreted as the identifier (so the target needs to have a matching identifier). As a result of such selection, the object with the specified identifier is selected.

c) If the reference starts with a "*", the subsequent portion of the reference is interpreted as a tag (one of the space-separated substrings of the tags attribute). As a result of such selection, all objects with with the specified tag substring are selected.

d) If none of the above, the entire reference is interpreted as a name attribute. As a result of such selection, all objects with the specified name are selected.

e) A reference can point to multiple targets. In that case, the targets are space-separated.

3. For the sake of completeness, I would like to propose that the attributes "tags" (and perhaps also "identifier") are also added to the top-level "glyph" elements of the GLIF. Alternatively, a list of "tag" elements should be registered in the public.* namespace of the lib.

4. The language for the "name" attribute of a GLIF glyph should be changed so it actually does impose some limitations, and the VERY least that the "name" attribute should not contain spaces. Virtually all implementations of UFO assume that the "name" attribute is closely tied to the PostScript name of a glyph. Tal's Robothon suggestion to introduce a "public.displayName" element strengthens this assumption. My initial suggestion was actually the reverse: to introduce "public.postScriptName", which would be strictly the name to be used as the 'post' glyph name. Then, the "name" attribute could remain "free". But I that would require changes in various codebases, and I guess that Tal is not willing to impose that work on the involved parties. The current situation is BAD. The spec suggests the "name" attribute can be anything but virtually all implementers pass that attribute straight into the 'post' table and 'CFF' table. This is BAD BAD BAD BAD! At the very least, the description of the "name" attribute should be strengthened to reflect that practice.

5. To sum up:

a) The "name" attribute of a point or guideline etc. does not need to be unique, and matching it always takes the entire name attribute as a target, so there is no "fancy" substring matching like in RoboFont (that behavior should be strongly discouraged!)

b) The "tags" attribute of a glyph or point or guideline etc. does not need to be unique. But the tags attribute in fact always consists of space-separate singleton tag entities, and matching always happens on the level of these singleton tag entities.

c) The "identifier" attribute of a [glyph or] point or guideline DOES need to be unique (as unique as only possible, even across the fonts), and the result of a selection by identifier should always be just one object.

Overall, I think such a mechanism would simplify the life of 3rd-party developers and would allow for a more coherent architecture of tools, plugins and formats that rely on UFO but need to add lots of custom data.

Opinions?
Adam

Ps. Example:

In GLIF proper:

<point x="134" y="187" type="curve" smooth="yes" identifier="298301984" tag="ih01 toKeep fancyBehavior" name="cont23" />
<point x="74" y="187" identifier="618331992" tag="sh01 myTarget" name="cont54" />
<point x="30" y="150" identifier="778355934" tag="dh01" name="cont66" />

In lib:

<lib>
<dict>
<key>com.fontlab.v3.ttprogram</key>
<data>
<key>ttProgram</key>
<array>
<key>ttc</key>
<dict>
<key>align</key>
<string>round</string>
<key>code</key>
<string>interpolateh</string>
<key>point</key>
<string>*ih01</string>
<key>point1</key>
<string>#618331992</string>
<key>point2</key>
<string>cont66</string>
</dict>
</array>
</data>
</dict>
</lib>

==

Adam Twardoch (List)

unread,
Mar 9, 2015, 10:58:12 AM3/9/15
to ufo-...@googlegroups.com
Ps2. The recommended behavior of UFO implementers would be:

1. For the "identifier" attribute, try to keep it as is between open and save (this is why it would also be useful to be added to glyphs, which can be renamed). If you really must, change all identifiers everywhere, including all instances in the lib.

2. For the "name" attribute, you can change it if needed. Implementers are discouraged from basing their selections in their custom data portions on the "name" attribute, because it can change easily.

3. For the "tags" attribute, you can add to it but please keep the previously found tag substrings intact. Custom data may rely on the previously-found tag substrings.

Also, since certain apps may choose to display tags in the GUI, I propose a convention where a tag that starts with "." should be "hidden" (similar to the Mac OS X file naming convention). So for example, if I have
<point x="134" y="187" type="curve" smooth="yes" identifier="298301984" tag=".ih01 toKeep .fancyBehavior" name="cont23" />
then an app might display "toKeep" to the user in a GUI but hide the other two. An app may implement a "show hidden tags" behavior, of course.

A.

Adam Twardoch (List)

unread,
Mar 9, 2015, 11:03:50 AM3/9/15
to ufo-...@googlegroups.com
Ps3. The "*" prefix as a reference selector for tag substrings may not be the best. I wouldn't want to use "." or ":" for certain reasons, so suggestions are welcome. Perhaps "%".

So ref="#38083755" selects by identifier, ref="important" by name and ref="%.ih01" by a "hidden" tag substring ".ih01".

A.

Adam Twardoch (List)

unread,
Mar 9, 2015, 11:06:29 AM3/9/15
to ufo-...@googlegroups.com
Ps4. For "hidden tags", instead of the "." prefix, it might be sensible to use "_" as a prefix instead. That would be a nod to the way private methods are marked in Python, and also a nod to a tradition where "_" is used as a prefix for "private" glyphs in FontLab Studio or Glyphs.

A.

Jens Kutilek

unread,
Mar 10, 2015, 7:23:35 AM3/10/15
to ufo-...@googlegroups.com
Adam Twardoch wrote:

> At Robothon, there's been a lot of talk about an abstracted format for TrueType
> hinting. Tal has talked about the basic types of high-level TT commands
> shared by many implementations: align, link, interpolate. Lucas has
> expressed desire for the ability to somehow "nest" some commands, most
> specifically, he'd like to be able to interpolate a FontLab double-link. Some
> other people have expressed their desire to be able to specify additional
> commands even if certain implementations wouldn't know what to do with it.

Just a heads-up: At the meeting in Den Haag I volunteered to think about how TrueType hinting could be represented in a UFO. I'll write down my thoughts and will be happy to share them with anyone interested.

> In lib:
>
> <lib>
> <dict>
> <key>com.fontlab.v3.ttprogram</key>
> <data>
> <key>ttProgram</key>
> <array>
> <key>ttc</key>
> <dict>
> <key>align</key>
> <string>round</string>
> <key>code</key>
> <string>interpolateh</string>
> <key>point</key>
> <string>*ih01</string>
> <key>point1</key>
> <string>#618331992</string>
> <key>point2</key>
> <string>cont66</string>
> </dict>
> </array>
> </data>
> </dict>
> </lib>

This looks much better than what vfb2ufo produces at the moment. Is this a plan or just something you made up for this example? ;)

Best,
Jens

Lasse Fister

unread,
Mar 10, 2015, 1:43:40 PM3/10/15
to ufo-...@googlegroups.com
On 03/09/2015 03:42 PM, Adam Twardoch (List) wrote:
> When it comes to the discussion about point numbers, identifiers and names, I think what is really meant is "selectors" akin to CSS selectors. In a way, the GLIF proper is like HTML and lots of stuff in the lib can be seen like CSS — additional data that does not necessarily represent value by itself but is somehow linked to some structures.
This in interesting! We are using CSS-like Selectors in Metapolator. And
we are reading them from UFOv3. We are calling it CPS to avoid confusion
(Cascading Properties Sheets).

This is how we do it:

For glyphs:
"ids" are taken from contents.plist element, I would expect these
names to be the PostScript name, however, we could handle spaces and
such with escapes, but this is not implemented yet.
"classes" are taken directly from groups.plist

For stuff inside of glyphs (contours, points, components, anchors,
guideline):
"ids" are taken from the "identifier" attribute
"classes" are taken from the "name" attribute, space separated

The uniqueness of ids follows the rules of UFOv3. Thus we have no
globally unique ids. unique selections include usually the element, like so:
glyph#a
Also, we load multiple masters at the same time, so there is likely more
than one glyph#a and we would select a unique one so: master#bold glyph#a

What I'm missing badly is a "name" attribute for contours! I'm thinking
of overloading the identifier, and in a way I'm already doing this :-(
Also, components should have a "name" attribute available.

By the way, about glyph names:

I think contents.plist is the better place to keep the glyph names than
the glif "name" attribute, because the dictionary data-structure of
contents.plist itself takes care of glyph name uniqueness. When
compared, having to look into each glif is very expensive also it makes
multiple uses of the same name possible.
Robofabs ufoLib also prefers the name of contents.plist. At least
"writeGlyph" just sets the "name" to the key in the contents.plist, and
"writeGlyphToString" does not even look at the "name" attribute of its
"glyphObject" argument.
The one thing left is, when reading a glif, the "_readName" method
expects a "name" attribute to be present and not empty or it raises an
error. But there is no check for uniqueness at all.
My opinion is that the "name" attribute of a glyph is redundant and
misleading. Thus it should be removed from the spec. Instead, all
glyph-names should live in contents.plist, which is the right place to
store that information. A display name could be in glyph, of course.


> In UFO3, we have "identifier" attributes, like HTML element "id" attributes. They're supposed to be unique across the board (in the entire document, I presume, i.e. font -- or even font family).
Nope in UFOv3 "identifiers" are unique within a glyph plus global
guidelines.

> Then, we have the "name" property. UFO 2.5 (i.e. the de facto implementation used by RoboFont) uses the "name" property so that it makes names out of sub-values and then sometimes treats these sub-values separately. This is actually very much akin to how the "class" attribute in HTML works.
Yes, "name" works well as a class attribute.
> 2. Any kinds of "operations" or "relative data" which needs to refer to existing objects could use a very simplified mechanism to refer to these objects. Not the whole cascading thing like in HTML and CSS, but much simpler, yet drawing from CSS selectors as a principle.
The cascading thing is rather how the data is read from CSS rules.
However, even a simplified CSS selector mechanism is very useful indeed.


> Opinions?
I can't say much about hinting.

Lasse

Adam Twardoch (List)

unread,
Mar 10, 2015, 9:14:40 PM3/10/15
to ufo-...@googlegroups.com
All very interesting. I agree that for glyphs, name is a good CSS-like "id" and group is a good CSS-like "class". There is the AFDKO convention of referring to FEA classes using the @ prefix.

It's also interesting that within a glyph, you treat "identifier" as an "id" and space-separated substrings of the point etc. "name" attribute as "classes".

Both RoboFont and TTH now rely on the concept of the name attribute actually being a collection of substrings (tags).

So I could simplify my suggestion:

1. When selecting glyphs, use the notation "nnn" to match a single glyph by its glyph name "nnn" and "@nnn" to match multiple glyphs by the group name "nnn" declared in groups.plist

2. Standardize the notion that within a GLIF, the object (point, guideline etc) "name" attribute is actually a space-separated list of tags.

3. When selecting (eg. in a GLIF lib structure such as for TTH) objects within a GLIF, use "nnn" to match a single object by the identifier "nnn", and use "@nnn" to match multiple objects by the tag "nnn" (where a tag is a space-separated portion of the name attribute).

4. Suggest the UX convention that tags prefixed by "_" should not by default be presented to the user in the UI.

I think the above is a very simple and consistent scheme which sort of reflects current practice AND does not require any changes to the structure of the GLIF spec (ie. the new tags attribute I proposed earlier is no longer required).

Adam

Sent from my mobile phone.
> --
> You received this message because you are subscribed to the Google Groups "Unified Font Object Specification" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to ufo-spec+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Adam Twardoch (List)

unread,
Mar 10, 2015, 9:23:57 PM3/10/15
to ufo-...@googlegroups.com


On 09.03.2015, at 23:14, Jens Kutilek <je...@fontfont.de> wrote:

Just a heads-up: At the meeting in Den Haag I volunteered to think about how TrueType hinting could be represented in a UFO. I'll write down my thoughts and will be happy to share them with anyone interested.

Excellent! Many thanks for volunteering! :) 
I made it up and proposed 3 months ago on this list when we were debating the vfb2ufo FontLab TTH syntax and the Adobe autohint syntax. 

It was just as part of my understanding how the current "temporary" syntaxes could be translated to plist. See:



I'm not sure if these examples I made are completely correct, since I'm not used to hand-writing XML on an assembly level (which plist is) :) 

A.

Adam Twardoch (List)

unread,
Mar 10, 2015, 9:28:54 PM3/10/15
to ufo-...@googlegroups.com
Ps.

5. Disallow spaces in the GLIF name attribute (it'll make everyone's lives easier) but explicitly allow them in the new public.displayName field that Tal proposed at Robothon.

Sent from my mobile phone.

Tal Leming

unread,
Mar 12, 2015, 9:55:56 PM3/12/15
to ufo-...@googlegroups.com
Hi Adam,

This is an interesting idea and I could see how useful it would be. I have a couple of reservations, both of which might be possible to work around.

1. Does this cross over into the spec defining application behavior? I don't know, but it is something that we should think about. We *try* to keep the spec from dictating anything other than read, write and "don't discard without alerting the user". There are some interpretation and translation guidelines, but those are mostly to ensure data consistency.

2. Adding a tags element at this point could cause some breakage or non-trivial implementation for developers. I want to keep UFO 4 limited to just a file structure change if at all possible. It could be implemented in the interim via the lib like this:

public.tags : {
identifier : "tags",
etc.
}

Though, the tags could also be implemented with an array so that string breaking wouldn't be necessary:

public.tags : {
identifier : ["tag1", "tag2", etc.]
}

Answering some of your points:

> At Robothon, I have talked to Tal briefly about the PS hint representation. He said he still intends to propose a better representation. His concern is that the current representation is like FontLab "hints", i.e. you have hint positions and widths, while he'd somehow prefer FontLab "links", i.e. info about linking points (that would ultimately use the UFO3 object IDs and be a bit more abstract).

My issue with the current implementation is that it is specific to a state of the glyph. If the outlines change, the hint data can become invalid. That sort of dependency is something that we try to avoid by design, but it may not be possible to do so with this. (See also: TT hints; Ugh; Quagmire.) I'm still mulling things over and Adobe's proposal may very likely be the basis of the official storage structure. (Apart from the whole base64 thing.)

The thing that I was talking about was an abstract way of noting that certain points/contours meant certain things. It wasn't just for hints specifically, but could represent lots of things: "these points form a serif", "these points are grouped together", "the segment between these points should be rendered as a sequence of pink hearts". This idea is cool but long dead. (cough UFO 6 cough)

> But I would say that anything that is related to point IDs would not really work for PS hinting. I mean, it is their nature that they can exist in a glyph where no points are to be seen within their "reach". It may be problematic or lead to unexpected results, but I think for PS hints, we need a way to represent that kind of situations. PS hinting is, after all, a bit "low level", they are (and should be) on the same level of abstraction as TrueType bytecode.

I'm going to have to defer to experts on this. I have very little knowledge about PS hints. Anything that I can learn would be from reading the specs, not from real world use.

> 4. The language for the "name" attribute of a GLIF glyph should be changed so it actually does impose some limitations, and the VERY least that the "name" attribute should not contain spaces. Virtually all implementations of UFO assume that the "name" attribute is closely tied to the PostScript name of a glyph. Tal's Robothon suggestion to introduce a "public.displayName" element strengthens this assumption. My initial suggestion was actually the reverse: to introduce "public.postScriptName", which would be strictly the name to be used as the 'post' glyph name. Then, the "name" attribute could remain "free". But I that would require changes in various codebases, and I guess that Tal is not willing to impose that work on the involved parties. The current situation is BAD. The spec suggests the "name" attribute can be anything but virtually all implementers pass that attribute straight into the 'post' table and 'CFF' table. This is BAD BAD BAD BAD! At the very least, the description of the "name" attribute should be strengthened to reflect that practice.

We should start a separate thread for this. My public.designName idea is not even half baked yet and it needs a lot more thought. Glyph names are a nightmare of backwards compatibility in every possible way. We relaxed the requirements for glyph names in UFO 3 because we don't want to make the format follow outdated notions of glyph naming. Why should we force the glyph names to conform to OTF-CFF naming requirements? Why stop there? Let's make them use a subset of ASCII that will make the names work on any OS since 1976! :-) But, yeah, we should have a discussion about glyph names at some point.

> a) The "name" attribute of a point or guideline etc. does not need to be unique, and matching it always takes the entire name attribute as a target, so there is no "fancy" substring matching like in RoboFont (that behavior should be strongly discouraged!)

Right. Names are meant to be a user facing thing. Requiring users to make things unique is not going to be reliable in practice.

> c) The "identifier" attribute of a [glyph or] point or guideline DOES need to be unique (as unique as only possible, even across the fonts), and the result of a selection by identifier should always be just one object.

The identifiers must be unique across a glyph, but there is no requirement for them to be unique across the font. We thought about this a lot. In theory, the number of possible identifiers should be enough to allow a unique identifier across the font for every single object. But, testing for and maintaining that uniqueness across such a huge number of objects would be troublesome in practice. So, we limited the scope. layer name + glyph name + identifier will give you a precise object locator.

> Opinions?

Could you give a few more use cases for the tags? I mean, as I understand it, it allows hint abstractions to point to types of things. Do you think it could be useful for other things?

Thanks,
Tal

Tal Leming

unread,
Mar 12, 2015, 10:01:49 PM3/12/15
to ufo-...@googlegroups.com
On Mar 10, 2015, at 1:43 PM, Lasse Fister <newsl...@graphicore.de> wrote:

What I'm missing badly is a "name" attribute for contours! I'm thinking
of overloading the identifier, and in a way I'm already doing this :-(
Also, components should have a "name" attribute available.

Heh. The point name idea is from UFO 1 beta 1. I don't know if we ever thought about giving contours and components names. Everything else has them though. We should fix this the next time we update GLIF. In the meantime, you can store names in the lib linked to identifiers.

By the way, about glyph names:

I think contents.plist is the better place to keep the glyph names than
the glif "name" attribute, because the dictionary data-structure of
contents.plist itself takes care of glyph name uniqueness. When
compared, having to look into each glif is very expensive also it makes
multiple uses of the same name possible.
Robofabs ufoLib also prefers the name of contents.plist. At least
"writeGlyph" just sets the "name" to the key in the contents.plist, and
"writeGlyphToString" does not even look at the "name" attribute of its
"glyphObject" argument.
The one thing left is, when reading a glif, the "_readName" method
expects a "name" attribute to be present and not empty or it raises an
error. But there is no check for uniqueness at all.
My opinion is that the "name" attribute of a glyph is redundant and
misleading. Thus it should be removed from the spec. Instead, all
glyph-names should live in contents.plist, which is the right place to
store that information. A display name could be in glyph, of course.

This is another very old thing. The spec used to say that the name attribute was functionally useless, but I guess we removed that. For the UFO 4 stuff that we're starting to kick around, the name attribute may become important again. We'll see how that all shakes out.

Thanks,
Tal

Tal Leming

unread,
Mar 12, 2015, 10:06:02 PM3/12/15
to ufo-...@googlegroups.com

On Mar 10, 2015, at 9:14 PM, Adam Twardoch (List) <list...@twardoch.com> wrote:

2. Standardize the notion that within a GLIF, the object (point, guideline etc) "name" attribute is actually a space-separated list of tags. 

This doesn't seem like a good idea to me. Lots of things use the name attribute for different purposes. I don't think we could make a blanket statement about how all existing point, anchor and guideline names should be interpreted. I much prefer the idea of storing a distinct set of tags somewhere else.

Thanks,
Tal

Adam Twardoch (List)

unread,
Mar 12, 2015, 11:54:47 PM3/12/15
to ufo-...@googlegroups.com

> On 13 Mar 2015, at 07:25, Tal Leming <t...@typesupply.com> wrote:
>
> 1. Does this cross over into the spec defining application behavior? I don't know, but it is something that we should think about. We *try* to keep the spec from dictating anything other than read, write and "don't discard without alerting the user". There are some interpretation and translation guidelines, but those are mostly to ensure data consistency.

Well, given that the foundation of UFO is very much linked to FontLab Studio 5 (most data structures present in FLS 5 translate to UFO in some way) and AFDKO (most things that makeOTF expects as input are in UFO), I don't think you can really "unlink" UFO and app behavior. UFO seems also to be linked to defcon/Robofab. Given that RoboFont is a "UFO editor", and there also seems to be a certain reluctance in introducing things to UFO that would be difficult for Frederik to implement. I wonder how much this situation is compliant with item #2 of the UFO Design Philosophy for me.

UFO dictates app behavior in countless aspects implicitly. The fact that OpenType Layout feature definitions are stored in the text-based FEA format "dictates" that an app has to be able to deal with that format somehow. Limitations of the FEA format also dictate limitations of UFO and apps. I have yet to see an approach that would allow to easily "superpolate" arbitrary GPOS or GDEF features rather than just "kerning" and "anchors". Caret positions? Cursive attachment? Contextual GPOS rules? Most Indic scripts use GPOS for things far beyond "mark attachment", but there's hardly any trace of consideration for the needs of complex-script designers in UFO.

UFO is useless without a FEA compiler. The Adobe implementation has only been opensourced last year (great!), but has been a closed-source app for more than a decade, and certainly has been at the time of the UFO inception. That's a conflict with item #2 of the UFO Design Philosophy for me.

UFO assumes that each "font" has its own set of glyphs, its own "features.plist" etc., despite the fact that in TTC, you can share glyphs, feature tables and other structures, and such practice is common in font development (CJK but not just). If you update a GLIF that is shared across 4 fonts in one UFO, you need to copy that GLIF into 3 other UFOs. Clear conflict with item #3 of the UFO Design Philosophy. I think it's rather telling that all the sources for the Adobe "Source" font series are available in UFO except Source Han Sans.

Even the fact that UFO excludes certain structures from standardization dictates app behavior. If you're making an app that allows you to design monochrome PostScript outlines, monochrome TrueType outlines and color (or monochrome) SVG outlines simultaneously, you have a problem: you can put the set of PS outlines into one UFO, the set of TT outlines in another UFO, and the set of SVG outlines in some custom place in either UFO (or both?). Clear conflict with item #3 of the Philosophy.

UFO says that GLIF glyph names can be of arbitrary length and contents, but ALL current implementations make a silent assumption that these names translate directly to PostScript glyph names which are subject to severe limitations. That actually is very much in sync with item #2 of the Philosophy, but that's where I think the Philosophy is wrongly applied (or wrong by itself).

Item #1 of the Philosophy postulates human readability and editability. You already know my opinion about "human readability" of the plist format. In fact, you yourself told me that I shouldn't be writing the plist format by hand and recommended a more abstract notation. And I think anyone who followed the discussion about the Adobe and FontLab storage of hinting data will agree that the non-plist formats we introduced are far more human-readable than the ones converted to be plist-compliant (see examples on https://github.com/adobe-type-tools/afdko/issues/25 ). We're going to make them plist-compliant, i.e. more *machine-readable* and less human-readable.

I commend the philosophical background to UFO, but I don't think UFO really delivers on its "high-level" promises. I'm not saying UFO should try to do it. But perhaps it's time to amend the UFO Design Philosophy towards actual practice. UFO is great, but it's great for "something" and certainly not "everything" or even "most things".

I don't want to turn this into a "rant" about what's wrong with UFO, because it would be pointless. I hope you appreciate my feedback *despite* the critical tone. In fact, I believe that in a way, we're not that different. I, too, am concerned about human accessibility of the font sources, it's future-proofness, app independence and avoidance of redundancy. But I also have concerns about the fact that in its current incarnation, UFO makes the European scripts strong first citizens while offering little benefit to Asian scripts. That's something that hurts and bothers me.

However, I am aware of how much work it would be to make UFO "world-ready", and I'm not even sure it is entirely possible.

As I've said on multiple occasions, you, Frederik, Erik, Just and others have done a tremendous service to the type community.

I think that contribution is very much on par with the work that Yuri has done to enable countless independent type designers to make Unicode-compliant, OpenType-aware fonts with high screen quality, and bring them out of the dark ages of Western-centric Type 1 world of the old Fontographer.

You guys have brought that effort to the next level, for which I am tremendously grateful.

We often hear about what UFO *is good for*, and I somewhat miss the bits where people would openly say what it *isn't good for*. So, hopefully in the interest of type designers across the entire world, I sometimes assume the role of the guy who fills that gap.

In the end, I'm not much of a philosopher myself. I just talk to type designers (from Europe, America, Japan, India, Hong Kong etc.), and listen to their stories. I try to understand the problems they're facing, and try to come up with possible practical solutions that address their needs. I don't actually care whether the solutions are called .ufo, .ufoz, .glyphs, .sfd or .vfb, as long as they address as many needs as possible.


> 2. Adding a tags element at this point could cause some breakage or non-trivial implementation for developers.

So UFO is not application independent after all. It's fine with me! ;)

> I want to keep UFO 4 limited to just a file structure change if at all possible. It could be implemented in the interim via the lib like this:
>
> public.tags : {
> identifier : "tags",
> etc.
> }
>
> Though, the tags could also be implemented with an array so that string breaking wouldn't be necessary:
>
> public.tags : {
> identifier : ["tag1", "tag2", etc.]
> }

Are you suggesting a JSON notation for this, or are the current UFO not sufficiently human editable to be written by hand, so you're picking a more abstract representation? ;)
OK, enough with the picking.

I agree that hijacking the point "name" attribute for a multi-string storage (in the style that Frederik has done in RoboFont) is not elegant. I'm open to do it either way, with some list of explicitly enumerated tags (elegant though disconnected from GLIF core so needs more cross-structure management) or with using Frederik's current method of hijacking the "name" attribute, which makes it more compact and provides a useful purpose for the already-specified "name" attribute.

Both approaches have their pros and cons, but I think ultimately, an explicit "tags" structure along the lines of what you're proposing is better. If more app developers implement behaviors such as the ones I name as examples at the end of this email, a "name" attribute could become really long (full of those space-separated keywords), and that would be kind of nasty.

> Answering some of your points:
>
>> At Robothon, I have talked to Tal briefly about the PS hint representation. He said he still intends to propose a better representation. His concern is that the current representation is like FontLab "hints", i.e. you have hint positions and widths, while he'd somehow prefer FontLab "links", i.e. info about linking points (that would ultimately use the UFO3 object IDs and be a bit more abstract).
>
> My issue with the current implementation is that it is specific to a state of the glyph. If the outlines change, the hint data can become invalid. That sort of dependency is something that we try to avoid by design, but it may not be possible to do so with this. (See also: TT hints; Ugh; Quagmire.) I'm still mulling things over and Adobe's proposal may very likely be the basis of the official storage structure. (Apart from the whole base64 thing.)

But that's the whole point behind the fundamental difference between PostScript hinting and TrueType instructions. TrueType instructions deal with points, so it makes sense to link them to points in some way, ideally using some high-level language and without references to point indexes.

But PostScript hints have nothing to do with points. You can have (and should be able to store) hints that are wider than any points, or hints where no points are to be found. PostScript hints are effectively more like "zones" within which "something" is "supposed" to happen.

Of course, if we adopt the VTTalk language for high-level hinting, we'll get stuff like links between points for free. It will be trivial to generate PostScript hints from VTTalk data. VTTalk has the concept of links between points. You can turn them into some TT assembly, but you can also generate the PostScript vstem or hstem stuff from them. Perhaps there are some aspects of PS hinting which cannot be implied from VTTalk in a direct and stable way, but I think that could be added to a slight revision of VTTalk.

In other words, VTTalk (or a subset thereof, or a dialect that defines of what FontLab TTH and VTT can do) is a sensible high-level language that can be used to express HINTS for both outline flavors: you can generate TrueType instructions from VTT hints, and you can also generate PostScript hints from VTT hints.

> The thing that I was talking about was an abstract way of noting that certain points/contours meant certain things. It wasn't just for hints specifically, but could represent lots of things: "these points form a serif", "these points are grouped together", "the segment between these points should be rendered as a sequence of pink hearts". This idea is cool but long dead. (cough UFO 6 cough)

Sounds good, but IMO, that's something for storage formats that are of higher level of abstraction (less flat) than UFO. :)

>> 4. The language for the "name" attribute of a GLIF glyph should be changed so it actually does impose some limitations, and the VERY least that the "name" attribute should not contain spaces. Virtually all implementations of UFO assume that the "name" attribute is closely tied to the PostScript name of a glyph. Tal's Robothon suggestion to introduce a "public.displayName" element strengthens this assumption. My initial suggestion was actually the reverse: to introduce "public.postScriptName", which would be strictly the name to be used as the 'post' glyph name. Then, the "name" attribute could remain "free". But I that would require changes in various codebases, and I guess that Tal is not willing to impose that work on the involved parties. The current situation is BAD. The spec suggests the "name" attribute can be anything but virtually all implementers pass that attribute straight into the 'post' table and 'CFF' table. This is BAD BAD BAD BAD! At the very least, the description of the "name" attribute should be strengthened to reflect that practice.
>
> We should start a separate thread for this. My public.designName idea is not even half baked yet and it needs a lot more thought. Glyph names are a nightmare of backwards compatibility in every possible way. We relaxed the requirements for glyph names in UFO 3 because we don't want to make the format follow outdated notions of glyph naming. Why should we force the glyph names to conform to OTF-CFF naming requirements? Why stop there? Let's make them use a subset of ASCII that will make the names work on any OS since 1976! :-) But, yeah, we should have a discussion about glyph names at some point.

Well, we should ask ourselves the question: what do people mean by a "glyph name". I think there are two kinds of glyph names: "public" glyph names, which are standardized to some extent and are subject of some limitations (effectively PostScript names at this point), and "private" glyph names (which I call "nicknames" rather than "display names" ;) ), which should enjoy full freedom. We'll most certainly not fit both kinds of requirements into one data point.

>> c) The "identifier" attribute of a [glyph or] point or guideline DOES need to be unique (as unique as only possible, even across the fonts), and the result of a selection by identifier should always be just one object.
>
> The identifiers must be unique across a glyph, but there is no requirement for them to be unique across the font. We thought about this a lot. In theory, the number of possible identifiers should be enough to allow a unique identifier across the font for every single object. But, testing for and maintaining that uniqueness across such a huge number of objects would be troublesome in practice. So, we limited the scope. layer name + glyph name + identifier will give you a precise object locator.

Ah, OK, thanks for the clarification! :)

>> Opinions?
>
> Could you give a few more use cases for the tags? I mean, as I understand it, it allows hint abstractions to point to types of things. Do you think it could be useful for other things?

Well, RoboFont uses the "hijack" paradigm. For example, if you open a TTF in RF, there will be many points on the outline which have the name "inserted". That "inserted" thingie actually belongs to tags. FontLab Studio 5.2.1 for Windows has a set of flags for "interpolated points" (in X and Y separately), where the app is supposed to calculate their position when other points are moved. These kinds of flags could be expressed as tags. We have several other point types and additional point behaviors in FontLab VI, but I cannot talk about them publicly at this point. They are useful for designers, and generally, their functioning is similar to the "inserted" RoboFont tag/flag or "interpolated" FontLab Studio 5.2 tag/flag. I can also imagine that a user could tag points with things like "round" or "inktrap" and then an app such as roundingUFO could have a mode where it only makes rounded corners or inktraps on points which have such tags, rather than on all corner points. These tags could also have a reversed meaning of course, so a user could prepare a design to be processed via roundingUFO, but could tag just a few points with "dontround" and then roundingUFO would keep these points as corners.

There's tons of other such scenarios I can think of, but I hope the examples above show the general gist. :)

Many thanks!

Best,
Adam


Adam Twardoch (List)

unread,
Mar 13, 2015, 2:02:05 AM3/13/15
to ufo-...@googlegroups.com
>> Could you give a few more use cases for the tags? I mean, as I understand it, it allows hint abstractions to point to types of things. Do you think it could be useful for other things?
>
> Well, RoboFont uses the "hijack" paradigm. For example, if you open a TTF in RF, there will be many points on the outline which have the name "inserted". That "inserted" thingie actually belongs to tags. FontLab Studio 5.2.1 for Windows has a set of flags for "interpolated points" (in X and Y separately), where the app is supposed to calculate their position when other points are moved. These kinds of flags could be expressed as tags. We have several other point types and additional point behaviors in FontLab VI, but I cannot talk about them publicly at this point. They are useful for designers, and generally, their functioning is similar to the "inserted" RoboFont tag/flag or "interpolated" FontLab Studio 5.2 tag/flag. I can also imagine that a user could tag points with things like "round" or "inktrap" and then an app such as roundingUFO could have a mode where it only makes rounded corners or inktraps on points which have such tags, rather than on all corner points. These tags could also have a reversed meaning of course, so a user could prepare a design to be processed via roundingUFO, but could tag just a few points with "dontround" and then roundingUFO would keep these points as corners.
>
> There's tons of other such scenarios I can think of, but I hope the examples above show the general gist. :)

A few more scenarios have to do with problem-solving. For example, an app such as Prepolator could easily tag glyphs or contours or nodes with a tag "incompatible", which then another app could interpret and direct the user to the place where he or she may need to fix the master compatibility problem. Modules such as FontAudit or its cousins such as Red Arrow could similarly tag glyphs, points and contours with some tags which were for the user to resolve. Apps similar to FontQA could do it as well, and then separate "reporting" tools could take notion of it. Same goes for versioning conflicts: in a teamwork scenario, a "UFO diff" app could find conflicting git/svn commits and then tag the appropriate locations with a poblem code. Any standalone or commandline app could perform these checks and tagging, and then a completely separate app (say RoboFont) could simply point users to such locations and allow them to review and modify stuff.

The general difference between tags vs identifiers is like the difference between HTML classes and HTML ids. Sometimes you want to address something very specifically, but on other occasions, you want to address a group of objects that share a certain property. The tags mechanism allows for separation of markup and logic (you keep the markup simple, i.e. you tag, and the logic of what you want to do with it is done somewhere else), and is simple enough to be processable by both humans and machines.

Tags are great for "deferred operations". While working (designing, reviewing), you often want to "mark" an object for later reference, or as a hint/aid for some automatic process, and this may happen at one point in time. Then, at another point in time, you may want to revisit those objects, or you run software that performs some "magic" on all objects that share a certain tag.

A.

Tal Leming

unread,
Mar 15, 2015, 10:25:20 PM3/15/15
to ufo-...@googlegroups.com
Adam,

Wow, this is quite an unexpected screed. I'll do my best to work through it.

Before I get into addressing your comments, I'd like to again remind you that I have a limited amount of time for working on the UFO spec. I work on this voluntarily because I think it is important. I have an actual job (designing and producing fonts) that comes first because it pays the bills. The UFO spec has to work around that. In fact, tonight I had a little opening in my schedule and I was planning to work on UFO 4 tests. UFO 4 is being developed largely to address the needs of large fonts (see ...somewhere... in your message). Instead, I'm going to be responding to your various messages. Please keep this in mind before you start accusing me of moving too slowly, not supporting X, Y, Z or whatever.

> On Mar 12, 2015, at 11:54 PM, Adam Twardoch (List) <list...@twardoch.com> wrote:

> Well, given that the foundation of UFO is very much linked to FontLab Studio 5 (most data structures present in FLS 5 translate to UFO in some way) and AFDKO (most things that makeOTF expects as input are in UFO), I don't think you can really "unlink" UFO and app behavior. UFO seems also to be linked to defcon/Robofab. Given that RoboFont is a "UFO editor"

Correct. I will not deny that the UFO is a file format for storing data that can be edited by many different font editors. That's kind of the point. Hey, remember when you thought all of this was a silly idea!? We're finally making progress with you, Adam. ;)

> and there also seems to be a certain reluctance in introducing things to UFO that would be difficult for Frederik to implement.

That's a *very* serious accusation. I really don't even know how to reply to this. I mean, RoboFont doesn't support UFO 3 yet, so...what are you saying?

> UFO dictates app behavior in countless aspects implicitly. The fact that OpenType Layout feature definitions are stored in the text-based FEA format "dictates" that an app has to be able to deal with that format somehow. Limitations of the FEA format also dictate limitations of UFO and apps.

This was a pragmatic decision. We've been over this before, Adam. Here goes again: UFO 1 did not include features because, among other things, we wanted to come up with a Universal Abstract Feature Description Language that supported everything from GSUB to GPOS to GX. I spent a whole lot of time on this. It was an absurdly hard problem to solve in a nice way that, among other things, didn't violate Adobe's patents on describing features in a human readable way. I came up with something, tried it in production (it was used in a 2002-ish version of LetterSetter), it was...marginally just better than terrible. Specifying the conversion to and from this was a nightmare, so it went away. We got lots of requests for feature support in UFO 1, so we had to make a decision: keep hoping for a perfect new format or go with something that was already in existence. The three that we looked at were the .fea, VOLT and FontForge syntaxes. At that point, most of the people using UFO were writing their features in .fea. So, we made the pragmatic decision to support it. It caused some data duplication (name, OS/2, blah tables; kerning) but it was the best solution that we could come up with. In hindsight, we made the right decision.

This is very similar to the situation that we are in with hinting right now. There is perfect and then there is pragmatic. Pragmatic usually wins.

> I have yet to see an approach that would allow to easily "superpolate" arbitrary GPOS or GDEF features rather than just "kerning" and "anchors". Caret positions? Cursive attachment? Contextual GPOS rules? Most Indic scripts use GPOS for things far beyond "mark attachment", but there's hardly any trace of consideration for the needs of complex-script designers in UFO.

I'd love to see an actual proposal for solving this. I don't have any expertise in this area, so I don't know the parameters of the problems.

> UFO is useless without a FEA compiler. The Adobe implementation has only been opensourced last year (great!), but has been a closed-source app for more than a decade, and certainly has been at the time of the UFO inception.

This is very misleading. Adobe generously made the code available to anyone for compilation into their tools. Yuri didn't write a compiler for FontLab, he uses Adobe's. So, it's not like we picked some thing that required a licensing fee or anything like that. There was also FontForge's implementation of the translation of the syntax to binary, so there was an alternative to Adobe's code.

> UFO assumes that each "font" has its own set of glyphs, its own "features.plist" etc., despite the fact that in TTC, you can share glyphs, feature tables and other structures, and such practice is common in font development (CJK but not just). If you update a GLIF that is shared across 4 fonts in one UFO, you need to copy that GLIF into 3 other UFOs.

Multi-font relationships are something that is on my radar. It was cut from my presentation for time.

> Even the fact that UFO excludes certain structures from standardization dictates app behavior. If you're making an app that allows you to design monochrome PostScript outlines, monochrome TrueType outlines and color (or monochrome) SVG outlines simultaneously, you have a problem: you can put the set of PS outlines into one UFO, the set of TT outlines in another UFO, and the set of SVG outlines in some custom place in either UFO (or both?).

This is a workflow issue, not a file-format issue. Case in point: Adobe has a ton of people way smarter than me working on Photoshop/.psd, yet there is a non-trivial third-party industry built around Photoshop/.psd workflow problems.

> I commend the philosophical background to UFO, but I don't think UFO really delivers on its "high-level" promises. I'm not saying UFO should try to do it. But perhaps it's time to amend the UFO Design Philosophy towards actual practice. UFO is great, but it's great for "something" and certainly not "everything" or even "most things".

I'm pretty certain that we have never said that it is perfect for everything or even most things.

> I don't want to turn this into a "rant" about what's wrong with UFO

"...but you know me! ¯\_(ツ)_/¯"

> I hope you appreciate my feedback *despite* the critical tone.

I don't mind criticism at all. In fact, I welcome constructive criticism. Criticism that comes with realistic, implementable proposals is how the UFO is going to move beyond where it is now. The UFO arose as a solution to a particular set of problems. As new problems popped up, new solutions were added. The problems were almost always problems that we ran into ourselves. So, yeah, a lot of it is Western-centric because that's the kind of work that we do. We have made and continue to make inquiries about how UFO is working for CJK and other writing systems. I think it was in 2012 that I said that I wanted to add vertical kerning support to UFO if it was necessary and could any experts on that get in touch? No one contacted me. Does that mean that it's not a problem that needs to be solved? I don't know, but I do know that no one jumped up to say, "Yes, now, please!" If a problem isn't known by me, I can't solve it. If I'm not an expert on something that needs to be solved, I'm probably not going to be able to solve it myself. Community input is very important.

Furthermore, digital type design history is littered with ideas that seemed so promising at the time. I'd name some things, but I don't want to offend anyone, including myself (RIP Links :'( I'l always love you, Links). I know it can be frustrating that we don't jump as soon as an idea comes up. Putting something in the spec is permanent and it means that every font editor that implements the UFO is going to have to at minimum give thought to how or if the editor should support it. So, each new thing needs to have a demonstrable need for existence and it's data structures need to be as clear as can be. Time is the best judge for these things.

> I agree that hijacking the point "name" attribute for a multi-string storage (in the style that Frederik has done in RoboFont) is not elegant.

The name attribute is for names, not tags. So, no, it should not be used for this. If tags are needed, there should be a real place for them.

Thanks,
Tal

Reply all
Reply to author
Forward
0 new messages