Esempio n. 1
0
    def is_valid(self):
        content = {}
        with io.open(self.fontpath, 'r', encoding="utf-8") as fp:
            content = json.load(fp, object_pairs_hook=collections.OrderedDict)

        if len(content.get('designer', '').split()) > 4:
            logger.error(
                'ER: Designer key is too long. Fix to "Multiple Designer"')
            return False
        if ' and ' in content.get('designer', ''):
            logger.error(
                'ER: Several designers in designer key. Fix to "Multiple Designer"'
            )
            return False
        if ',' in content.get('designer', ''):
            logger.error(
                'ER: Several designers in designer key. Fix to "Multiple Designer"'
            )
            return False
        if '.' in content.get('designer', ''):
            logger.error(
                'ER: Several designers in designer key. Fix to "Multiple Designer"'
            )
            return False

        logger.info(u'OK: Designer "{}"'.format(content.get('designer', '')))
        return True
Esempio n. 2
0
def run(command, cwd=None):
    """ Wrapper for subprocess.Popen with custom logging support.

        :param command: shell command to run, required
        :param cwd: - current working dir, required
        :param log: - logging object with .write() method, required

    """
    # Start the command
    env = os.environ.copy()

    logger.info('$ %s\n' %
                command.replace(os_origin.getcwd() + os.path.sep, ''))
    env.update({'PYTHONPATH': os_origin.pathsep.join(sys.path)})
    process = subprocess.Popen(command,
                               shell=True,
                               cwd=cwd or os_origin.getcwd(),
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               close_fds=True,
                               env=env)
    out, err = process.communicate()
    if out.strip():
        logger.info(out.strip())
    if err.strip():
        logger.error(err.strip())
    return out
Esempio n. 3
0
 def logging_raw(self, message):
     if message.startswith('### ') or message.startswith('## '):
         message = '\n' * 3 + message.strip()
     if message.startswith('$ '):
         message = '\n' + message.strip().replace(os.getcwd() + os.path.sep,
                                                  '')
     logger.info(message)
Esempio n. 4
0
    def fix(self, check=False):
        space = self.getGlyph(0x0020)
        nbsp = self.getGlyph(0x00A0)
        isNbspAdded = isSpaceAdded = False
        if not nbsp:
            isNbspAdded = True
            try:
                nbsp = self.addGlyph(0x00A0, 'nbsp')
            except Exception as ex:
                logger.error('ER: {}'.format(ex))
                return False
        if not space:
            isSpaceAdded = True
            try:
                space = self.addGlyph(0x0020, 'space')
            except Exception as ex:
                logger.error('ER: {}'.format(ex))
                return False

        spaceWidth = self.getWidth(space)
        nbspWidth = self.getWidth(nbsp)

        fontfile = os.path.basename(self.fontpath)
        if spaceWidth != nbspWidth or nbspWidth < 0:

            self.setWidth(nbsp, max(nbspWidth, spaceWidth))
            self.setWidth(space, max(nbspWidth, spaceWidth))

            if isNbspAdded:
                if check:
                    msg = 'ER: {} space {} nbsp N: Add nbsp'
                    logger.error(msg.format(fontfile, spaceWidth))
                else:
                    msg = 'ER: {} space {} nbsp N: Added nbsp to {}'
                    logger.error(msg.format(fontfile, spaceWidth, spaceWidth))

            if isSpaceAdded:
                if check:
                    msg = 'ER: {} space N nbsp {}: Add space'
                    logger.error(msg.format(fontfile, nbspWidth))
                else:
                    msg = 'ER: {} space N nbsp {}: Added space {}'
                    logger.error(msg.format(fontfile, nbspWidth, nbspWidth))
                
            if nbspWidth < spaceWidth:
                if check:
                    msg = 'ER: {} space {} nbsp {}: Change nbsp to {}'
                else:
                    msg = 'ER: {} space {} nbsp {}: Fixed nbsp to {}'
                logger.error(msg.format(fontfile, spaceWidth, nbspWidth, spaceWidth))
            else:
                if check:
                    msg = 'ER: {} space {} nbsp {}: Change space to {}'
                else:
                    msg = 'ER: {} space {} nbsp {}: Fixed space to {}'
                logger.error(msg.format(fontfile, spaceWidth, nbspWidth, nbspWidth))
            return True

        logger.info('OK: {} space {} nbsp {}'.format(fontfile, spaceWidth, nbspWidth))
        return
Esempio n. 5
0
    def show(self):
        if 'gasp' not in self.font.tables:
            logger.error('no table gasp')
            return

        try:
            logger.info(self.font['gasp'].gaspRange[65535])
        except IndexError:
            logger.error('no index 65535')
Esempio n. 6
0
    def logging_task(self, message):
        if self.forcerun:
            self.incr_total_tasks()
            return

        prefix = "### (%s of %s) " % (self._counter, self.total_tasks)
        self.incr_task_counter()

        logger.info('\n\n\n' + (prefix + message.strip()).strip())
Esempio n. 7
0
    def logging_task(self, message):
        if self.forcerun:
            self.incr_total_tasks()
            return

        prefix = "### (%s of %s) " % (self._counter, self.total_tasks)
        self.incr_task_counter()

        logger.info('\n\n\n' + (prefix + message.strip()).strip())
Esempio n. 8
0
    def show(self, path):
        try:
            table = self.font.get('gasp')
        except:
            logger.error('ER: {}: no table gasp'.format(path))
            return

        try:
            logger.info(self.font.get('gasp').gaspRange[65535])
        except IndexError:
            logger.error('ER: {}: no index 65535'.format(path))
Esempio n. 9
0
    def show(self, path):
        try:
            table = self.font.get('gasp')
        except:
            logger.error('ER: {}: no table gasp'.format(path))
            return

        try:
            logger.info(self.font.get('gasp').gaspRange[65535])
        except IndexError:
            logger.error('ER: {}: no index 65535'.format(path))
Esempio n. 10
0
    def addSuccess(self, test):
        super(BakeryTestResult, self).addSuccess(test)

        if hasattr(test, 'operator'):
            logger.info(self._format_test_output(test, 'OK'))

        test_method = getattr(test, test._testMethodName)
        if hasattr(test_method, 'autofix'):
            # if testcase is marked as autofixed then add it to ff
            if hasattr(self.ff, 'append'):
                self.ff.append(test)
        elif hasattr(self.sl, 'append'):
            self.sl.append(test)
Esempio n. 11
0
    def addSuccess(self, test):
        super(BakeryTestResult, self).addSuccess(test)

        if hasattr(test, 'operator'):
            logger.info(self._format_test_output(test, 'OK'))

        test_method = getattr(test, test._testMethodName)
        if hasattr(test_method, 'autofix'):
            # if testcase is marked as autofixed then add it to ff
            if hasattr(self.ff, 'append'):
                self.ff.append(test)
        elif hasattr(self.sl, 'append'):
            self.sl.append(test)
Esempio n. 12
0
def convert(sourceFont, ttf, otf=None):
    try:
        font = fontforge.open(sourceFont)
    except:
        logger.error("Error: Could not open font (%s)" % sourceFont)
        return

    font.selection.all()

    # Remove overlap
    try:
        font.removeOverlap()
    except:
        logger.error("Error: Could not remove overlaps")

    if otf:
        try:
            font.generate(otf)
            logger.info("OK: Generated OpenType-CFF (%s)" % otf)
        except:
            logger.error("Error: Could not generate OpenType-CFF (%s)" % otf)

    # Convert curves to quadratic (TrueType)
    try:
        font.layers["Fore"].is_quadratic = True
    except:
        logger.error("Error: Could not convert to quadratic TrueType curves")
        return

    # Simplify
    try:
        font.simplify(1, ('setstarttoextremum',
                          'removesingletonpoints',
                          'mergelines'))
    except:
        logger.error("Error: Could not simplify")

    # Correct Directions
    try:
        font.correctDirection()
    except:
        logger.error("Error: Could not correct directions")

    # Generate with DSIG and OpenType tables
    try:
        flags = ('dummy-dsig', 'opentype')
        font.generate(ttf, flags=flags)
        logger.info("Success: Generated OpenType-TTF (%s)" % ttf)
    except:
        logger.error("Error: Could not generate OpenType-TTF (%s)" % ttf)
        return
Esempio n. 13
0
    def callmethod(self, methodname, test):
        import inspect
        pkg = '.'.join(methodname.split('.')[:-1])
        mod = importlib.import_module(pkg)
        method = getattr(mod, methodname.split('.')[-1])

        if not inspect.isclass(method):
            return method(test)
        klass_instance = method(test, test.operator.path)
        if hasattr(klass_instance, 'get_shell_command'):
            logger.info('$ {}'.format(klass_instance.get_shell_command()))

        if test.apply_fix:
            klass_instance.apply(override_origin=test.apply_fix)
Esempio n. 14
0
    def callmethod(self, methodname, test):
        import inspect
        pkg = '.'.join(methodname.split('.')[:-1])
        mod = importlib.import_module(pkg)
        method = getattr(mod, methodname.split('.')[-1])

        if not inspect.isclass(method):
            return method(test)
        klass_instance = method(test, test.operator.path)
        if hasattr(klass_instance, 'get_shell_command'):
            logger.info('$ {}'.format(klass_instance.get_shell_command()))

        if test.apply_fix:
            klass_instance.apply(override_origin=test.apply_fix)
Esempio n. 15
0
    def fix(self, check=False):
        val = self.font['OS/2'].fsType
        fontfile = os.path.basename(self.fontpath)

        if val == 0:
            from bakery_cli.bakery import Bakery
            logger.info('OK: {}'.format(fontfile))
            return

        if check:
            logger.error('ER: {} {}: Change to 0'.format(fontfile, val))
        else:
            logger.error('ER: {} {}: Fixed to 0'.format(fontfile, val))
            self.font['OS/2'].fsType = 0
        return True
Esempio n. 16
0
    def fix(self, check=False):
        val = self.font['OS/2'].fsType
        fontfile = os.path.basename(self.fontpath)

        if val == 0:
            from bakery_cli.bakery import Bakery
            logger.info('OK: {}'.format(fontfile))
            return

        if check:
            logger.error('ER: {} {}: Change to 0'.format(fontfile, val))
        else:
            logger.error('ER: {} {}: Fixed to 0'.format(fontfile, val))
            self.font['OS/2'].fsType = 0
        return True
Esempio n. 17
0
    def fix(self):
        newfilename = self.validate()

        new_targetpath = os.path.join(os.path.dirname(self.fontpath),
                                      newfilename)
        shutil.move(self.fontpath, new_targetpath)

        from bakery_cli.logger import logger
        logger.info('$ mv {} {}'.format(self.fontpath, os.path.basename(new_targetpath)))

        self.testcase.operator.path = new_targetpath
        from bakery_cli.utils import ProcessedFile
        
        f = ProcessedFile()
        f.filepath = newfilename

        self.save_after_fix = False
        return True
Esempio n. 18
0
    def fix(self):
        newfilename = self.validate()

        new_targetpath = os.path.join(os.path.dirname(self.fontpath),
                                      newfilename)
        shutil.move(self.fontpath, new_targetpath)

        from bakery_cli.logger import logger
        logger.info('$ mv {} {}'.format(self.fontpath,
                                        os.path.basename(new_targetpath)))

        self.testcase.operator.path = new_targetpath
        from bakery_cli.utils import ProcessedFile

        f = ProcessedFile()
        f.filepath = newfilename

        self.save_after_fix = False
        return True
Esempio n. 19
0
    def fix(self, check=True):
        if check:
            if not self.is_valid():
                return False
            return True

        if self.is_valid():
            logger.info(u'OK: Designer "{}"'.format(content.get('designer', '')))
            return True

        from bakery_cli.scripts.genmetadata import striplines
        content = {}
        with io.open(self.fontpath, 'r', encoding="utf-8") as fp:
            content = json.load(fp, object_pairs_hook=collections.OrderedDict)

        content['designer'] = 'Multiple Designers'
        with io.open(self.fontpath, 'w', encoding='utf-8') as f:
            contents = json.dumps(content, indent=2, ensure_ascii=False)
            f.write(striplines(contents))
        return True
Esempio n. 20
0
    def is_valid(self):
        content = {}
        with io.open(self.fontpath, 'r', encoding="utf-8") as fp:
            content = json.load(fp, object_pairs_hook=collections.OrderedDict)

        if len(content.get('designer', '').split()) > 4:
            logger.error('ER: Designer key is too long. Fix to "Multiple Designer"')
            return False
        if ' and ' in content.get('designer', ''):
            logger.error('ER: Several designers in designer key. Fix to "Multiple Designer"')
            return False
        if ',' in content.get('designer', ''):
            logger.error('ER: Several designers in designer key. Fix to "Multiple Designer"')
            return False
        if '.' in content.get('designer', ''):
            logger.error('ER: Several designers in designer key. Fix to "Multiple Designer"')
            return False

        logger.info(u'OK: Designer "{}"'.format(content.get('designer', '')))
        return True
Esempio n. 21
0
    def fix(self, check=True):
        if check:
            if not self.is_valid():
                return False
            return True

        if self.is_valid():
            logger.info(u'OK: Designer "{}"'.format(content.get(
                'designer', '')))
            return True

        from bakery_cli.scripts.genmetadata import striplines
        content = {}
        with io.open(self.fontpath, 'r', encoding="utf-8") as fp:
            content = json.load(fp, object_pairs_hook=collections.OrderedDict)

        content['designer'] = 'Multiple Designers'
        with io.open(self.fontpath, 'w', encoding='utf-8') as f:
            contents = json.dumps(content, indent=2, ensure_ascii=False)
            f.write(striplines(contents))
        return True
Esempio n. 22
0
    def is_valid(self):
        has_errors = False
        regex = re.compile(r'-(.*?)Italic\.ttf')
        match = regex.search(self.fontpath)
        if match:
            ttfont = ttLib.TTFont(self.fontpath)

            f = '{:#010b}'.format(ttfont['head'].macStyle)
            if match.group(1) != 'Bold':
                if not bool(ttfont['head'].macStyle & 0b10):
                    logger.error(
                        'ER: HEAD macStyle is {} should be 00000010'.format(f))
                    has_errors = True
            elif not bool(ttfont['head'].macStyle & 0b11):
                logger.error(
                    'ER: HEAD macStyle is {} should be 00000011'.format(f))
                has_errors = True

            if ttfont['post'].italicAngle == 0:
                logger.error('ER: POST italicAngle is 0 should be -13')
                has_errors = True
            # Check NAME table contains correct names for Italic
            if ttfont['OS/2'].fsSelection & 0b1:
                logger.info('OK: OS/2 fsSelection')
            else:
                logger.error('ER: OS/2 fsSelection')
            for name in ttfont['name'].names:
                if name.nameID not in [2, 4, 6, 17]:
                    continue

                string = name.toUnicode()

                if string.endswith('Italic'):
                    logger.info('OK: NAME ID{}:\t{}'.format(
                        name.nameID, string))
                else:
                    logger.error('ER: NAME ID{}:\t{}'.format(
                        name.nameID, string))
        else:
            pass
Esempio n. 23
0
    def is_valid(self):
        has_errors = False
        regex = re.compile(r'-(.*?)Italic\.ttf')
        match = regex.search(self.fontpath)
        if match:
            ttfont = ttLib.TTFont(self.fontpath)

            f = '{:#010b}'.format(ttfont['head'].macStyle)
            if match.group(1) != 'Bold':
                if not bool(ttfont['head'].macStyle & 0b10):
                    logger.error('ER: HEAD macStyle is {} should be 00000010'.format(f))
                    has_errors = True
            elif not bool(ttfont['head'].macStyle & 0b11):
                    logger.error('ER: HEAD macStyle is {} should be 00000011'.format(f))
                    has_errors = True

            if ttfont['post'].italicAngle == 0:
                logger.error('ER: POST italicAngle is 0 should be -13')
                has_errors = True
            # Check NAME table contains correct names for Italic
            if ttfont['OS/2'].fsSelection & 0b1:
                logger.info('OK: OS/2 fsSelection')
            else:
                logger.error('ER: OS/2 fsSelection')
            for name in ttfont['name'].names:
                if name.nameID not in [2, 4, 6, 17]:
                    continue

                if name.isUnicode():
                    string = name.string.decode('utf-16-be')
                else:
                    string = name.string
                if string.endswith('Italic'):
                    logger.info('OK: NAME ID{}:\t{}'.format(name.nameID, string))
                else:
                    logger.error('ER: NAME ID{}:\t{}'.format(name.nameID, string))
        else:
            pass
