Beispiel #1
0
    def testSubsetting(self):
        "Tests TTFontFile and TTF parsing code"
        ttf = TTFontFile("Vera.ttf")
        subset = ttf.makeSubset([0x41, 0x42])
        subset = TTFontFile(StringIO(subset), 0)
        for tag in ('cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2',
                    'post', 'cvt ', 'fpgm', 'glyf', 'loca', 'prep'):
            self.assert_(subset.get_table(tag))

        subset.seek_table('loca')
        for n in range(4):
            pos = subset.read_ushort()  # this is actually offset / 2
            self.failIf(
                pos % 2 != 0,
                "glyph %d at +%d should be long aligned" % (n, pos * 2))

        self.assertEquals(subset.name, "BitstreamVeraSans-Roman")
        self.assertEquals(subset.flags, FF_SYMBOLIC)
        self.assertEquals(subset.italicAngle, 0.0)
        self.assertNear(subset.ascent, 759.765625)
        self.assertNear(subset.descent, -240.234375)
        self.assertEquals(subset.capHeight, 759.765625)
        self.assertNear(
            subset.bbox,
            [-183.10546875, -235.83984375, 1287.109375, 928.22265625])
        self.assertEquals(subset.stemV, 87)
Beispiel #2
0
    def testSubsetting(self):
        "Tests TTFontFile and TTF parsing code"
        ttf = TTFontFile("luxiserif.ttf")
        subset = ttf.makeSubset([0x41, 0x42])
        subset = TTFontFile(StringIO(subset), 0)
        for tag in ('cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2',
                    'post', 'cvt ', 'fpgm', 'glyf', 'loca', 'prep'):
            self.assert_(subset.get_table(tag))

        subset.seek_table('loca')
        for n in range(4):
            pos = subset.read_ushort()  # this is actually offset / 2
            self.failIf(
                pos % 2 != 0,
                "glyph %d at +%d should be long aligned" % (n, pos * 2))

        self.assertEquals(subset.name, "LuxiSerif")
        self.assertEquals(subset.flags, FF_SYMBOLIC)
        self.assertEquals(subset.italicAngle, 0.0)
        self.assertNear(subset.ascent, 783.203125)  # FIXME: or 992?
        self.assertNear(subset.descent, -205.078125)  # FIXME: or -210?
        self.assertEquals(subset.capHeight, 0)
        self.assertNear(subset.bbox,
                        [-203.125, -210.9375, 983.3984375, 992.67578125])
        self.assertEquals(subset.stemV, 87)
Beispiel #3
0
 def testFontFileChecksum(self):
     "Tests TTFontFile and TTF parsing code"
     file = TTFOpenFile("Vera.ttf")[1].read()
     TTFontFile(StringIO(file), validate=1)  # should not fail
     file1 = file[:12345] + "\xFF" + file[12346:]  # change one byte
     self.assertRaises(TTFError, TTFontFile, StringIO(file1), validate=1)
     file1 = file[:8] + "\xFF" + file[9:]  # change one byte
     self.assertRaises(TTFError, TTFontFile, StringIO(file1), validate=1)
Beispiel #4
0
 def testFontFileChecksum(self):
     "Tests TTFontFile and TTF parsing code"
     F = TTFOpenFile("Vera.ttf")[1].read()
     TTFontFile(getBytesIO(F), validate=1)  # should not fail
     F1 = F[:12345] + b"\xFF" + F[12346:]  # change one byte
     self.assertRaises(TTFError, TTFontFile, getBytesIO(F1), validate=1)
     F1 = F[:8] + b"\xFF" + F[9:]  # change one byte
     self.assertRaises(TTFError, TTFontFile, getBytesIO(F1), validate=1)
Beispiel #5
0
    def testSubsetting(self):
        "Tests TTFontFile and TTF parsing code"
        ttf = TTFontFile("luxiserif.ttf")
        subset = ttf.makeSubset([0x41, 0x42])
        subset = TTFontFile(StringIO(subset), 0)
        for tag in (
            "cmap",
            "head",
            "hhea",
            "hmtx",
            "maxp",
            "name",
            "OS/2",
            "post",
            "cvt ",
            "fpgm",
            "glyf",
            "loca",
            "prep",
        ):
            self.assert_(subset.get_table(tag))

        subset.seek_table("loca")
        for n in range(4):
            pos = subset.read_ushort()  # this is actually offset / 2
            self.failIf(pos % 2 != 0, "glyph %d at +%d should be long aligned" % (n, pos * 2))

        self.assertEquals(subset.name, "LuxiSerif")
        self.assertEquals(subset.flags, FF_SYMBOLIC)
        self.assertEquals(subset.italicAngle, 0.0)
        self.assertEquals(subset.ascent, 783)  # FIXME: or 992?
        self.assertEquals(subset.descent, -206)  # FIXME: or -210?
        self.assertEquals(subset.capHeight, 0)
        self.assertEquals(subset.bbox, [-204, -211, 983, 992])
        self.assertEquals(subset.stemV, 87)
