Example #1
0
 def find_usage_in(self, elem, inherited_style, ff_rules):
     style = elem_style(self.style_rules, elem.get('class', '') or '', inherited_style)
     for child in elem:
         self.find_usage_in(child, style, ff_rules)
     has_font, existing = used_font(style, ff_rules)
     if not has_font:
         return
     if existing is None:
         in_book = used_font(style, self.embedded_fonts)[1]
         if in_book is None:
             # Try to find the font in the system
             added = self.embed_font(style)
             if added is not None:
                 ff_rules.append(added)
                 self.embedded_fonts.append(added)
         else:
             # TODO: Create a page rule from the book rule (cannot use it
             # directly as paths might be different)
             item = in_book['item']
             sheet = self.parser.parseString(in_book['rule'].cssText, validate=False)
             rule = sheet.cssRules[0]
             page_sheet = self.get_page_sheet()
             href = page_sheet.abshref(item.href)
             rule.style.setProperty('src', 'url(%s)' % href)
             ff_rules.append(find_font_face_rules(sheet, self.oeb)[0])
             page_sheet.data.insertRule(rule, len(page_sheet.data.cssRules))
Example #2
0
 def find_usage_in(self, elem, inherited_style, ff_rules):
     style = elem_style(self.style_rules,
                        elem.get('class', '') or '', inherited_style)
     for child in elem:
         self.find_usage_in(child, style, ff_rules)
     has_font, existing = used_font(style, ff_rules)
     if not has_font:
         return
     if existing is None:
         in_book = used_font(style, self.embedded_fonts)[1]
         if in_book is None:
             # Try to find the font in the system
             added = self.embed_font(style)
             if added is not None:
                 ff_rules.append(added)
                 self.embedded_fonts.append(added)
         else:
             # TODO: Create a page rule from the book rule (cannot use it
             # directly as paths might be different)
             item = in_book['item']
             sheet = self.parser.parseString(in_book['rule'].cssText,
                                             validate=False)
             rule = sheet.cssRules[0]
             page_sheet = self.get_page_sheet()
             href = page_sheet.abshref(item.href)
             rule.style.setProperty('src', 'url(%s)' % href)
             ff_rules.append(find_font_face_rules(sheet, self.oeb)[0])
             page_sheet.data.insertRule(rule, len(page_sheet.data.cssRules))
Example #3
0
    def serialize(self, text_styles, fonts, embed_relationships,
                  font_data_map):
        makeelement = self.namespace.makeelement
        font_families, seen = set(), set()
        for ts in text_styles:
            if ts.font_family:
                lf = ts.font_family.lower()
                if lf not in seen:
                    seen.add(lf)
                    font_families.add(ts.font_family)
        family_map = {}
        for family in sorted(font_families):
            family_map[family] = makeelement(fonts, 'w:font', w_name=family)

        embedded_fonts = []
        for item in self.oeb.manifest:
            if item.media_type in OEB_STYLES and hasattr(
                    item.data, 'cssRules'):
                embedded_fonts.extend(find_font_face_rules(item, self.oeb))

        num = 0
        face_map = defaultdict(set)
        rel_map = {}
        for ef in embedded_fonts:
            ff = ef['font-family'][0]
            if ff not in font_families:
                continue
            num += 1
            bold = ef['weight'] > 400
            italic = ef['font-style'] != 'normal'
            tag = 'Regular'
            if bold or italic:
                tag = 'Italic'
                if bold and italic:
                    tag = 'BoldItalic'
                elif bold:
                    tag = 'Bold'
            if tag in face_map[ff]:
                continue
            face_map[ff].add(tag)
            font = family_map[ff]
            key = uuid4()
            item = ef['item']
            rid = rel_map.get(item)
            if rid is None:
                rel_map[item] = rid = 'rId%d' % num
                fname = 'fonts/font%d.odttf' % num
                makeelement(embed_relationships,
                            'Relationship',
                            Id=rid,
                            Type=self.namespace.names['EMBEDDED_FONT'],
                            Target=fname)
                font_data_map['word/' + fname] = obfuscate_font_data(
                    item.data, key)
            makeelement(font,
                        'w:embed' + tag,
                        r_id=rid,
                        w_fontKey='{%s}' % key.urn.rpartition(':')[-1].upper(),
                        w_subsetted="true"
                        if self.opts.subset_embedded_fonts else "false")
Example #4
0
 def find_embedded_fonts(self):
     '''
     Find all @font-face rules and extract the relevant info from them.
     '''
     self.embedded_fonts = []
     for item in self.oeb.manifest:
         if not hasattr(item.data, 'cssRules'):
             continue
         self.embedded_fonts.extend(find_font_face_rules(item, self.oeb))
