def drawTextItem(self, point, text_item): # return super(PdfEngine, self).drawTextItem(point, text_item) self.apply_graphics_state() gi = GlyphInfo(*self.qt_hack.get_glyphs(point, text_item)) if not gi.indices: return metrics = self.fonts.get(gi.name) if metrics is None: from calibre.utils.fonts.utils import get_all_font_names try: names = get_all_font_names(gi.name, True) names = ' '.join('%s=%s'%(k, names[k]) for k in sorted(names)) except Exception: names = 'Unknown' self.debug('Loading font: %s' % names) try: self.fonts[gi.name] = metrics = self.create_sfnt(text_item) except UnsupportedFont: return super(PdfEngine, self).drawTextItem(point, text_item) for glyph_id in gi.indices: try: metrics.glyph_map[glyph_id] = metrics.full_glyph_map[glyph_id] except (KeyError, ValueError): pass glyphs = [] last_x = last_y = 0 for glyph_index, (x, y) in zip(gi.indices, gi.positions): glyphs.append((x-last_x, last_y - y, glyph_index)) last_x, last_y = x, y self.pdf.draw_glyph_run([gi.stretch, 0, 0, -1, 0, 0], gi.size, metrics, glyphs)
def drawTextItem(self, point, text_item): self.content_written_to_current_page = 'drawTextItem' # return super(PdfEngine, self).drawTextItem(point, text_item) self.apply_graphics_state() gi = GlyphInfo(*self.qt_hack.get_glyphs(point, text_item)) if not gi.indices: return metrics = self.fonts.get(gi.name) if metrics is None: from calibre.utils.fonts.utils import get_all_font_names try: names = get_all_font_names(gi.name, True) names = ' '.join('%s=%s'%(k, names[k]) for k in sorted(names)) except Exception: names = 'Unknown' self.debug('Loading font: %s' % names) try: self.fonts[gi.name] = metrics = self.create_sfnt(text_item) except UnsupportedFont: return super(PdfEngine, self).drawTextItem(point, text_item) for glyph_id in gi.indices: try: metrics.glyph_map[glyph_id] = metrics.full_glyph_map[glyph_id] except (KeyError, ValueError): pass glyphs = [] last_x = last_y = 0 for glyph_index, (x, y) in zip(gi.indices, gi.positions): glyphs.append((x-last_x, last_y - y, glyph_index)) last_x, last_y = x, y self.pdf.draw_glyph_run([gi.stretch, 0, 0, -1, 0, 0], gi.size, metrics, glyphs)
def __init__(self, sfnt): for table in (b'head', b'hhea', b'hmtx', b'cmap', b'OS/2', b'post', b'name'): if table not in sfnt: raise UnsupportedFont('This font has no %s table'%table) self.sfnt = sfnt self.head = self.sfnt[b'head'] hhea = self.sfnt[b'hhea'] hhea.read_data(self.sfnt[b'hmtx']) self.ascent = hhea.ascender self.descent = hhea.descender self.bbox = (self.head.x_min, self.head.y_min, self.head.x_max, self.head.y_max) self._advance_widths = hhea.advance_widths self.cmap = self.sfnt[b'cmap'] self.units_per_em = self.head.units_per_em self.os2 = self.sfnt[b'OS/2'] self.os2.read_data() self.post = self.sfnt[b'post'] self.post.read_data() self.names = get_all_font_names(self.sfnt[b'name'].raw, raw_is_table=True) self.is_otf = 'CFF ' in self.sfnt.tables self._sig = hash(self.sfnt[b'name'].raw) # Metrics for embedding in PDF pdf_scale = self.pdf_scale = lambda x:int(round(x*1000./self.units_per_em)) self.pdf_ascent, self.pdf_descent = map(pdf_scale, (self.os2.typo_ascender, self.os2.typo_descender)) self.pdf_bbox = tuple(map(pdf_scale, self.bbox)) self.pdf_capheight = pdf_scale(getattr(self.os2, 'cap_height', self.os2.typo_ascender)) self.pdf_avg_width = pdf_scale(self.os2.average_char_width) self.pdf_stemv = 50 + int((self.os2.weight_class / 65.0) ** 2)
def __init__(self, sfnt): self.sfnt = sfnt self.head = self.sfnt[b"head"] hhea = self.sfnt[b"hhea"] hhea.read_data(self.sfnt[b"hmtx"]) self.ascent = hhea.ascender self.descent = hhea.descender self.bbox = (self.head.x_min, self.head.y_min, self.head.x_max, self.head.y_max) self._advance_widths = hhea.advance_widths self.cmap = self.sfnt[b"cmap"] self.units_per_em = self.head.units_per_em self.os2 = self.sfnt[b"OS/2"] self.os2.read_data() self.post = self.sfnt[b"post"] self.post.read_data() self.names = get_all_font_names(self.sfnt[b"name"].raw, raw_is_table=True) self.is_otf = "CFF " in self.sfnt.tables self._sig = hash(self.sfnt[b"name"].raw) # Metrics for embedding in PDF pdf_scale = self.pdf_scale = lambda x: int(round(x * 1000.0 / self.units_per_em)) self.pdf_ascent, self.pdf_descent = map(pdf_scale, (self.os2.typo_ascender, self.os2.typo_descender)) self.pdf_bbox = tuple(map(pdf_scale, self.bbox)) self.pdf_capheight = pdf_scale(getattr(self.os2, "cap_height", self.os2.typo_ascender)) self.pdf_avg_width = pdf_scale(self.os2.average_char_width) self.pdf_stemv = 50 + int((self.os2.weight_class / 65.0) ** 2)
def drawTextItem(self, point, text_item): # return super(PdfEngine, self).drawTextItem(point, text_item) self.apply_graphics_state() gi = GlyphInfo(*self.qt_hack.get_glyphs(point, text_item)) if not gi.indices: return metrics = self.fonts.get(gi.name) if metrics is None: from calibre.utils.fonts.utils import get_all_font_names try: names = get_all_font_names(gi.name, True) names = ' '.join('%s=%s' % (k, names[k]) for k in sorted(names)) except Exception: names = 'Unknown' self.debug('Loading font: %s' % names) try: self.fonts[gi.name] = metrics = self.create_sfnt(text_item) except UnsupportedFont: self.debug( 'Failed to load font: %s, drawing text as outlines...' % names) return super(PdfEngine, self).drawTextItem(point, text_item) indices, positions = [], [] ignore_glyphs = metrics.ignore_glyphs for glyph_id, gpos in zip(gi.indices, gi.positions): if glyph_id not in ignore_glyphs: indices.append(glyph_id), positions.append(gpos) for glyph_id in indices: try: metrics.glyph_map[glyph_id] = metrics.full_glyph_map[glyph_id] except (KeyError, ValueError): pass glyphs = [] last_x = last_y = 0 for glyph_index, (x, y) in zip(indices, positions): glyphs.append((x - last_x, last_y - y, glyph_index)) last_x, last_y = x, y if not self.content_written_to_current_page: dy = self.graphics.current_state.transform.dy() ypositions = [y + dy for x, y in positions] miny = min(ypositions or (0, )) maxy = max(ypositions or (self.pixel_height, )) page_top = self.header_height if self.has_headers else 0 page_bottom = self.pixel_height - (self.footer_height if self.has_footers else 0) if page_top <= miny <= page_bottom or page_top <= maxy <= page_bottom: self.content_written_to_current_page = 'drawTextItem' else: self.debug( 'Text in header/footer: miny=%s maxy=%s page_top=%s page_bottom=%s' % (miny, maxy, page_top, page_bottom)) self.pdf.draw_glyph_run([gi.stretch, 0, 0, -1, 0, 0], gi.size, metrics, glyphs)
def check_fonts(container): font_map = {} errors = [] for name, mt in container.mime_map.iteritems(): if mt in OEB_FONTS: raw = container.raw_data(name) try: name_map = get_all_font_names(raw) except Exception as e: errors.append(InvalidFont(_('Not a valid font: %s') % e, name)) continue font_map[name] = name_map.get('family_name', None) or name_map.get( 'preferred_family_name', None) or name_map.get( 'wws_family_name', None) try: embeddable, fs_type = is_font_embeddable(raw) except UnsupportedFont: embeddable = True if not embeddable: errors.append(NotEmbeddable(name, fs_type)) sheets = [] for name, mt in container.mime_map.iteritems(): if mt in OEB_STYLES: try: sheets.append((name, container.parsed(name), None)) except Exception: pass # Could not parse, ignore elif mt in OEB_DOCS: for style in container.parsed(name).xpath( '//*[local-name()="style"]'): if style.get('type', 'text/css') == 'text/css' and style.text: sheets.append((name, container.parse_css(style.text), style.sourceline)) for name, sheet, line_offset in sheets: for rule in sheet.cssRules.rulesOfType(CSSRule.FONT_FACE_RULE): src = rule.style.getPropertyCSSValue('src') if src is not None and src.length > 0: href = getattr(src.item(0), 'uri', None) if href is not None: fname = container.href_to_name(href, name) font_name = font_map.get(fname, None) if font_name is None: continue families = parse_font_family( rule.style.getPropertyValue('font-family')) if families: if families[0] != font_name: errors.append( FontAliasing(font_name, families[0], name, line_offset)) return errors
def check_fonts(container): font_map = {} errors = [] for name, mt in container.mime_map.iteritems(): if mt in OEB_FONTS: raw = container.raw_data(name) if mt == guess_type('a.woff'): try: raw = woff.from_woff(raw) except Exception as e: errors.append( InvalidFont(_('Not a valid WOFF font: %s') % e, name)) continue try: name_map = get_all_font_names(raw) except Exception as e: errors.append(InvalidFont(_('Not a valid font: %s') % e, name)) continue font_map[name] = name_map.get('family_name', None) or name_map.get( 'preferred_family_name', None) or name_map.get( 'wws_family_name', None) sheets = [] for name, mt in container.mime_map.iteritems(): if mt in OEB_STYLES: sheets.append((name, container.parsed(name), None)) elif mt in OEB_DOCS: for style in container.parsed(name).xpath( '//*[local-name()="style"]'): if style.get('type', 'text/css') == 'text/css': sheets.append((name, container.parse_css(style.text), style.sourceline)) for name, sheet, line_offset in sheets: for rule in sheet.cssRules.rulesOfType(CSSRule.FONT_FACE_RULE): src = rule.style.getPropertyCSSValue('src') if src is not None and src.length > 0: href = getattr(src.item(0), 'uri', None) if href is not None: fname = container.href_to_name(href, name) font_name = font_map.get(fname, None) if font_name is None: continue ff = rule.style.getPropertyCSSValue('font-family') if ff is not None and ff.length > 0: ff = getattr(ff.item(0), 'value', None) if ff is not None and ff != font_name: errors.append( FontAliasing(font_name, ff, name, line_offset)) return errors
def drawTextItem(self, point, text_item): # return super(PdfEngine, self).drawTextItem(point, text_item) self.apply_graphics_state() gi = GlyphInfo(*self.qt_hack.get_glyphs(point, text_item)) if not gi.indices: return metrics = self.fonts.get(gi.name) if metrics is None: from calibre.utils.fonts.utils import get_all_font_names try: names = get_all_font_names(gi.name, True) names = ' '.join('%s=%s'%(k, names[k]) for k in sorted(names)) except Exception: names = 'Unknown' self.debug('Loading font: %s' % names) try: self.fonts[gi.name] = metrics = self.create_sfnt(text_item) except UnsupportedFont: self.debug('Failed to load font: %s, drawing text as outlines...' % names) return super(PdfEngine, self).drawTextItem(point, text_item) indices, positions = [], [] ignore_glyphs = metrics.ignore_glyphs for glyph_id, gpos in zip(gi.indices, gi.positions): if glyph_id not in ignore_glyphs: indices.append(glyph_id), positions.append(gpos) for glyph_id in indices: try: metrics.glyph_map[glyph_id] = metrics.full_glyph_map[glyph_id] except (KeyError, ValueError): pass glyphs = [] last_x = last_y = 0 for glyph_index, (x, y) in zip(indices, positions): glyphs.append((x-last_x, last_y - y, glyph_index)) last_x, last_y = x, y if not self.content_written_to_current_page: dy = self.graphics.current_state.transform.dy() ypositions = [y + dy for x, y in positions] miny = min(ypositions or (0,)) maxy = max(ypositions or (self.pixel_height,)) page_top = self.header_height if self.has_headers else 0 page_bottom = self.pixel_height - (self.footer_height if self.has_footers else 0) if page_top <= miny <= page_bottom or page_top <= maxy <= page_bottom: self.content_written_to_current_page = 'drawTextItem' else: self.debug('Text in header/footer: miny=%s maxy=%s page_top=%s page_bottom=%s'% ( miny, maxy, page_top, page_bottom)) self.pdf.draw_glyph_run([gi.stretch, 0, 0, -1, 0, 0], gi.size, metrics, glyphs)
def check_fonts(container): font_map = {} errors = [] for name, mt in container.mime_map.iteritems(): if mt in OEB_FONTS: raw = container.raw_data(name) if mt == guess_type('a.woff'): try: raw = woff.from_woff(raw) except Exception as e: errors.append(InvalidFont(_('Not a valid WOFF font: %s') % e, name)) continue try: name_map = get_all_font_names(raw) except Exception as e: errors.append(InvalidFont(_('Not a valid font: %s') % e, name)) continue font_map[name] = name_map.get('family_name', None) or name_map.get('preferred_family_name', None) or name_map.get('wws_family_name', None) sheets = [] for name, mt in container.mime_map.iteritems(): if mt in OEB_STYLES: try: sheets.append((name, container.parsed(name), None)) except Exception: pass # Could not parse, ignore elif mt in OEB_DOCS: for style in container.parsed(name).xpath('//*[local-name()="style"]'): if style.get('type', 'text/css') == 'text/css' and style.text: sheets.append((name, container.parse_css(style.text), style.sourceline)) for name, sheet, line_offset in sheets: for rule in sheet.cssRules.rulesOfType(CSSRule.FONT_FACE_RULE): src = rule.style.getPropertyCSSValue('src') if src is not None and src.length > 0: href = getattr(src.item(0), 'uri', None) if href is not None: fname = container.href_to_name(href, name) font_name = font_map.get(fname, None) if font_name is None: continue ff = rule.style.getPropertyCSSValue('font-family') if ff is not None and ff.length > 0: ff = getattr(ff.item(0), 'value', None) if ff is not None and ff != font_name: errors.append(FontAliasing(font_name, ff, name, line_offset)) return errors
def check_fonts(container): font_map = {} errors = [] for name, mt in iteritems(container.mime_map): if mt in OEB_FONTS: raw = container.raw_data(name) try: name_map = get_all_font_names(raw) except Exception as e: errors.append(InvalidFont(_('Not a valid font: %s') % e, name)) continue font_map[name] = name_map.get('family_name', None) or name_map.get('preferred_family_name', None) or name_map.get('wws_family_name', None) try: embeddable, fs_type = is_font_embeddable(raw) except UnsupportedFont: embeddable = True if not embeddable: errors.append(NotEmbeddable(name, fs_type)) sheets = [] for name, mt in iteritems(container.mime_map): if mt in OEB_STYLES: try: sheets.append((name, container.parsed(name), None)) except Exception: pass # Could not parse, ignore elif mt in OEB_DOCS: for style in container.parsed(name).xpath('//*[local-name()="style"]'): if style.get('type', 'text/css') == 'text/css' and style.text: sheets.append((name, container.parse_css(style.text), style.sourceline)) for name, sheet, line_offset in sheets: for rule in sheet.cssRules.rulesOfType(CSSRule.FONT_FACE_RULE): src = rule.style.getPropertyCSSValue('src') if src is not None and src.length > 0: href = getattr(src.item(0), 'uri', None) if href is not None: fname = container.href_to_name(href, name) font_name = font_map.get(fname, None) if font_name is None: continue families = parse_font_family(rule.style.getPropertyValue('font-family')) if families: if families[0] != font_name: errors.append(FontAliasing(font_name, families[0], name, line_offset)) return errors