Exemplo n.º 1
0
    def open(self, use_hash_map):
        font_path = self.font_path

        if self.font_format == 'UFO':
            self.font_type = UFO_FONT_TYPE
            ufotools.validateLayers(font_path)
            self.defcon_font = defcon.Font(font_path)
            self.ufo_format = self.defcon_font.ufoFormatVersionTuple
            self.use_hash_map = use_hash_map
            self.ufo_font_hash_data = ufotools.UFOFontData(
                font_path,
                self.use_hash_map,
                programName=ufotools.kCheckOutlineName)
            self.ufo_font_hash_data.readHashMap()

        else:
            print("Converting to temp UFO font...")
            self.temp_ufo_path = temp_path = get_temp_dir_path('font.ufo')

            if not run_shell_command(['tx', '-ufo', font_path, temp_path]):
                raise FocusFontError('Failed to convert input font to UFO.')

            try:
                self.defcon_font = defcon.Font(temp_path)
            except UFOLibError:
                raise

            if self.font_format == 'OTF':
                self.font_type = OTF_FONT_TYPE
            elif self.font_format == 'CFF':
                self.font_type = CFF_FONT_TYPE
            else:
                self.font_type = TYPE1_FONT_TYPE

        return self.defcon_font
Exemplo n.º 2
0
def run(args):
    options = Options(args)

    # Set the current dir to the design space dir, so that relative paths in
    # the design space file will work.
    dsDir, dsFile = os.path.split(os.path.abspath(options.dsPath))
    os.chdir(dsDir)
    options.dsPath = dsFile

    dsPath, newInstancesList = readDesignSpaceFile(options)
    if not dsPath:
        return

    version = 2
    if len(newInstancesList) == 1:
        logMsg.log("Building 1 instance...")
    else:
        logMsg.log("Building %s instances..." % (len(newInstancesList)))
    mutatorMathBuild(documentPath=dsPath,
                     outputUFOFormatVersion=version,
                     roundGeometry=(not options.allowDecimalCoords))
    if (dsPath != options.dsPath) and os.path.exists(dsPath):
        os.remove(dsPath)

    logMsg.log("Built %s instances." % (len(newInstancesList)))
    # Remove glyph.lib and font.lib (except for "public.glyphOrder")
    for instancePath in newInstancesList:
        postProcessInstance(instancePath, options)

    if options.doNormalize:
        logMsg.log("Applying UFO normalization...")
        for instancePath in newInstancesList:
            normalizeUFO(instancePath,
                         outputPath=None,
                         onlyModified=True,
                         writeModTimes=False)

    if options.doAutoHint or options.doOverlapRemoval:
        logMsg.log("Applying post-processing...")
        # Apply autohint and checkoutlines, if requested.
        for instancePath in newInstancesList:
            # make new instance font.
            updateInstance(options, instancePath)

    # checkoutlinesufo does ufotools.validateLayers()
    if not options.doOverlapRemoval:
        for instancePath in newInstancesList:
            # make sure that that there are no old glyphs left in the
            # processed glyphs folder
            validateLayers(instancePath)

    # The defcon library renames glyphs. Need to fix them again
    if options.doOverlapRemoval or options.doAutoHint:
        for instancePath in newInstancesList:
            if options.doNormalize:
                normalizeUFO(instancePath,
                             outputPath=None,
                             onlyModified=False,
                             writeModTimes=False)
