-
-
Save ryanbugden/7b885e69768f5c618ae9cec418f102a6 to your computer and use it in GitHub Desktop.
(An ezui implementation) Copy glyphs from another source that don't exist in one of your UFOs.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # menuTitle: Copy Missing Glyphs from Other Source | |
| import ezui | |
| from mojo.UI import PostBannerNotification, getDefault | |
| from mojo.subscriber import Subscriber | |
| import drawBot | |
| import functools | |
| @functools.cache | |
| def colorImage(color, width=20, height=12): | |
| if color is None: | |
| return None | |
| drawBot.newDrawing() | |
| drawBot.newPage(width, height) | |
| drawBot.fill(*color) | |
| drawBot.rect(0, 0, width, height) | |
| im = drawBot.saveImage("NSImage") | |
| drawBot.endDrawing() | |
| return im | |
| class CopyMissingGlyphs(Subscriber, ezui.WindowController): | |
| def build(self): | |
| self.default_mark_colors = [value for (value, name) in getDefault("markColors")] | |
| content = """ | |
| * TwoColumnForm @form | |
| > :Source Font: | |
| > ( ...) @popUpSrce | |
| > :Destination Font: | |
| > ( ...) @popUpDest | |
| > ----------------- | |
| > :Mark Color: | |
| > (( ...)) @markColors | |
| > :Fit to: | |
| > (X) Cap-Height @heights | |
| > ( ) X-Height | |
| # (Scales contours and anchors, not components) | |
| > ----------------- | |
| > : | |
| > [ ] Only fill template glyphs @templateFill | |
| * HorizontalStack @bottomRow | |
| > %% @progressSpinner | |
| > (Copy Missing Glyphs) @commit | |
| """ | |
| title_width = 105 | |
| item_width = 190 | |
| descriptionData = dict( | |
| form=dict( | |
| titleColumnWidth=title_width, | |
| itemColumnWidth=item_width | |
| ), | |
| popUpSrce=dict( | |
| items=[], | |
| selected=1, | |
| width=item_width, | |
| ), | |
| popUpDest=dict( | |
| items=[], | |
| selected=0, # not necessary | |
| width=item_width, | |
| ), | |
| progressSpinner=dict( | |
| showWhenStopped=False, | |
| gravity="trailing" | |
| ), | |
| commit=dict( | |
| width=item_width, | |
| gravity="trailing" | |
| ), | |
| bottomRow=dict( | |
| distribution="gravity", | |
| ) | |
| ) | |
| self.w = ezui.EZPanel( | |
| content=content, | |
| descriptionData=descriptionData, | |
| title="Copy Missing Glyphs", | |
| controller=self | |
| ) | |
| self.pop_up_srce = self.w.getItem("popUpSrce") | |
| self.pop_up_dest = self.w.getItem("popUpDest") | |
| self.mark_colors = self.w.getItem("markColors") | |
| self.mark_colors.setItemDescriptions( | |
| [dict(image=colorImage(value), text=name) for (value, name) in getDefault("markColors")] | |
| ) | |
| self.spinner = self.w.getItem("progressSpinner") | |
| self.getAllFonts() | |
| def started(self): | |
| self.w.open() | |
| def getAllFonts(self): | |
| self.a = AllFonts() | |
| print("-1") | |
| self.list_of_fonts = [] # empty field if no fonts | |
| if self.a: | |
| for f in self.a: | |
| if f.info.familyName and f.info.styleName: | |
| self.list_of_fonts.append(f.info.familyName + " - " + f.info.styleName) | |
| else: # show "Untitled #" or whatever the new font display name is | |
| self.list_of_fonts.append(f._document._windowTitleDisplayName()) | |
| # set the menu | |
| self.pop_up_srce.setItems(self.list_of_fonts) | |
| self.pop_up_dest.setItems(self.list_of_fonts) | |
| self.pop_up_dest.set(0) | |
| self.pop_up_srce.set(0) | |
| if len(self.list_of_fonts) > 1: | |
| self.pop_up_srce.set(1) | |
| def fontDocumentDidOpen(self, info): | |
| self.getAllFonts() | |
| def fontDocumentDidOpenNew(self, info): | |
| self.getAllFonts() | |
| def commitCallback(self, sender): | |
| self.spinner.start() | |
| srce_f = self.a[self.w.getItem("popUpSrce").get()] | |
| dest_f = self.a[self.w.getItem("popUpDest").get()] | |
| scale_by = dest_f.info.capHeight / srce_f.info.capHeight | |
| if self.w.getItem("heights").get() == 1: | |
| scale_by = dest_f.info.xHeight / srce_f.info.xHeight | |
| mark_color_index = self.w.getItem("markColors").get() | |
| r,g,b,a = getDefault("markColors")[mark_color_index][0] | |
| for srce_g_name in srce_f.glyphOrder: | |
| for layer in srce_f.layers: | |
| if srce_g_name in layer.keys(): | |
| srce_g = layer[srce_g_name] | |
| # Match the default layers | |
| if layer == srce_f.defaultLayer: | |
| dest_layer = dest_f.defaultLayer | |
| else: | |
| if not layer in dest_f.layerOrder: | |
| dest_f.newLayer(layer.name) | |
| dest_layer = dest_f.getLayer(layer.name) | |
| if srce_g.name not in dest_layer.keys(): | |
| # Skip copying the glyph if it's not a template glyph in the destination font, and you've chosen that option in the window | |
| if self.w.getItem("templateFill").get() == True: | |
| if not srce_g.name in dest_f.templateGlyphOrder: | |
| continue | |
| dest_layer.newGlyph(srce_g.name) | |
| copied_glyph = srce_g.copy() | |
| # Only scale contours + anchors | |
| for c in copied_glyph.contours: | |
| c.scaleBy(scale_by, origin=(0,0)) | |
| for anc in copied_glyph.anchors: | |
| anc.scaleBy(scale_by, origin=(0,0)) | |
| copied_glyph.width = srce_g.width * scale_by | |
| dest_layer.insertGlyph(copied_glyph, name=srce_g.name) | |
| dest_layer[srce_g.name].markColor = (r,g,b,a) | |
| dest_f.changed() | |
| self.spinner.stop() | |
| # Notify what just happened | |
| message = f"Copying glyphs from {srce_f.info.familyName} {srce_f.info.styleName} into empty glyphs slots of {dest_f.info.familyName} {dest_f.info.styleName}." | |
| print(message) | |
| PostBannerNotification("Copied Missing Glyphs", message) | |
| CopyMissingGlyphs() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment