Exemple #1
0
    def get_embed_font_info(self, family, failure_critical=True):
        efi = []
        body_font_family = None
        if not family:
            return body_font_family, efi
        from calibre.utils.fonts.scanner import font_scanner, NoFonts
        from calibre.utils.fonts.utils import panose_to_css_generic_family
        try:
            faces = font_scanner.fonts_for_family(family)
        except NoFonts:
            msg = (u'No embeddable fonts found for family: %r' % family)
            if failure_critical:
                raise ValueError(msg)
            self.oeb.log.warn(msg)
            return body_font_family, efi
        if not faces:
            msg = (u'No embeddable fonts found for family: %r' % family)
            if failure_critical:
                raise ValueError(msg)
            self.oeb.log.warn(msg)
            return body_font_family, efi

        for i, font in enumerate(faces):
            ext = 'otf' if font['is_otf'] else 'ttf'
            fid, href = self.oeb.manifest.generate(
                id=u'font',
                href=u'fonts/%s.%s' %
                (ascii_filename(font['full_name']).replace(u' ', u'-'), ext))
            item = self.oeb.manifest.add(fid,
                                         href,
                                         guess_type('dummy.' + ext)[0],
                                         data=font_scanner.get_font_data(font))
            item.unload_data_from_memory()

            cfont = {
                u'font-family': u'"%s"' % font['font-family'],
                u'panose-1': u' '.join(map(unicode_type, font['panose'])),
                u'src': u'url(%s)' % item.href,
            }

            if i == 0:
                generic_family = panose_to_css_generic_family(font['panose'])
                body_font_family = u"'%s',%s" % (font['font-family'],
                                                 generic_family)
                self.oeb.log(u'Embedding font: %s' % font['font-family'])
            for k in (u'font-weight', u'font-style', u'font-stretch'):
                if font[k] != u'normal':
                    cfont[k] = font[k]
            rule = '@font-face { %s }' % ('; '.join(
                u'%s:%s' % (k, v) for k, v in iteritems(cfont)))
            rule = css_parser.parseString(rule)
            efi.append(rule)

        return body_font_family, efi
Exemple #2
0
    def get_embed_font_info(self, family, failure_critical=True):
        efi = []
        body_font_family = None
        if not family:
            return body_font_family, efi
        from calibre.utils.fonts.scanner import font_scanner, NoFonts
        from calibre.utils.fonts.utils import panose_to_css_generic_family
        try:
            faces = font_scanner.fonts_for_family(family)
        except NoFonts:
            msg = (u'No embeddable fonts found for family: %r'%family)
            if failure_critical:
                raise ValueError(msg)
            self.oeb.log.warn(msg)
            return body_font_family, efi
        if not faces:
            msg = (u'No embeddable fonts found for family: %r'%family)
            if failure_critical:
                raise ValueError(msg)
            self.oeb.log.warn(msg)
            return body_font_family, efi

        for i, font in enumerate(faces):
            ext = 'otf' if font['is_otf'] else 'ttf'
            fid, href = self.oeb.manifest.generate(id=u'font',
                href=u'fonts/%s.%s'%(ascii_filename(font['full_name']).replace(u' ', u'-'), ext))
            item = self.oeb.manifest.add(fid, href,
                    guess_type('dummy.'+ext)[0],
                    data=font_scanner.get_font_data(font))
            item.unload_data_from_memory()

            cfont = {
                    u'font-family':u'"%s"'%font['font-family'],
                    u'panose-1': u' '.join(map(unicode_type, font['panose'])),
                    u'src': u'url(%s)'%item.href,
            }

            if i == 0:
                generic_family = panose_to_css_generic_family(font['panose'])
                body_font_family = u"'%s',%s"%(font['font-family'], generic_family)
                self.oeb.log(u'Embedding font: %s'%font['font-family'])
            for k in (u'font-weight', u'font-style', u'font-stretch'):
                if font[k] != u'normal':
                    cfont[k] = font[k]
            rule = '@font-face { %s }'%('; '.join(u'%s:%s'%(k, v) for k, v in
                iteritems(cfont)))
            rule = css_parser.parseString(rule)
            efi.append(rule)

        return body_font_family, efi