Exemplo n.º 3
0
    def open(self, use_hash_map):
        font_path = self.font_path
        try:
            ufotools.validateLayers(font_path)
            self.defcon_font = defcon.Font(font_path)
            self.ufo_format = self.defcon_font.ufoFormatVersion
            if self.ufo_format < 2:
                self.ufo_format = 2
            self.font_type = UFO_FONT_TYPE
            self.use_hash_map = use_hash_map
            self.ufo_font_hash_data = ufotools.UFOFontData(
                font_path,
                self.use_hash_map,
                programName=ufotools.kCheckOutlineName)
            self.ufo_font_hash_data.readHashMap()

        except ufoLib.UFOLibError as e:
            if (not os.path.isdir(font_path)) \
                    and "metainfo.plist is missing" in e.message:
                # It was a file, but not a UFO font.
                # Try converting to UFO font, and try again.
                print("converting to temp UFO font...")
                self.temp_ufo_path = temp_path = font_path + ".temp.ufo"
                if os.path.exists(temp_path):
                    shutil.rmtree(temp_path)
                cmd = "tx -ufo \"%s\" \"%s\"" % (font_path, temp_path)
                subprocess.call(cmd,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.STDOUT)
                if os.path.exists(temp_path):
                    try:
                        self.defcon_font = defcon.Font(temp_path)
                    except ufoLib.UFOLibError:
                        return
                    # It must be a font file!
                    self.temp_ufo_path = temp_path
                    # figure out font type.
                    try:
                        ff = open(font_path, "rb")
                        data = ff.read(10)
                        ff.close()
                    except (IOError, OSError):
                        return
                    if data[:4] == "OTTO":  # it is an OTF font.
                        self.font_type = OPENTYPE_CFF_FONT_TYPE
                    elif (data[0] == '\1') and (data[1] == '\0'):  # CFF file
                        self.font_type = CFF_FONT_TYPE
                    elif "%" in data:
                        self.font_type = TYPE1_FONT_TYPE
                    else:
                        print('Font type is unknown: '
                              'will not be able to save changes')
            else:
                raise e
        return self.defcon_font
Exemplo n.º 4
0
    def open(self, use_hash_map):
        font_path = self.font_path
        try:
            ufotools.validateLayers(font_path)
            self.defcon_font = defcon.Font(font_path)
            self.ufo_format = self.defcon_font.ufoFormatVersion
            if self.ufo_format < 2:
                self.ufo_format = 2
            self.font_type = UFO_FONT_TYPE
            self.use_hash_map = use_hash_map
            self.ufo_font_hash_data = ufotools.UFOFontData(
                font_path, self.use_hash_map,
                programName=ufotools.kCheckOutlineName)
            self.ufo_font_hash_data.readHashMap()

        except ufoLib.UFOLibError as e:
            if (not os.path.isdir(font_path)) \
                    and "metainfo.plist is missing" in e.message:
                # It was a file, but not a UFO font.
                # Try converting to UFO font, and try again.
                print("converting to temp UFO font...")
                self.temp_ufo_path = temp_path = font_path + ".temp.ufo"
                if os.path.exists(temp_path):
                    shutil.rmtree(temp_path)
                cmd = "tx -ufo \"%s\" \"%s\"" % (font_path, temp_path)
                subprocess.call(
                    cmd, shell=True,
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT)
                if os.path.exists(temp_path):
                    try:
                        self.defcon_font = defcon.Font(temp_path)
                    except ufoLib.UFOLibError:
                        return
                    # It must be a font file!
                    self.temp_ufo_path = temp_path
                    # figure out font type.
                    try:
                        ff = open(font_path, "rb")
                        data = ff.read(10)
                        ff.close()
                    except (IOError, OSError):
                        return
                    if data[:4] == "OTTO":  # it is an OTF font.
                        self.font_type = OPENTYPE_CFF_FONT_TYPE
                    elif (data[0] == '\1') and (data[1] == '\0'):  # CFF file
                        self.font_type = CFF_FONT_TYPE
                    elif "%" in data:
                        self.font_type = TYPE1_FONT_TYPE
                    else:
                        print('Font type is unknown: '
                              'will not be able to save changes')
            else:
                raise e
        return self.defcon_font