Example #5
0
 def find_embedded_fonts(self):
     '''
     Find all @font-face rules and extract the relevant info from them.
     '''
     self.embedded_fonts = []
     for item in self.oeb.manifest:
         if not hasattr(item.data, 'cssRules'):
             continue
         self.embedded_fonts.extend(find_font_face_rules(item, self.oeb))
Example #6
0
 def embed_font(self, style):
     ff = [
         unicode(f) for f in style.get('font-family', [])
         if unicode(f).lower() not in {
             'serif', 'sansserif', 'sans-serif', 'fantasy', 'cursive',
             'monospace'
         }
     ]
     if not ff:
         return
     ff = ff[0]
     if ff in self.warned or ff == 'inherit':
         return
     try:
         fonts = font_scanner.fonts_for_family(ff)
     except NoFonts:
         self.log.warn('Failed to find fonts for family:', ff,
                       'not embedding')
         self.warned.add(ff)
         return
     try:
         weight = int(style.get('font-weight', '400'))
     except (ValueError, TypeError, AttributeError):
         w = style['font-weight']
         if w not in self.warned2:
             self.log.warn('Invalid weight in font style: %r' % w)
             self.warned2.add(w)
         return
     for f in fonts:
         if f['weight'] == weight and f['font-style'] == style.get(
                 'font-style', 'normal') and f['font-stretch'] == style.get(
                     'font-stretch', 'normal'):
             self.log('Embedding font %s from %s' %
                      (f['full_name'], f['path']))
             data = font_scanner.get_font_data(f)
             name = f['full_name']
             ext = 'otf' if f['is_otf'] else 'ttf'
             name = ascii_filename(name).replace(' ', '-').replace(
                 '(', '').replace(')', '')
             fid, href = self.oeb.manifest.generate(id=u'font',
                                                    href=u'fonts/%s.%s' %
                                                    (name, ext))
             item = self.oeb.manifest.add(fid,
                                          href,
                                          guess_type('dummy.' + ext)[0],
                                          data=data)
             item.unload_data_from_memory()
             page_sheet = self.get_page_sheet()
             href = page_sheet.relhref(item.href)
             css = '''@font-face { font-family: "%s"; font-weight: %s; font-style: %s; font-stretch: %s; src: url(%s) }''' % (
                 f['font-family'], f['font-weight'], f['font-style'],
                 f['font-stretch'], href)
             sheet = self.parser.parseString(css, validate=False)
             page_sheet.data.insertRule(sheet.cssRules[0],
                                        len(page_sheet.data.cssRules))
             return find_font_face_rules(sheet, self.oeb)[0]
Example #7
0
    def process_item(self, item, sheets):
        ff_rules = []
        self.current_item = item
        self.page_sheet = None
        for sheet in sheets:
            if 'page_css' in sheet.id:
                ff_rules.extend(find_font_face_rules(sheet, self.oeb))
                self.page_sheet = sheet

        base = {'font-family':['serif'], 'font-weight': '400',
                'font-style':'normal', 'font-stretch':'normal'}

        for body in item.data.xpath('//*[local-name()="body"]'):
            self.find_usage_in(body, base, ff_rules)
Example #8
0
    def process_item(self, item, sheets):
        ff_rules = []
        self.current_item = item
        self.page_sheet = None
        for sheet in sheets:
            if 'page_css' in sheet.id:
                ff_rules.extend(find_font_face_rules(sheet, self.oeb))
                self.page_sheet = sheet

        base = {'font-family':['serif'], 'font-weight': '400',
                'font-style':'normal', 'font-stretch':'normal'}

        for body in item.data.xpath('//*[local-name()="body"]'):
            self.find_usage_in(body, base, ff_rules)
Example #9
0
    def serialize(self, text_styles, fonts, embed_relationships, font_data_map):
        makeelement = self.namespace.makeelement
        font_families, seen = set(), set()
        for ts in text_styles:
            if ts.font_family:
                lf = ts.font_family.lower()
                if lf not in seen:
                    seen.add(lf)
                    font_families.add(ts.font_family)
        family_map = {}
        for family in sorted(font_families):
            family_map[family] = makeelement(fonts, 'w:font', w_name=family)

        embedded_fonts = []
        for item in self.oeb.manifest:
            if item.media_type in OEB_STYLES and hasattr(item.data, 'cssRules'):
                embedded_fonts.extend(find_font_face_rules(item, self.oeb))

        num = 0
        face_map = defaultdict(set)
        rel_map = {}
        for ef in embedded_fonts:
            ff = ef['font-family'][0]
            if ff not in font_families:
                continue
            num += 1
            bold = ef['weight'] > 400
            italic = ef['font-style'] != 'normal'
            tag = 'Regular'
            if bold or italic:
                tag = 'Italic'
                if bold and italic:
                    tag = 'BoldItalic'
                elif bold:
                    tag = 'Bold'
            if tag in face_map[ff]:
                continue
            face_map[ff].add(tag)
            font = family_map[ff]
            key = uuid4()
            item = ef['item']
            rid = rel_map.get(item)
            if rid is None:
                rel_map[item] = rid = 'rId%d' % num
                fname = 'fonts/font%d.odttf' % num
                makeelement(embed_relationships, 'Relationship', Id=rid, Type=self.namespace.names['EMBEDDED_FONT'], Target=fname)
                font_data_map['word/' + fname] = obfuscate_font_data(item.data, key)
            makeelement(font, 'w:embed' + tag, r_id=rid,
                        w_fontKey='{%s}' % key.urn.rpartition(':')[-1].upper(),
                        w_subsetted="true" if self.opts.subset_embedded_fonts else "false")