Beispiel #6
0
 def testFontFile(self):
     "Tests TTFontFile and TTF parsing code"
     ttf = TTFontFile("Vera.ttf")
     self.assertEquals(ttf.name, "BitstreamVeraSans-Roman")
     self.assertEquals(ttf.flags, FF_SYMBOLIC)
     self.assertEquals(ttf.italicAngle, 0.0)
     self.assertNear(ttf.ascent,759.765625)
     self.assertNear(ttf.descent,-240.234375)
     self.assertEquals(ttf.capHeight, 759.765625)
     self.assertNear(ttf.bbox, [-183.10546875, -235.83984375, 1287.109375, 928.22265625])
     self.assertEquals(ttf.stemV, 87)
     self.assertEquals(ttf.defaultWidth, 600.09765625)
Beispiel #7
0
 def testFontFile(self):
     "Tests TTFontFile and TTF parsing code"
     ttf = TTFontFile("luxiserif.ttf")
     self.assertEquals(ttf.name, "LuxiSerif")
     self.assertEquals(ttf.flags, FF_SYMBOLIC)
     self.assertEquals(ttf.italicAngle, 0.0)
     self.assertNear(ttf.ascent, 783.203125)  # FIXME: or 992?
     self.assertNear(ttf.descent, -205.078125)  # FIXME: or -210?
     self.assertEquals(ttf.capHeight, 0)
     self.assertNear(ttf.bbox,
                     [-203.125, -210.9375, 983.3984375, 992.67578125])
     self.assertEquals(ttf.stemV, 87)
     self.assertEquals(ttf.defaultWidth, 250)
    def testSubsetting(self):
        "Tests TTFontFile and TTF parsing code"
        ttf = TTFontFile("Vera.ttf")
        subset = ttf.makeSubset([0x41, 0x42])
        subset = TTFontFile(getBytesIO(subset), 0)
        for tag in ('cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2',
                    'post', 'cvt ', 'fpgm', 'glyf', 'loca', 'prep'):
            self.assert_(subset.get_table(tag))

        subset.seek_table('loca')
        for n in range(4):
            pos = subset.read_ushort()    # this is actually offset / 2
            self.failIf(pos % 2 != 0, "glyph %d at +%d should be long aligned" % (n, pos * 2))

        self.assertEquals(subset.name, b"BitstreamVeraSans-Roman")
        self.assertEquals(subset.flags, FF_SYMBOLIC)
        self.assertEquals(subset.italicAngle, 0.0)
        self.assertNear(subset.ascent,759.765625)
        self.assertNear(subset.descent,-240.234375)
        self.assertEquals(subset.capHeight, 759.765625)
        self.assertNear(subset.bbox, [-183.10546875, -235.83984375, 1287.109375, 928.22265625])
        self.assertEquals(subset.stemV, 87)
    def testSubsetting(self):
        "Tests TTFontFile and TTF parsing code"
        ttf = TTFontFile("luxiserif.ttf")
        subset = ttf.makeSubset([0x41, 0x42])
        subset = TTFontFile(StringIO(subset), 0)
        for tag in ('cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'OS/2',
                    'post', 'cvt ', 'fpgm', 'glyf', 'loca', 'prep'):
            self.assert_(subset.get_table(tag))

        subset.seek_table('loca')
        for n in range(4):
            pos = subset.read_ushort()    # this is actually offset / 2
            self.failIf(pos % 2 != 0, "glyph %d at +%d should be long aligned" % (n, pos * 2))

        self.assertEquals(subset.name, "LuxiSerif")
        self.assertEquals(subset.flags, FF_SYMBOLIC)
        self.assertEquals(subset.italicAngle, 0.0)
        self.assertNear(subset.ascent,783.203125)       # FIXME: or 992?
        self.assertNear(subset.descent,-205.078125)     # FIXME: or -210?
        self.assertEquals(subset.capHeight, 0)
        self.assertNear(subset.bbox, [-203.125, -210.9375, 983.3984375, 992.67578125])
        self.assertEquals(subset.stemV, 87)