Exemplo n.º 5
0
def run(options):

    # Set the current dir to the design space dir, so that relative paths in
    # the design space file will work.
    dsDir, dsFile = os.path.split(os.path.abspath(options.dsPath))
    os.chdir(dsDir)
    options.dsPath = dsFile

    dsPath, newInstancesList = readDesignSpaceFile(options)
    if not dsPath:
        return

    if len(newInstancesList) == 1:
        logger.info("Building 1 instance...")
    else:
        logger.info("Building %s instances..." % len(newInstancesList))
    ufoProcessorBuild(documentPath=dsPath,
                      outputUFOFormatVersion=options.ufo_version,
                      roundGeometry=(not options.no_round),
                      logger=logger)
    if (dsPath != options.dsPath) and os.path.exists(dsPath):
        os.remove(dsPath)

    logger.info("Built %s instances." % len(newInstancesList))
    # Remove glyph.lib and font.lib (except for "public.glyphOrder")
    for instancePath in newInstancesList:
        postProcessInstance(instancePath, options)

    if options.doNormalize:
        logger.info("Applying UFO normalization...")
        for instancePath in newInstancesList:
            normalizeUFO(instancePath, outputPath=None, onlyModified=True,
                         writeModTimes=False)

    if options.doAutoHint or options.doOverlapRemoval:
        logger.info("Applying post-processing...")
        # Apply autohint and checkoutlines, if requested.
        for instancePath in newInstancesList:
            # make new instance font.
            updateInstance(options, instancePath)

    # checkoutlinesufo does ufotools.validateLayers()
    if not options.doOverlapRemoval:
        for instancePath in newInstancesList:
            # make sure that that there are no old glyphs left in the
            # processed glyphs folder
            validateLayers(instancePath)

    # The defcon library renames glyphs. Need to fix them again
    if options.doOverlapRemoval or options.doAutoHint:
        for instancePath in newInstancesList:
            if options.doNormalize:
                normalizeUFO(instancePath, outputPath=None, onlyModified=False,
                             writeModTimes=False)