Esempio n. 24
0
def run(command, cwd=None):
    """ Wrapper for subprocess.Popen with custom logging support.

        :param command: shell command to run, required
        :param cwd: - current working dir, required
        :param log: - logging object with .write() method, required

    """
    # Start the command
    env = os.environ.copy()

    logger.info('$ %s\n' % command.replace(os_origin.getcwd() + os.path.sep, ''))
    env.update({'PYTHONPATH': os_origin.pathsep.join(sys.path)})
    process = subprocess.Popen(command, shell=True, cwd=cwd or os_origin.getcwd(),
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE,
                               close_fds=True, env=env)
    out, err = process.communicate()
    if out.strip():
        logger.info(out.strip())
    if err.strip():
        logger.error(err.strip())
    return out
Esempio n. 25
0
    def fix(self, check=False):
        retval = False
        fontfile = os.path.basename(self.fontpath)

        space = self.getGlyph(0x0020)
        nbsp = self.getGlyph(0x00A0)
        if space not in ["space", "uni0020"]:
            logger.error(
                'ER: {}: Glyph 0x0020 is called "{}": Change to "space" or "uni0020"'
                .format(fontfile, space))
        if nbsp not in ["nbsp", "uni00A0"]:
            logger.error(
                'ER: {}: Glyph 0x00A0 is called "{}": Change to "nbsp" or "uni00A0"'
                .format(fontfile, nbsp))

        isNbspAdded = isSpaceAdded = False
        if not nbsp:
            isNbspAdded = True
            try:
                nbsp = self.addGlyph(0x00A0, 'nbsp')
            except Exception as ex:
                logger.error('ER: {}'.format(ex))
                return False
        if not space:
            isSpaceAdded = True
            try:
                space = self.addGlyph(0x0020, 'space')
            except Exception as ex:
                logger.error('ER: {}'.format(ex))
                return False

        for g in [space, nbsp]:
            if self.glyphHasInk(g):
                if check:
                    logger.error(
                        'ER: {}: Glyph "{}" has ink. Delete any contours or components'
                        .format(fontfile, g))
                else:
                    logger.error(
                        'ER: {}: Glyph "{}" has ink. Fixed: Overwritten by an empty glyph'
                        .format(fontfile, g))
                    #overwrite existing glyph with an empty one
                    self.font['glyf'].glyphs[g] = ttLib.getTableModule(
                        'glyf').Glyph()
                    retval = True

        spaceWidth = self.getWidth(space)
        nbspWidth = self.getWidth(nbsp)

        if spaceWidth != nbspWidth or nbspWidth < 0:

            self.setWidth(nbsp, min(nbspWidth, spaceWidth))
            self.setWidth(space, min(nbspWidth, spaceWidth))

            if isNbspAdded:
                if check:
                    msg = 'ER: {} space {} nbsp None: Add nbsp with advanceWidth {}'
                else:
                    msg = 'ER: {} space {} nbsp None: Added nbsp with advanceWidth {}'
                logger.error(msg.format(fontfile, spaceWidth, spaceWidth))

            if isSpaceAdded:
                if check:
                    msg = 'ER: {} space None nbsp {}: Add space with advanceWidth {}'
                else:
                    msg = 'ER: {} space None nbsp {}: Added space with advanceWidth {}'
                logger.error(msg.format(fontfile, nbspWidth, nbspWidth))

            if nbspWidth > spaceWidth and spaceWidth >= 0:
                if check:
                    msg = 'ER: {} space {} nbsp {}: Change space advanceWidth to {}'
                else:
                    msg = 'ER: {} space {} nbsp {}: Fixed space advanceWidth to {}'
                logger.error(
                    msg.format(fontfile, spaceWidth, nbspWidth, nbspWidth))
            else:
                if check:
                    msg = 'ER: {} space {} nbsp {}: Change nbsp advanceWidth to {}'
                else:
                    msg = 'ER: {} space {} nbsp {}: Fixed nbsp advanceWidth to {}'
                logger.error(
                    msg.format(fontfile, spaceWidth, nbspWidth, spaceWidth))
            return True

        logger.info('OK: {} space {} nbsp {}'.format(fontfile, spaceWidth,
                                                     nbspWidth))
        return retval