Example #10
0
 def do_embed(f):
     data = font_scanner.get_font_data(f)
     name = f['full_name']
     ext = 'otf' if f['is_otf'] else 'ttf'
     name = ascii_filename(name).replace(' ', '-').replace('(', '').replace(')', '')
     fid, href = self.oeb.manifest.generate(id=u'font', href=u'fonts/%s.%s'%(name, ext))
     item = self.oeb.manifest.add(fid, href, guess_type('dummy.'+ext)[0], data=data)
     item.unload_data_from_memory()
     page_sheet = self.get_page_sheet()
     href = page_sheet.relhref(item.href)
     css = '''@font-face { font-family: "%s"; font-weight: %s; font-style: %s; font-stretch: %s; src: url(%s) }''' % (
         f['font-family'], f['font-weight'], f['font-style'], f['font-stretch'], href)
     sheet = self.parser.parseString(css, validate=False)
     page_sheet.data.insertRule(sheet.cssRules[0], len(page_sheet.data.cssRules))
     return find_font_face_rules(sheet, self.oeb)[0]
Example #11
0
 def do_embed(f):
     data = font_scanner.get_font_data(f)
     name = f['full_name']
     ext = 'otf' if f['is_otf'] else 'ttf'
     name = ascii_filename(name).replace(' ', '-').replace('(', '').replace(')', '')
     fid, href = self.oeb.manifest.generate(id=u'font', href=u'fonts/%s.%s'%(name, ext))
     item = self.oeb.manifest.add(fid, href, guess_type('dummy.'+ext)[0], data=data)
     item.unload_data_from_memory()
     page_sheet = self.get_page_sheet()
     href = page_sheet.relhref(item.href)
     css = '''@font-face { font-family: "%s"; font-weight: %s; font-style: %s; font-stretch: %s; src: url(%s) }''' % (
         f['font-family'], f['font-weight'], f['font-style'], f['font-stretch'], href)
     sheet = self.parser.parseString(css, validate=False)
     page_sheet.data.insertRule(sheet.cssRules[0], len(page_sheet.data.cssRules))
     return find_font_face_rules(sheet, self.oeb)[0]
Example #12
0
 def embed_font(self, style):
     ff = [unicode(f) for f in style.get('font-family', []) if unicode(f).lower() not in {
         'serif', 'sansserif', 'sans-serif', 'fantasy', 'cursive', 'monospace'}]
     if not ff:
         return
     ff = ff[0]
     if ff in self.warned or ff == 'inherit':
         return
     try:
         fonts = font_scanner.fonts_for_family(ff)
     except NoFonts:
         self.log.warn('Failed to find fonts for family:', ff, 'not embedding')
         self.warned.add(ff)
         return
     try:
         weight = int(style.get('font-weight', '400'))
     except (ValueError, TypeError, AttributeError):
         w = style['font-weight']
         if w not in self.warned2:
             self.log.warn('Invalid weight in font style: %r' % w)
             self.warned2.add(w)
         return
     for f in fonts:
         if f['weight'] == weight and f['font-style'] == style.get('font-style', 'normal') and f['font-stretch'] == style.get('font-stretch', 'normal'):
             self.log('Embedding font %s from %s' % (f['full_name'], f['path']))
             data = font_scanner.get_font_data(f)
             name = f['full_name']
             ext = 'otf' if f['is_otf'] else 'ttf'
             name = ascii_filename(name).replace(' ', '-').replace('(', '').replace(')', '')
             fid, href = self.oeb.manifest.generate(id=u'font', href=u'fonts/%s.%s'%(name, ext))
             item = self.oeb.manifest.add(fid, href, guess_type('dummy.'+ext)[0], data=data)
             item.unload_data_from_memory()
             page_sheet = self.get_page_sheet()
             href = page_sheet.relhref(item.href)
             css = '''@font-face { font-family: "%s"; font-weight: %s; font-style: %s; font-stretch: %s; src: url(%s) }''' % (
                 f['font-family'], f['font-weight'], f['font-style'], f['font-stretch'], href)
             sheet = self.parser.parseString(css, validate=False)
             page_sheet.data.insertRule(sheet.cssRules[0], len(page_sheet.data.cssRules))
             return find_font_face_rules(sheet, self.oeb)[0]