Exemplo n.º 6
0
def run(args=None):
    options = get_options(args)
    font_path = os.path.abspath(options.file_path)
    font_file = FontFile(font_path)
    defcon_font = font_file.open(options.allow_changes)
    # We allow use of a hash map to skip glyphs only if fixing glyphs
    if options.clear_hash_map:
        font_file.clear_hash_map()
        return

    if defcon_font is None:
        print("Could not open  file: %s." % font_path)
        return

    if not options.glyph_list:
        glyph_list = list(defcon_font.keys())
    else:
        if not defcon_font.glyphOrder:
            raise FocusFontError(
                "Error: public.glyphOrder is empty or missing "
                "from lib.plist file of %s" %
                os.path.abspath(options.file_path))
        else:
            glyph_list = filter_glyph_list(options.glyph_list,
                                           defcon_font.glyphOrder,
                                           options.file_path)
    if not glyph_list:
        raise FocusFontError(
            "Error: selected glyph list is empty for font <%s>." %
            options.file_path)

    if not options.write_to_default_layer:
        try:
            processed_layer = defcon_font.layers[PROCD_GLYPHS_LAYER_NAME]
        except KeyError:
            processed_layer = defcon_font.newLayer(PROCD_GLYPHS_LAYER_NAME)
    else:
        processed_layer = None
        font_file.save_to_default_layer = True
    font_changed = False
    last_had_msg = False
    seen_glyph_count = 0
    processed_glyph_count = 0
    for glyph_name in sorted(glyph_list):
        changed = False
        seen_glyph_count += 1
        msg = []

        if glyph_name not in defcon_font:
            continue

        # font_file.check_skip_glyph updates the hash map for the glyph,
        # so we call it even when the  '-all' option is used.
        skip = font_file.check_skip_glyph(glyph_name, options.check_all)
        # Note: this will delete glyphs from the processed layer,
        #       if the glyph hash has changed.
        if skip:
            continue
        processed_glyph_count += 1

        defcon_glyph = defcon_font[glyph_name]
        if defcon_glyph.components:
            defcon_glyph.decomposeAllComponents()
        new_glyph = booleanOperations.booleanGlyph.BooleanGlyph(defcon_glyph)
        if len(new_glyph) == 0:
            # Complain about empty glyph only if it is not a space glyph.
            if not RE_SPACE_PATTERN.search(glyph_name):
                msg = ["has no contours"]
            else:
                msg = []
        else:
            for test in options.test_list:
                if test is not None:
                    new_glyph, changed, msg = \
                        test(new_glyph, changed, msg, options)

        if not options.quiet_mode:
            if len(msg) == 0:
                if last_had_msg:
                    print()
                print('.', end='')
                last_had_msg = False
            else:
                print(os.linesep + glyph_name, ' '.join(msg), end='')
                last_had_msg = True
        if changed and options.allow_changes:
            font_changed = True
            original_contours = list(defcon_glyph)
            font_file.update_hash_entry(glyph_name, changed)
            if options.write_to_default_layer:
                fixed_glyph = defcon_glyph
                fixed_glyph.clearContours()
            else:
                # this will replace any pre-existing glyph:
                processed_layer.newGlyph(glyph_name)
                fixed_glyph = processed_layer[glyph_name]
                fixed_glyph.width = defcon_glyph.width
                fixed_glyph.height = defcon_glyph.height
                fixed_glyph.unicodes = defcon_glyph.unicodes
            point_pen = fixed_glyph.getPointPen()
            new_glyph.drawPoints(point_pen)
            if options.allow_decimal_coords:
                for contour in fixed_glyph:
                    for point in contour:
                        point.x = round(point.x, 3)
                        point.y = round(point.y, 3)
            else:
                for contour in fixed_glyph:
                    for point in contour:
                        point.x = int(round(point.x))
                        point.y = int(round(point.y))
            restore_contour_order(fixed_glyph, original_contours)
        # The following is needed when the script is called from another
        # script with Popen():
        sys.stdout.flush()
    # update layer plist: the hash check call may have deleted processed layer
    # glyphs because the default layer glyph is newer.

    # At this point, we may have deleted glyphs in the
    # processed layer.writer.getGlyphSet()
    # will fail unless we update the contents.plist file to match.
    if options.allow_changes:
        ufotools.validateLayers(font_path, False)

    if not font_changed:
        # Even if the program didn't change any glyphs,
        # we should still save updates to the src glyph hash file.
        font_file.close()
    else:
        font_file.save()

    if processed_glyph_count != seen_glyph_count:
        print("Skipped %s of %s glyphs." %
              (seen_glyph_count - processed_glyph_count, seen_glyph_count))
    if not options.quiet_mode:
        print("Done with font")