Esempio n. 26
0
 def logging_cmd(self, message):
     logger.info('\n$ ' +
                 message.strip().replace(os.getcwd() + os.path.sep, ''))
Esempio n. 27
0
 def logging_cmd(self, message):
     logger.info('\n$ ' + message.strip().replace(os.getcwd() + os.path.sep, ''))
Esempio n. 28
0
 def logging_raw(self, message):
     if message.startswith('### ') or message.startswith('## '):
         message = '\n' * 3 + message.strip()
     if message.startswith('$ '):
         message = '\n' + message.strip().replace(os.getcwd() + os.path.sep, '')
     logger.info(message)
Esempio n. 29
0
def validate(font, fontStyle):
    errors = []

    f = '{:#09b}'.format(font['head'].macStyle)

    if fontStyle.endswith('Italic'):
        if not fontStyleIsBold(fontStyle):
            if not bool(font['head'].macStyle & 0b10):
                errors.append(('ER: HEAD macStyle is {} should be 00000010'.format(f),
                               setMacStyle, [font, font['head'].macStyle | 0b10]))
        elif not bool(font['head'].macStyle & 0b11):
            errors.append(('ER: HEAD macStyle is {} should be 00000011'.format(f),
                           setMacStyle, [font, font['head'].macStyle | 0b11]))
    else:
        if not fontStyleIsBold(fontStyle):
            if bool(font['head'].macStyle & 0b10):
                newvalue = font['head'].macStyle | 0b1111111111111100
                errors.append(('ER: HEAD macStyle is {} should be {:#09b}'.format(f, newvalue),
                               setMacStyle, [font, newvalue]))
        elif bool(font['head'].macStyle & 0b01):
            newvalue = font['head'].macStyle | 0b1111111111111101
            errors.append(('ER: HEAD macStyle is {} should be {:#09b}'.format(f, newvalue),
                           setMacStyle, [font, newvalue]))

    if font['post'].italicAngle != 0 and not fontStyle.endswith('Italic'):
        errors.append(('ER: POST italicAngle is {} should be 0'.format(font['post'].italicAngle),
                       italicAngle, [font, 0]))

    if font['post'].italicAngle == 0 and fontStyle.endswith('Italic'):
        newvalue = getSuggestedItalicAngle(font)
        errors.append(('ER: POST italicAngle is 0 should be {}'.format(newvalue),
                       italicAngle, [font, newvalue]))

    # Check NAME table contains correct names for Italic
    if fontStyle.endswith('Italic'):

        if not fontStyleIsBold(fontStyle):
            if font['OS/2'].fsSelection & 0b000001:
                logger.info('OK: OS/2 fsSelection')
            else:
                newvalue = font['OS/2'].fsSelection | 0b1
                msg = 'ER: OS/2 fsSelection is {:#06b} should be {:#06b}'
                errors.append((msg.format(font['OS/2'].fsSelection, newvalue),
                               setFsSelection, [font, newvalue]))
        else:
            if font['OS/2'].fsSelection & 0b100001:
                logger.info('OK: OS/2 fsSelection')
            else:
                newvalue = font['OS/2'].fsSelection | 0b100001
                msg = 'ER: OS/2 fsSelection is {:#06b} should be {:#06b}'
                errors.append((msg.format(font['OS/2'].fsSelection, newvalue),
                               setFsSelection, [font, newvalue]))

    elif fontStyleIsBold(fontStyle):
        if font['OS/2'].fsSelection & 0b100000:
            logger.info('OK: OS/2 fsSelection')
        else:
            newvalue = font['OS/2'].fsSelection | 0b100000
            msg = 'ER: OS/2 fsSelection is {:#06b} should be {:#06b}'
            errors.append((msg.format(font['OS/2'].fsSelection, newvalue),
                           setFsSelection, [font, newvalue]))

    for name in font['name'].names:
        if name.nameID not in [2, 4, 6, 17]:
            continue

        string = name.string.decode(name.getEncoding())

        if fontStyle.endswith('Italic'):
            if string.endswith('Italic'):
                logger.info('OK: NAME ID{}:\t{}'.format(name.nameID, string))
            else:
                errors.append(('ER: NAME ID{}:\t{}'.format(name.nameID, string),
                               setValidNames, [font, fontStyleIsBold(fontStyle)]))
        elif fontStyleIsBold(fontStyle):
            if fontStyleIsBold(string):
                logger.info('OK: NAME ID{}:\t{}'.format(name.nameID, string))
            else:
                errors.append(('ER: NAME ID{}:\t{}'.format(name.nameID, string),
                               setValidNames, [font, fontStyleIsBold(fontStyle)]))

    return errors
