cu2qu icon indicating copy to clipboard operation
cu2qu copied to clipboard

otf2ttf?

Open davelab6 opened this issue 8 years ago • 9 comments

Has anyone used cu2qu to convert a cff (file.otf) to ttf (file.ttf)?

cu2qu works on Defcon/Robofab Font objects, and thus UFO sources. To convert a OTF to TTF means intermediate conversion to UFO, which I suppose https://github.com/typesupply/extractor may be used for?

BTW, https://github.com/caryll/otfcc seems to offer a straight forward otf2ttf

davelab6 avatar Sep 08 '16 18:09 davelab6

With the pens, it should be straightforward to convert. @anthrotype

behdad avatar Sep 08 '16 18:09 behdad

BTW, https://github.com/caryll/otfcc seems to offer a straight forward otf2ttf

Here's the package: https://github.com/caryll/otfcc-cubic2quad

It's executed so: otfccdump input.otf | otfcc-c2q | otfccbuild -o output.ttf

Where otfcc-c2q consumes, modifies and outputs the sfnt json serialization of otfccdump. I like the use of unix pipes here.

The script c2q.js has 88 lines and its only relevant dependency https://github.com/fontello/cubic2quad has 303 lines, the latter does the math.

I'm using this right now and it seems to work OK. I did not dig too deep though.

graphicore avatar Sep 09 '16 03:09 graphicore

All the pieces are there. otfcc is probably much faster.

import sys
from defcon import Font
from extractor import extractUFO
from cu2qu.ufo import font_to_quadratic
from ufo2ft import compileTTF

ufo = Font()
extractUFO(sys.argv[1], ufo)
font_to_quadratic(ufo)
ttf = compileTTF(ufo)
ttf.save(sys.argv[2])

moyogo avatar Sep 09 '16 04:09 moyogo

Have a look at extractor’s extractOpenTypeGlyphs() and ufo2ft’s OutlineTTFCompiler.setupTable_glyf() if you want to just use a pen and create a glyf table directly without going through a temporary UFO.

moyogo avatar Sep 09 '16 06:09 moyogo

If it is only about converting the glyph outlines, I'd not use the extractor because it likely to throw out lots of viable information (like non-kerning font features, even not all ways of OpenType kerning can be represented in UFO). It shouldn't be hard to just use the pens to create a new glyf table.

On Fri, Sep 9, 2016, 8:25 AM Denis Moyogo Jacquerye < [email protected]> wrote:

Have a look at ufo2ft’s outlineOTF. OutlineTTFCompiler.setupTable_glyf() https://github.com/googlei18n/ufo2ft/blob/8ce57a83460a6e9415fb26f4cbb0b4138f4cfaba/Lib/ufo2ft/outlineOTF.py#L938 if you want to just use a pen and create a glyf table directly without going through a temporary UFO.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/googlei18n/cu2qu/issues/47#issuecomment-245829966, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFu2iWXFGA7mAeFKs7AyAGWNXGHxLnsks5qoPvhgaJpZM4J4S20 .

khaledhosny avatar Sep 09 '16 08:09 khaledhosny

I found this in my stash. Maybe we could add it to fonttools Snippets.

from __future__ import print_function, division, absolute_import
import sys
from fontTools.ttLib import TTFont, newTable
from cu2qu.pens import Cu2QuPen
from fontTools.pens.ttGlyphPen import TTGlyphPen


# default approximation error
MAX_ERR = 1.0


def glyphs_to_quadratic(glyphs, max_err, **kwargs):
    quadGlyphs = {}
    for gname in glyphs.keys():
        glyph = glyphs[gname]
        ttPen = TTGlyphPen(glyphs)
        cu2quPen = Cu2QuPen(ttPen, max_err, **kwargs)
        glyph.draw(cu2quPen)
        quadGlyphs[gname] = ttPen.glyph()
    return quadGlyphs


def font_to_ttf(ttFont, max_err, **kwargs):
    glyphOrder = ttFont.getGlyphOrder()

    ttFont["loca"] = newTable("loca")
    ttFont["glyf"] = glyf = newTable("glyf")
    glyf.glyphOrder = glyphOrder
    glyf.glyphs = glyphs_to_quadratic(ttFont.getGlyphSet(), max_err, **kwargs)
    del ttFont["CFF "]

    ttFont["maxp"] = maxp = newTable("maxp")
    maxp.tableVersion = 0b10000
    maxp.maxZones = 1
    maxp.maxTwilightPoints = 0
    maxp.maxStorage = 0
    maxp.maxFunctionDefs = 0
    maxp.maxInstructionDefs = 0
    maxp.maxStackElements = 0
    maxp.maxSizeOfInstructions = 0
    maxp.maxComponentElements = max(
        len(g.components if hasattr(g, 'components') else [])
        for g in glyf.glyphs.values())

    post = ttFont["post"]
    post.formatType = 2.0
    post.extraNames = []
    post.mapping = {}
    post.glyphOrder = glyphOrder

    ttFont.sfntVersion = "\000\001\000\000"


if __name__ == "__main__":
    font = TTFont(sys.argv[1])
    font_to_ttf(font, max_err=MAX_ERR)
    font.save(sys.argv[2])

anthrotype avatar Sep 09 '16 09:09 anthrotype

Yes please, add it!

Typo in maxp version: 0b10000 should be 0x10000 instead, or better, 0x00010000.

behdad avatar Jan 12 '17 01:01 behdad

Note that for a font like NotoSansCJK that has 65535 glyphs, post table format 2.0 overflows. Trying with format 3.0 now.

behdad avatar Jan 12 '17 01:01 behdad

Post table format 3.0 worked. I got a NotoSansCJK.ttf file that seems to work.

behdad avatar Jan 12 '17 02:01 behdad