def run(options):

    ds_doc = DesignSpaceDocument.fromfile(options.dsPath)

    # can still have a successful read but useless DSD (no sources, no
    # instances, sources non-existent, other conditions
    validateDesignspaceDoc(ds_doc, options)

    copy_features = any(src.copyFeatures for src in ds_doc.sources)
    features_store = {}
    if not copy_features:
        # '<features copy="1"/>' is NOT set in any of masters.
        # Collect the contents of 'features.fea' of any existing
        # instances so that they can be restored later.
        features_store = collect_features_content(ds_doc.instances,
                                                  options.indexList)

    # Set the current dir to the design space dir, so that relative paths in
    # the design space file will work.
    dsDir, dsFile = os.path.split(os.path.abspath(options.dsPath))
    os.chdir(dsDir)
    options.dsPath = dsFile

    if options.indexList:
        dsPath = filterDesignspaceInstances(ds_doc, options)
    else:
        dsPath = dsFile

    newInstancesList = [inst.path for inst in ds_doc.instances]
    newInstancesCount = len(newInstancesList)

    if newInstancesCount == 1:
        logger.info("Building 1 instance...")
    else:
        logger.info("Building %s instances..." % newInstancesCount)
    ufoProcessorBuild(documentPath=dsPath,
                      outputUFOFormatVersion=options.ufo_version,
                      roundGeometry=(not options.no_round),
                      logger=logger)
    if (dsPath != options.dsPath) and os.path.exists(dsPath):
        os.remove(dsPath)

    logger.info("Built %s instances." % newInstancesCount)
    # Remove glyph.lib and font.lib (except for "public.glyphOrder")
    for instancePath in newInstancesList:
        postProcessInstance(instancePath, options)

    if options.doNormalize:
        logger.info("Applying UFO normalization...")
        for instancePath in newInstancesList:
            normalizeUFO(instancePath,
                         outputPath=None,
                         onlyModified=True,
                         writeModTimes=False)

    if options.doAutoHint or options.doOverlapRemoval:
        logger.info("Applying post-processing...")
        # Apply autohint and checkoutlines, if requested.
        for instancePath in newInstancesList:
            # make new instance font.
            updateInstance(instancePath, options)

    # checkoutlinesufo does ufotools.validateLayers()
    if not options.doOverlapRemoval:
        for instancePath in newInstancesList:
            # make sure that there are no old glyphs left in the
            # processed glyphs folder
            validateLayers(instancePath)

    # The defcon library renames glyphs. Need to fix them again
    if options.doOverlapRemoval or options.doAutoHint:
        for instancePath in newInstancesList:
            if options.doNormalize:
                normalizeUFO(instancePath,
                             outputPath=None,
                             onlyModified=False,
                             writeModTimes=False)

    # Restore the contents of the instances' 'features.fea' files
    for fea_pth, fea_cntnts in features_store.items():
        with open(fea_pth, 'w') as fp:
            fp.write(fea_cntnts)