Esempio n. 30
0
    def fix(self, check=False):
        retval = False
        fontfile = os.path.basename(self.fontpath)

        space = self.getGlyph(0x0020)
        nbsp = self.getGlyph(0x00A0)
        if space not in ["space", "uni0020"]:
            logger.error('ER: {}: Glyph 0x0020 is called "{}": Change to "space" or "uni0020"'.format(fontfile, space))
        if nbsp not in ["nbsp", "uni00A0"]:
            logger.error('ER: {}: Glyph 0x00A0 is called "{}": Change to "nbsp" or "uni00A0"'.format(fontfile, nbsp))

        isNbspAdded = isSpaceAdded = False
        if not nbsp:
            isNbspAdded = True
            try:
                nbsp = self.addGlyph(0x00A0, 'nbsp')
            except Exception as ex:
                logger.error('ER: {}'.format(ex))
                return False
        if not space:
            isSpaceAdded = True
            try:
                space = self.addGlyph(0x0020, 'space')
            except Exception as ex:
                logger.error('ER: {}'.format(ex))
                return False

        for g in [space, nbsp]:
            if self.glyphHasInk(g):
                if check:
                    logger.error('ER: {}: Glyph "{}" has ink. Delete any contours or components'.format(fontfile, g))
                else:
                    logger.error('ER: {}: Glyph "{}" has ink. Fixed: Overwritten by an empty glyph'.format(fontfile, g))
                    #overwrite existing glyph with an empty one
                    self.font['glyf'].glyphs[g] = ttLib.getTableModule('glyf').Glyph()
                    retval = True

        spaceWidth = self.getWidth(space)
        nbspWidth = self.getWidth(nbsp)

        if spaceWidth != nbspWidth or nbspWidth < 0:

            self.setWidth(nbsp, min(nbspWidth, spaceWidth))
            self.setWidth(space, min(nbspWidth, spaceWidth))

            if isNbspAdded:
                if check:
                    msg = 'ER: {} space {} nbsp None: Add nbsp with advanceWidth {}'
                else:
                    msg = 'ER: {} space {} nbsp None: Added nbsp with advanceWidth {}'
                logger.error(msg.format(fontfile, spaceWidth, spaceWidth))

            if isSpaceAdded:
                if check:
                    msg = 'ER: {} space None nbsp {}: Add space with advanceWidth {}'
                else:
                    msg = 'ER: {} space None nbsp {}: Added space with advanceWidth {}'
                logger.error(msg.format(fontfile, nbspWidth, nbspWidth))
                
            if nbspWidth > spaceWidth and spaceWidth >= 0:
                if check:
                    msg = 'ER: {} space {} nbsp {}: Change space advanceWidth to {}'
                else:
                    msg = 'ER: {} space {} nbsp {}: Fixed space advanceWidth to {}'
                logger.error(msg.format(fontfile, spaceWidth, nbspWidth, nbspWidth))
            else:
                if check:
                    msg = 'ER: {} space {} nbsp {}: Change nbsp advanceWidth to {}'
                else:
                    msg = 'ER: {} space {} nbsp {}: Fixed nbsp advanceWidth to {}'
                logger.error(msg.format(fontfile, spaceWidth, nbspWidth, spaceWidth))
            return True

        logger.info('OK: {} space {} nbsp {}'.format(fontfile, spaceWidth, nbspWidth))
        return retval