Exemple #3
0
    def __init__(self, elem, embed_relationships, XPath, get):
        self.name = self.family_name = get(elem, 'w:name')
        self.alt_names = tuple(
            get(x, 'w:val') for x in XPath('./w:altName')(elem))
        if self.alt_names and not has_system_fonts(self.name):
            for x in self.alt_names:
                if has_system_fonts(x):
                    self.family_name = x
                    break

        self.embedded = {}
        for x in ('Regular', 'Bold', 'Italic', 'BoldItalic'):
            for y in XPath('./w:embed%s[@r:id]' % x)(elem):
                rid = get(y, 'r:id')
                key = get(y, 'w:fontKey')
                subsetted = get(y, 'w:subsetted') in {'1', 'true', 'on'}
                if rid in embed_relationships:
                    self.embedded[x] = Embed(embed_relationships[rid], key,
                                             subsetted)

        self.generic_family = 'auto'
        for x in XPath('./w:family[@w:val]')(elem):
            self.generic_family = get(x, 'w:val', 'auto')

        ntt = binary_property(elem, 'notTrueType', XPath, get)
        self.is_ttf = ntt is inherit or not ntt

        self.panose1 = None
        self.panose_name = None
        for x in XPath('./w:panose1[@w:val]')(elem):
            try:
                v = get(x, 'w:val')
                v = tuple(int(v[i:i + 2], 16) for i in range(0, len(v), 2))
            except (TypeError, ValueError, IndexError):
                pass
            else:
                self.panose1 = v
                self.panose_name = panose_to_css_generic_family(v)

        self.css_generic_family = {
            'roman': 'serif',
            'swiss': 'sans-serif',
            'modern': 'monospace',
            'decorative': 'fantasy',
            'script': 'cursive'
        }.get(self.generic_family, None)
        self.css_generic_family = self.css_generic_family or self.panose_name or 'serif'
Exemple #4
0
    def find_font_for_text(self,
                           text,
                           allowed_families={'serif', 'sans-serif'},
                           preferred_families=('serif', 'sans-serif',
                                               'monospace', 'cursive',
                                               'fantasy')):
        '''
        Find a font on the system capable of rendering the given text.

        Returns a font family (as given by fonts_for_family()) that has a
        "normal" font and that can render the supplied text. If no such font
        exists, returns None.

        :return: (family name, faces) or None, None
        '''
        from calibre.utils.fonts.utils import (supports_text,
                                               panose_to_css_generic_family,
                                               get_printable_characters)
        if not isinstance(text, unicode_type):
            raise TypeError(u'%r is not unicode' % text)
        text = get_printable_characters(text)
        found = {}

        def filter_faces(font):
            try:
                raw = self.get_font_data(font)
                return supports_text(raw, text)
            except:
                pass
            return False

        for family in self.find_font_families():
            faces = list(filter(filter_faces, self.fonts_for_family(family)))
            if not faces:
                continue
            generic_family = panose_to_css_generic_family(faces[0]['panose'])
            if generic_family in allowed_families or generic_family == preferred_families[
                    0]:
                return (family, faces)
            elif generic_family not in found:
                found[generic_family] = (family, faces)

        for f in preferred_families:
            if f in found:
                return found[f]
        return None, None