Exemplo n.º 8
0
def run(args=None):
    options = get_options(args)
    font_path = options.font_path
    font_format = options.font_format
    font_file = FontFile(font_path, font_format)
    use_hash_map = True if font_format == 'UFO' else False
    defcon_font = font_file.open(use_hash_map)
    if font_format == 'PFC':
        font_format = 'UFO'

    # We allow use of a hash map to skip glyphs only if fixing glyphs
    if options.clear_hash_map:
        font_file.clear_hash_map()
        return

    if defcon_font is None:
        print("Could not open file: %s." % font_path)
        return

    if not options.glyph_list:
        glyph_list = list(defcon_font.keys())
    else:
        if not defcon_font.glyphOrder:
            raise FocusFontError(
                "Error: public.glyphOrder is empty or missing "
                "from lib.plist file of %s" % font_path)
        else:
            glyph_list = filter_glyph_list(options.glyph_list,
                                           defcon_font.glyphOrder, font_path)
    if not glyph_list:
        raise FocusFontError(
            "Error: selected glyph list is empty for font <%s>." % font_path)

    if (font_format == 'UFO') and (not options.write_to_default_layer):
        try:
            processed_layer = defcon_font.layers[PROCD_GLYPHS_LAYER_NAME]
        except KeyError:
            processed_layer = defcon_font.newLayer(PROCD_GLYPHS_LAYER_NAME)
    else:
        processed_layer = None
        font_file.save_to_default_layer = True

    font_changed = False
    seen_glyph_count = 0
    processed_glyph_count = 0

    max_length = max([len(g) for g in glyph_list])
    fmt = '{:<%d}' % max_length
    glyph_list = sorted(glyph_list)
    list_length = len(glyph_list)
    with trange(list_length) as t:
        for i in t:
            glyph_name = glyph_list[i]
            t.set_description('Checking outlines for %s' %
                              fmt.format(glyph_name))
            changed = False
            seen_glyph_count += 1
            msg = []

            if glyph_name not in defcon_font:
                continue

            # font_file.check_skip_glyph updates the hash map for the glyph,
            # so we call it even when the  '-all' option is used.
            skip = font_file.check_skip_glyph(glyph_name, options.check_all)
            # Note: this will delete glyphs from the processed layer,
            #       if the glyph hash has changed.
            if skip:
                continue
            processed_glyph_count += 1

            defcon_glyph = defcon_font[glyph_name]
            if defcon_glyph.components:
                defcon_glyph.decomposeAllComponents()
            new_glyph = booleanOperations.booleanGlyph.BooleanGlyph(
                defcon_glyph)
            if len(new_glyph) == 0:
                # Complain about empty glyph only if it is not a space glyph.
                if not RE_SPACE_PATTERN.search(glyph_name):
                    msg = ["has no contours"]
                else:
                    msg = []
            else:
                for test in options.test_list:
                    if test is not None:
                        new_glyph, changed, msg = \
                            test(new_glyph, changed, msg, options)

            if not options.quiet_mode:
                if msg:
                    tqdm.write('%s %s' % (glyph_name, ' '.join(msg)))
            if changed and options.allow_changes:
                font_changed = True
                original_contours = list(defcon_glyph)
                if font_file.save_to_default_layer:
                    fixed_glyph = defcon_glyph
                    fixed_glyph.clearContours()
                else:
                    # this will replace any pre-existing glyph:
                    processed_layer.newGlyph(glyph_name)
                    fixed_glyph = processed_layer[glyph_name]
                    fixed_glyph.width = defcon_glyph.width
                    fixed_glyph.height = defcon_glyph.height
                    fixed_glyph.unicodes = defcon_glyph.unicodes
                point_pen = fixed_glyph.getPointPen()
                new_glyph.drawPoints(point_pen)
                if options.allow_decimal_coords:
                    for contour in fixed_glyph:
                        for point in contour:
                            point.x = round(point.x, 3)
                            point.y = round(point.y, 3)
                else:
                    for contour in fixed_glyph:
                        for point in contour:
                            point.x = int(round(point.x))
                            point.y = int(round(point.y))

                # JH May 2020: remove overlap can leave some coincident points
                # we use thresholdAttrGlyph (modified thresholdPen) to remove
                # them prior to restore_contour_order.
                thresholdAttrGlyph(fixed_glyph, 1)

                if not options.ignore_contour_order:
                    restore_contour_order(fixed_glyph, original_contours)

            # The following is needed when the script is called from another
            # script with Popen():
            sys.stdout.flush()
            if i == list_length - 1:
                t.set_description("Finished checkoutlinesufo")

    # update layer plist: the hash check call may have deleted processed layer
    # glyphs because the default layer glyph is newer.

    # At this point, we may have deleted glyphs in the
    # processed layer.writer.getGlyphSet()
    # will fail unless we update the contents.plist file to match.
    if options.allow_changes:
        ufotools.validateLayers(font_path, False)

    if not font_changed:
        # Even if the program didn't change any glyphs,
        # we should still save updates to the src glyph hash file.
        font_file.close()
    else:
        font_file.save()

    if processed_glyph_count != seen_glyph_count:
        print("Skipped %s of %s glyphs." %
              (seen_glyph_count - processed_glyph_count, seen_glyph_count))
    if not options.quiet_mode:
        print("Done with font")