Beispiel #10
0
def loadFonts():
    """
    Search the system and build lists of available fonts.
    """

    if not any([afmList, pfbList, ttfList]):
        # FIXME: When we drop support por py2, use recursive globs
        for folder in flist:
            for root, _, files in os.walk(folder):
                for f in files:
                    if fnmatch(f, "*.ttf") or fnmatch(f, "*.ttc"):
                        ttfList.append(os.path.join(root, f))
                    elif fnmatch(f, "*.afm"):
                        afmList.append(os.path.join(root, f))
                    elif fnmatch(f, "*.pfb"):
                        pfbList[f[:-4]] = os.path.join(root, f)

        for ttf in ttfList:
            try:
                font = TTFontFile(ttf)
            except TTFError:
                log.warning("Error processing %s", ttf)
                continue

            family = make_string(font.familyName.lower())
            fontName = make_string(font.name).lower()
            baseName = os.path.basename(ttf)[:-4]
            fullName = make_string(font.fullName).lower()

            for k in (fontName, fullName, fullName.replace("italic", "oblique")):
                fonts[k] = (ttf, ttf, family)

            bold = FF_FORCEBOLD == FF_FORCEBOLD & font.flags
            italic = FF_ITALIC == FF_ITALIC & font.flags

            # And we can try to build/fill the family mapping
            if family not in families:
                families[family] = [fontName, fontName, fontName, fontName]
            if bold and italic:
                families[family][3] = fontName
            elif bold:
                families[family][1] = fontName
            elif italic:
                families[family][2] = fontName
            # FIXME: what happens if there are Demi and Medium
            # weights? We get a random one.
            else:
                families[family][0] = fontName

        # Now we have full afm and pbf lists, process the
        # afm list to figure out family name, weight and if
        # it's italic or not, as well as where the
        # matching pfb file is

        for afm in afmList:
            family = None
            fontName = None
            italic = False
            bold = False
            for line in open(afm, "r"):
                line = line.strip()
                if line.startswith("StartCharMetrics"):
                    break
                elif line.startswith("FamilyName"):
                    family = line.split(" ", 1)[1].lower()
                elif line.startswith("FontName"):
                    fontName = line.split(" ")[1]
                elif line.startswith("FullName"):
                    fullName = line.split(" ", 1)[1]
                elif line.startswith("Weight"):
                    bold = line.split(" ")[1] == "Bold"
                elif line.startswith("ItalicAngle"):
                    italic = line.split(" ")[1] != "0.0"

            baseName = os.path.basename(afm)[:-4]
            if family in Ignored or family in Alias:
                continue
            if baseName not in pfbList:
                log.info("afm file without matching pfb file: %s" % baseName)
                continue

            # So now we have a font we know we can embed.
            for n in (
                fontName.lower(),
                fullName.lower(),
                fullName.lower().replace("italic", "oblique"),
            ):
                fonts[n] = (afm, pfbList[baseName], family)

            # And we can try to build/fill the family mapping
            if family not in families:
                families[family] = [fontName, fontName, fontName, fontName]
            if bold and italic:
                families[family][3] = fontName
            elif bold:
                families[family][1] = fontName
            elif italic:
                families[family][2] = fontName
            # FIXME: what happens if there are Demi and Medium
            # weights? We get a random one.
            else:
                families[family][0] = fontName
Beispiel #11
0
    def search(self):
        started = time.clock()
        if not self._dirs:
            raise ValueError(
                "Font search path is empty!  Please specify search directories using addDirectory or addDirectories"
            )

        if self.useCache:
            cfn = self._getCacheFileName()
            if rl_isfile(cfn):
                try:
                    self.load(cfn)
                    #print "loaded cached file with %d fonts (%s)" % (len(self._fonts), cfn)
                    return
                except:
                    pass  #pickle load failed.  Ho hum, maybe it's an old pickle.  Better rebuild it.

        from stat import ST_MTIME
        for dirName in self._dirs:
            fileNames = rl_listdir(dirName)
            for fileName in fileNames:
                root, ext = os.path.splitext(fileName)
                if ext.lower() in EXTENSIONS:
                    #it's a font
                    f = FontDescriptor()
                    f.fileName = os.path.normpath(
                        os.path.join(dirName, fileName))
                    f.timeModified = rl_getmtime(f.fileName)

                    ext = ext.lower()
                    if ext[0] == '.':
                        ext = ext[1:]
                    f.typeCode = ext  #strip the dot

                    #what to do depends on type.  We only accept .pfb if we
                    #have .afm to go with it, and don't handle .otf now.

                    if ext in ('otf', 'pfa'):
                        self._skippedFiles.append(fileName)

                    elif ext in ('ttf', 'ttc'):
                        #parsing should check it for us
                        from reportlab.pdfbase.ttfonts import TTFontFile, TTFError
                        try:
                            font = TTFontFile(fileName, validate=self.validate)
                        except TTFError:
                            self._badFiles.append(fileName)
                            continue
                        f.name = font.name
                        f.fullName = font.fullName
                        f.styleName = font.styleName
                        f.familyName = font.familyName
                        f.isBold = (FF_FORCEBOLD == FF_FORCEBOLD & font.flags)
                        f.isItalic = (FF_ITALIC == FF_ITALIC & font.flags)

                    elif ext == 'pfb':

                        # type 1; we need an AFM file or have to skip.
                        if rl_isfile(os.path.join(dirName, root + '.afm')):
                            f.metricsFileName = os.path.normpath(
                                os.path.join(dirName, root + '.afm'))
                        elif rl_isfile(os.path.join(dirName, root + '.AFM')):
                            f.metricsFileName = os.path.normpath(
                                os.path.join(dirName, root + '.AFM'))
                        else:
                            self._skippedFiles.append(fileName)
                            continue
                        from reportlab.pdfbase.pdfmetrics import parseAFMFile

                        (info, glyphs) = parseAFMFile(f.metricsFileName)
                        f.name = info['FontName']
                        f.fullName = info.get('FullName', f.name)
                        f.familyName = info.get('FamilyName', None)
                        f.isItalic = (float(info.get('ItalicAngle', 0)) > 0.0)
                        #if the weight has the word bold, deem it bold
                        f.isBold = ('bold' in info.get('Weight', '').lower())

                    self._fonts.append(f)
        if self.useCache:
            self.save(cfn)

        finished = time.clock()