Exemple #5
0
    def get_embed_font_info(self, family, failure_critical=True):
        efi = []
        body_font_family = None
        if not family:
            return body_font_family, efi
        from calibre.utils.fonts.scanner import font_scanner
        from calibre.utils.fonts.utils import panose_to_css_generic_family

        faces = font_scanner.fonts_for_family(family)
        if not faces:
            msg = u"No embeddable fonts found for family: %r" % self.opts.embed_font_family
            if failure_critical:
                raise ValueError(msg)
            self.oeb.log.warn(msg)
            return body_font_family, efi

        for i, font in enumerate(faces):
            ext = "otf" if font["is_otf"] else "ttf"
            fid, href = self.oeb.manifest.generate(
                id=u"font", href=u"fonts/%s.%s" % (ascii_filename(font["full_name"]).replace(u" ", u"-"), ext)
            )
            item = self.oeb.manifest.add(
                fid, href, guess_type("dummy." + ext)[0], data=font_scanner.get_font_data(font)
            )
            item.unload_data_from_memory()

            cfont = {
                u"font-family": u'"%s"' % font["font-family"],
                u"panose-1": u" ".join(map(unicode, font["panose"])),
                u"src": u"url(%s)" % item.href,
            }

            if i == 0:
                generic_family = panose_to_css_generic_family(font["panose"])
                body_font_family = u"'%s',%s" % (font["font-family"], generic_family)
                self.oeb.log(u"Embedding font: %s" % font["font-family"])
            for k in (u"font-weight", u"font-style", u"font-stretch"):
                if font[k] != u"normal":
                    cfont[k] = font[k]
            rule = "@font-face { %s }" % ("; ".join(u"%s:%s" % (k, v) for k, v in cfont.iteritems()))
            rule = cssutils.parseString(rule)
            efi.append(rule)

        return body_font_family, efi
Exemple #6
0
    def find_font_for_text(
        self,
        text,
        allowed_families={"serif", "sans-serif"},
        preferred_families=("serif", "sans-serif", "monospace", "cursive", "fantasy"),
    ):
        """
        Find a font on the system capable of rendering the given text.

        Returns a font family (as given by fonts_for_family()) that has a
        "normal" font and that can render the supplied text. If no such font
        exists, returns None.

        :return: (family name, faces) or None, None
        """
        from calibre.utils.fonts.utils import supports_text, panose_to_css_generic_family, get_printable_characters

        if not isinstance(text, unicode):
            raise TypeError("%r is not unicode" % text)
        text = get_printable_characters(text)
        found = {}

        def filter_faces(font):
            try:
                raw = self.get_font_data(font)
                return supports_text(raw, text)
            except:
                pass
            return False

        for family in self.find_font_families():
            faces = filter(filter_faces, self.fonts_for_family(family))
            if not faces:
                continue
            generic_family = panose_to_css_generic_family(faces[0]["panose"])
            if generic_family in allowed_families or generic_family == preferred_families[0]:
                return (family, faces)
            elif generic_family not in found:
                found[generic_family] = (family, faces)

        for f in preferred_families:
            if f in found:
                return found[f]
        return None, None
Exemple #7
0
    def __init__(self, elem, embed_relationships, XPath, get):
        self.name = self.family_name = get(elem, 'w:name')
        self.alt_names = tuple(get(x, 'w:val') for x in XPath('./w:altName')(elem))
        if self.alt_names and not has_system_fonts(self.name):
            for x in self.alt_names:
                if has_system_fonts(x):
                    self.family_name = x
                    break

        self.embedded = {}
        for x in ('Regular', 'Bold', 'Italic', 'BoldItalic'):
            for y in XPath('./w:embed%s[@r:id]' % x)(elem):
                rid = get(y, 'r:id')
                key = get(y, 'w:fontKey')
                subsetted = get(y, 'w:subsetted') in {'1', 'true', 'on'}
                if rid in embed_relationships:
                    self.embedded[x] = Embed(embed_relationships[rid], key, subsetted)

        self.generic_family = 'auto'
        for x in XPath('./w:family[@w:val]')(elem):
            self.generic_family = get(x, 'w:val', 'auto')

        ntt = binary_property(elem, 'notTrueType', XPath, get)
        self.is_ttf = ntt is inherit or not ntt

        self.panose1 = None
        self.panose_name = None
        for x in XPath('./w:panose1[@w:val]')(elem):
            try:
                v = get(x, 'w:val')
                v = tuple(int(v[i:i+2], 16) for i in xrange(0, len(v), 2))
            except (TypeError, ValueError, IndexError):
                pass
            else:
                self.panose1 = v
                self.panose_name = panose_to_css_generic_family(v)

        self.css_generic_family = {'roman':'serif', 'swiss':'sans-serif', 'modern':'monospace',
                                   'decorative':'fantasy', 'script':'cursive'}.get(self.generic_family, None)
        self.css_generic_family = self.css_generic_family or self.panose_name or 'serif'