Exemplo n.º 9
0
def run(args=None):
    options = get_options(args)
    font_path = os.path.abspath(options.file_path)
    font_file = FontFile(font_path)
    defcon_font = font_file.open(options.allow_changes)
    # We allow use of a hash map to skip glyphs only if fixing glyphs
    if options.clear_hash_map:
        font_file.clear_hash_map()
        return

    if defcon_font is None:
        print("Could not open  file: %s." % font_path)
        return

    if not options.glyph_list:
        glyph_list = list(defcon_font.keys())
    else:
        if not defcon_font.glyphOrder:
            raise FocusFontError(
                "Error: public.glyphOrder is empty or missing "
                "from lib.plist file of %s" %
                os.path.abspath(options.file_path))
        else:
            glyph_list = filter_glyph_list(
                options.glyph_list, defcon_font.glyphOrder, options.file_path)
    if not glyph_list:
        raise FocusFontError(
            "Error: selected glyph list is empty for font <%s>." %
            options.file_path)

    if not options.write_to_default_layer:
        try:
            processed_layer = defcon_font.layers[PROCD_GLYPHS_LAYER_NAME]
        except KeyError:
            processed_layer = defcon_font.newLayer(PROCD_GLYPHS_LAYER_NAME)
    else:
        processed_layer = None
        font_file.save_to_default_layer = True
    font_changed = False
    last_had_msg = False
    seen_glyph_count = 0
    processed_glyph_count = 0
    for glyph_name in sorted(glyph_list):
        changed = False
        seen_glyph_count += 1
        msg = []

        if glyph_name not in defcon_font:
            continue

        # font_file.check_skip_glyph updates the hash map for the glyph,
        # so we call it even when the  '-all' option is used.
        skip = font_file.check_skip_glyph(glyph_name, options.check_all)
        # Note: this will delete glyphs from the processed layer,
        #       if the glyph hash has changed.
        if skip:
            continue
        processed_glyph_count += 1

        defcon_glyph = defcon_font[glyph_name]
        if defcon_glyph.components:
            defcon_glyph.decomposeAllComponents()
        new_glyph = booleanOperations.booleanGlyph.BooleanGlyph(defcon_glyph)
        if len(new_glyph) == 0:
            # Complain about empty glyph only if it is not a space glyph.
            if not RE_SPACE_PATTERN.search(glyph_name):
                msg = ["has no contours"]
            else:
                msg = []
        else:
            for test in options.test_list:
                if test is not None:
                    new_glyph, changed, msg = \
                        test(new_glyph, changed, msg, options)

        if not options.quiet_mode:
            if len(msg) == 0:
                if last_had_msg:
                    print()
                print('.', end='')
                last_had_msg = False
            else:
                print(os.linesep + glyph_name, ' '.join(msg), end='')
                last_had_msg = True
        if changed and options.allow_changes:
            font_changed = True
            original_contours = list(defcon_glyph)
            if options.write_to_default_layer:
                fixed_glyph = defcon_glyph
                fixed_glyph.clearContours()
            else:
                # this will replace any pre-existing glyph:
                processed_layer.newGlyph(glyph_name)
                fixed_glyph = processed_layer[glyph_name]
                fixed_glyph.width = defcon_glyph.width
                fixed_glyph.height = defcon_glyph.height
                fixed_glyph.unicodes = defcon_glyph.unicodes
            point_pen = fixed_glyph.getPointPen()
            new_glyph.drawPoints(point_pen)
            if options.allow_decimal_coords:
                for contour in fixed_glyph:
                    for point in contour:
                        point.x = round(point.x, 3)
                        point.y = round(point.y, 3)
            else:
                for contour in fixed_glyph:
                    for point in contour:
                        point.x = int(round(point.x))
                        point.y = int(round(point.y))
            restore_contour_order(fixed_glyph, original_contours)
        # The following is needed when the script is called from another
        # script with Popen():
        sys.stdout.flush()
    # update layer plist: the hash check call may have deleted processed layer
    # glyphs because the default layer glyph is newer.

    # At this point, we may have deleted glyphs in the
    # processed layer.writer.getGlyphSet()
    # will fail unless we update the contents.plist file to match.
    if options.allow_changes:
        ufotools.validateLayers(font_path, False)

    if not font_changed:
        # Even if the program didn't change any glyphs,
        # we should still save updates to the src glyph hash file.
        font_file.close()
    else:
        font_file.save()

    if processed_glyph_count != seen_glyph_count:
        print("Skipped %s of %s glyphs." %
              (seen_glyph_count - processed_glyph_count, seen_glyph_count))
    if not options.quiet_mode:
        print("Done with font")