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

Updates to CID-keyed UFO handling #1628

Merged
merged 23 commits into from Apr 6, 2023
Merged

Conversation

punchcutter
Copy link
Contributor

@punchcutter punchcutter commented Mar 23, 2023

Added getGlyphByCID to uforead
@kaydeearts this is on top of your kd-fix-glyphname-search branch. We need the same CID functionality as in t1read and cffread so this is one of those things. We should also check the -decid flag and make sure we can do that with UFO as well.

@punchcutter
Copy link
Contributor Author

For reference we previously had an error fatal(h, "Cannot read glyphs from UFO fonts by CID "); when running a command like tx -g /12345 -ufo -o subset.ufo full.ufo
With this PR we can read by CID.

@punchcutter
Copy link
Contributor Author

I didn't run tests or add any new yet. Just want to get this out there first so we can look at it.

@punchcutter
Copy link
Contributor Author

punchcutter commented Mar 25, 2023

Related to the absfont_dump changes I made I noticed that dumping a CID-keyed UFO doesn't report CIDCount because it's not set in uforead until after we have read the glyphs in ufoIterateGlyphs. Other formats already contain cid.CIDCount at the top. Perhaps we should also write CIDCount into the lib.plist along with ROS and CIDFontName. Then we can read it back without going through every glyph first. That would also make it faster to get the value when reading the UFO with Python.

Update: we should be setting it in parseCIDMap instead of ufoIterateGlyphs. Then it works as expected. I pushed that commit which makes more sense since reading the cidmap is where that info comes from in the first place.

@punchcutter
Copy link
Contributor Author

With the last commit we get output like this from a CID-keyed UFO that also has real glyph names. By default we write UFOs with glyph names like cidXXXXX, but once in UFO they can be anything so we want to display them here. This also means we can convert to name-keyed and maintain the nice names.

## glyph[tag] {name,cid,iFD,LanguageGroup}
glyph[0] {.notdef,0,5,1}
glyph[1] {uni0020,1,14,0}
glyph[2] {uni0021,2,14,0}
glyph[3] {uni0022,3,14,0}
glyph[4] {uni0023,4,14,0}
glyph[5] {uni0024,5,14,0}
glyph[6] {uni0025,6,14,0}
glyph[7] {uni0026,7,14,0}
glyph[8] {uni0027,8,14,0}
glyph[9] {uni0028,9,14,0}
glyph[10] {uni0029,10,14,0}
glyph[11] {uni002A,11,14,0}
glyph[12] {uni002B,12,14,0}
glyph[13] {uni002C,13,14,0}
glyph[14] {uni002D,14,14,0}
glyph[15] {uni002E,15,14,0}
glyph[16] {uni002F,16,14,0}
glyph[17] {uni0030,17,14,0}
glyph[18] {uni0031,18,14,0}

@punchcutter punchcutter changed the title Add getGlyphByCID to uforead Updateds to CID-keyed UFO handling Mar 26, 2023
@punchcutter punchcutter changed the title Updateds to CID-keyed UFO handling Updates to CID-keyed UFO handling Mar 26, 2023
@punchcutter
Copy link
Contributor Author

I keep forgetting to put [skip ci] in these latest commits when I know tests will fail because of something unrelated.

@punchcutter
Copy link
Contributor Author

I made a few changes to writing the lib.plist. The CIDMap entry keys need to be ordered alphabetically or we fail in the uforead bsearch when checking glyphs. But we also want the public.glyphOrder to be sorted by CID. So now we get both. With this I can round trip dumping 18 FDicts as subset CID-keyed UFOs and then running mergefonts to put them back together. The only thing missing for that is that mergefonts doesn't yet understand how to maintain glyph names when merging UFOs, but that's probably not a big deal right now.

…warning because the dup glif is discarded earlier when calling findGLIFRecByName(h, glyphName). Previously, this was searching by fileName rather than glyphName.
…e have different inputs and different parsing functions that aren't all consistent yet. Better fixes in the future.
FPRINTF_S(h->fp, "## glyph[tag] {cid,iFD");
else
/* UFO can store names even when CID-keyed */
if (top->sup.srcFontType == 7) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there, or could there be, some constant defined to use instead of 7 here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duh, I have no idea why I put 7. The enum is abfSrcFontTypeUFOCID

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with the enum string instead of 7.

else
sprintf(gname, "cid%hu", info->cid);
if (info->gname.ptr != NULL) {
strcpy(gname, info->gname.ptr);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using strncpy seems particularly wise here given the fixed buffer size and the potentially unverified length.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

@@ -340,6 +340,86 @@ int ufwBegFont(ufwCtx h, long flags, char *glyphLayerDir) {
return ufwSuccess;
}

static void orderNameKeyedGlyphs(ufwCtx h) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we're using these n^2 sorts for stability?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think all this sorting is lovely, but cffwrite and t1write have ordering by CID or Name so I half copied what's done in those so that we can correctly sort here. The reason it came up was because we were writing the CIDMap in CID order which then made uforead fail to read it correctly, but more importantly if I open and save the UFO in typical UFO Python tools then the lib.plist was in a completely different. The whole XML dict is sorted by key including CIDMap and we weren't doing that in ufowrite so that's what all this does. Order by name so that we can write the CIDMap correctly and then order by CID so that public.glyphOrder is in the correct CID order. It's kind of ugly. We should really be reading all of this into a libxml2 structure and work from that, but this all works well enough so far.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking more about the efficiency than presence of the sorting, but I guess the worst case is 2^32 operations, which isn't a deal breaker.

I believe we use a canned quicksort elsewhere, which is why I asked about stability (quicksort isn't stable), but it seems like it's doubtful we'd have duplicate keys anyway (in which case stability isn't relevant).

I dunno, I guess we can do this for the time being and revisit later.

@kaydeearts kaydeearts requested a review from skef April 5, 2023 20:51
skef
skef previously approved these changes Apr 5, 2023
Copy link
Collaborator

@skef skef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

Copy link
Collaborator

@kaydeearts kaydeearts left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skef had already approved & I'm adding my 👍 !

@kaydeearts kaydeearts merged commit 23ddd12 into develop Apr 6, 2023
7 checks passed
@kaydeearts kaydeearts deleted the zqs-fix-ufo-GlyphByCID branch April 6, 2023 04:27
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

Successfully merging this pull request may close these issues.

None yet

3 participants