def loadFonts():
    """
    Search the system and build lists of available fonts.
    """

    if not afmList and not pfbList and not ttfList:
        # Find all ".afm" and ".pfb" files files
        def findFontFiles(_, folder, names):
            for f in os.listdir(folder):
                ext = os.path.splitext(f)[-1]
                if ext in ['.ttf', '.ttc']:
                    ttfList.append(os.path.join(folder, f))
                if ext == '.afm':
                    afmList.append(os.path.join(folder, f))
                if ext == '.pfb':
                    pfbList[f[:-4]] = os.path.join(folder, f)

        for folder in flist:
            os.path.walk(folder, findFontFiles, None)

        for ttf in ttfList:
            '''Find out how to process these'''
            try:
                font = TTFontFile(ttf)
            except TTFError:
                continue

            #print ttf, font.name, font.fullName, font.styleName, font.familyName
            family = font.familyName.lower()
            fontName = font.name
            baseName = os.path.basename(ttf)[:-4]
            fullName = font.fullName

            fonts[fontName.lower()] = (ttf, ttf, family)
            fonts[fullName.lower()] = (ttf, ttf, family)
            fonts[fullName.lower().replace('italic',
                                           'oblique')] = (ttf, ttf, family)
            bold = (FF_FORCEBOLD == FF_FORCEBOLD & font.flags)
            italic = (FF_ITALIC == FF_ITALIC & font.flags)

            # And we can try to build/fill the family mapping
            if family not in families:
                families[family] = [fontName, fontName, fontName, fontName]
            if bold and italic:
                families[family][3] = fontName
            elif bold:
                families[family][1] = fontName
            elif italic:
                families[family][2] = fontName
            # FIXME: what happens if there are Demi and Medium
            # weights? We get a random one.
            else:
                families[family][0] = fontName

        # Now we have full afm and pbf lists, process the
        # afm list to figure out family name, weight and if
        # it's italic or not, as well as where the
        # matching pfb file is

        for afm in afmList:
            family = None
            fontName = None
            italic = False
            bold = False
            for line in open(afm, 'r'):
                line = line.strip()
                if line.startswith('StartCharMetrics'):
                    break
                elif line.startswith('FamilyName'):
                    family = ' '.join(line.split(' ')[1:]).lower()
                elif line.startswith('FontName'):
                    fontName = line.split(' ')[1]
                # TODO: find a way to alias the fullname to this font
                # so you can use names like "Bitstream Charter Italic"
                elif line.startswith('FullName'):
                    fullName = ' '.join(line.split(' ')[1:])
                elif line.startswith('Weight'):
                    w = line.split(' ')[1]
                    if w == 'Bold':
                        bold = True
                elif line.startswith('ItalicAngle'):
                    if line.split(' ')[1] != '0.0':
                        italic = True

            baseName = os.path.basename(afm)[:-4]
            if family in Ignored:
                continue
            if family in Alias:
                continue
            if baseName not in pfbList:
                log.info("afm file without matching pfb file: %s" % baseName)
                continue

            # So now we have a font we know we can embed.
            fonts[fontName.lower()] = (afm, pfbList[baseName], family)
            fonts[fullName.lower()] = (afm, pfbList[baseName], family)
            fonts[fullName.lower().replace(
                'italic', 'oblique')] = (afm, pfbList[baseName], family)

            # And we can try to build/fill the family mapping
            if family not in families:
                families[family] = [fontName, fontName, fontName, fontName]
            if bold and italic:
                families[family][3] = fontName
            elif bold:
                families[family][1] = fontName
            elif italic:
                families[family][2] = fontName
            # FIXME: what happens if there are Demi and Medium
            # weights? We get a random one.
            else:
                families[family][0] = fontName