def embedded_font_demo(): my_canvas = canvas.Canvas("embed_font.pdf", pagesize=letter) reportlab_folder = os.path.dirname(reportlab.__file__) fonts_folder = os.path.join(reportlab_folder, 'fonts') print('ReportLab font folder is located at {}'.format( fonts_folder)) afm = os.path.join(fonts_folder, 'DarkGardenMK.afm') pfb = os.path.join(fonts_folder, 'DarkGardenMK.pfb') # Register the font so we can use it font_face = pdfmetrics.EmbeddedType1Face(afm, pfb) pdfmetrics.registerTypeFace(font_face) face_name = 'DarkGardenMK' font = pdfmetrics.Font('DarkGardenMK', face_name, 'WinAnsiEncoding') pdfmetrics.registerFont(font) # Use the font! my_canvas.setFont('DarkGardenMK', 40) my_canvas.drawString(10, 730, 'The DarkGardenMK font') my_canvas.save()
def __init__(self, path, margin_x=48, margin_y=60, file_name='Untitled.pdf', file_name_S3='Untitled.pdf', is_landscape=False, author=None, title=None): self.path = path self.margin_x = self.origin_x = margin_x self.margin_y = self.origin_y = margin_y self.file_name = file_name self.is_landscape = is_landscape self.author = author self.title = title # embeds "Hand of Sean" font: afmFile = os.path.join(settings.FONT_ROOT, 'HandOfSean.afm') pfbFile = os.path.join(settings.FONT_ROOT, 'HandOfSean.pfb') ttfFile = os.path.join(settings.FONT_ROOT, 'handsean.ttf') justFace = pdfmetrics.EmbeddedType1Face(afmFile, pfbFile) #embeds font faceName = 'HandOfSean' # pulled from AFM file pdfmetrics.registerTypeFace(justFace) justFont = pdfmetrics.Font('HandSean', faceName, 'WinAnsiEncoding') pdfmetrics.registerFont(justFont) pdfmetrics.registerFont(TTFont('HandSean', ttfFile)) response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename=' + self.file_name self.set_orientation(self.is_landscape) self.canvas = canvas.Canvas(self.path + '/' + self.file_name, pagesize=(self.page_width, self.page_height)) if self.author is not None: self.canvas.setAuthor(self.author) if self.title is not None: self.canvas.setTitle(self.title)
def set_cyr_font(): # fname - the font file name without extension fname = 'a010013l' # faceName - view a010013l.AFM file as a plain text and look at # row beginning with 'FontName' word (it's usually the fourth row). # The word after 'FontName' is the faceName ('URWGothicL-Book' in this case). faceName = 'URWGothicL-Book' # Define new Type 1 font cyrFace = pdfmetrics.EmbeddedType1Face(fname + '.afm', fname + '.pfb') # Create a new encoding called 'CP1251' cyrenc = pdfmetrics.Encoding('CP1251') # Fill in the tuple with Unicode glyphs in accordance with cp1251 (win1251) # encoding cp1251 = ( 'afii10051', 'afii10052', 'quotesinglbase', 'afii10100', 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'Euro', 'perthousand', 'afii10058', 'guilsinglleft', 'afii10059', 'afii10061', 'afii10060', 'afii10145', 'afii10099', 'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark', 'afii10106', 'guilsinglright', 'afii10107', 'afii10109', 'afii10108', 'afii10193', 'space', 'afii10062', 'afii10110', 'afii10057', 'currency', 'afii10050', 'brokenbar', 'section', 'afii10023', 'copyright', 'afii10053', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', 'afii10056', 'degree', 'plusminus', 'afii10055', 'afii10103', 'afii10098', 'mu1', 'paragraph', 'periodcentered', 'afii10071', 'afii61352', 'afii10101', 'guillemotright', 'afii10105', 'afii10054', 'afii10102', 'afii10104', 'afii10017', 'afii10018', 'afii10019', 'afii10020', 'afii10021', 'afii10022', 'afii10024', 'afii10025', 'afii10026', 'afii10027', 'afii10028', 'afii10029', 'afii10030', 'afii10031', 'afii10032', 'afii10033', 'afii10034', 'afii10035', 'afii10036', 'afii10037', 'afii10038', 'afii10039', 'afii10040', 'afii10041', 'afii10042', 'afii10043', 'afii10044', 'afii10045', 'afii10046', 'afii10047', 'afii10048', 'afii10049', 'afii10065', 'afii10066', 'afii10067', 'afii10068', 'afii10069', 'afii10070', 'afii10072', 'afii10073', 'afii10074', 'afii10075', 'afii10076', 'afii10077', 'afii10078', 'afii10079', 'afii10080', 'afii10081', 'afii10082', 'afii10083', 'afii10084', 'afii10085', 'afii10086', 'afii10087', 'afii10088', 'afii10089', 'afii10090', 'afii10091', 'afii10092', 'afii10093', 'afii10094', 'afii10095', 'afii10096', 'afii10097' ) # Replace glyphs from code 128 to code 256 with cp1251 values for i in range(128, 256): cyrenc[i] = cp1251[i - 128] # Register newly created encoding pdfmetrics.registerEncoding(cyrenc) # Register type face pdfmetrics.registerTypeFace(cyrFace) # Register the font with adding '1251' to its name pdfmetrics.registerFont(pdfmetrics.Font(faceName + '1251', faceName, 'CP1251')) return faceName + '1251' # def set_cyr_font
def font_start(self, name, ttf=None, afm=None, pfb=None): # True Type Fonts if ttf: font_path = os.path.join(self.font_dir, ttf) pdfmetrics.registerFont(TTFont(name, font_path)) return # Type 1 face = pdfmetrics.EmbeddedType1Face(afm, pfb) pdfmetrics.registerTypeFace(face) font = pdfmetrics.Font(name, name, 'WinAnsiEncoding') pdfmetrics.registerFont(font)
def register_type1_font(): """This function is a maintenence function that registers new Type 1 font for PDF use This only need be run on new installations and when installing new fonts. Does not need to be run every time a program starts up. This modifies the ReportLab installation.""" # Define the location of the font to be registered folder = os.path.dirname(reportlab.__file__) + os.sep + "fonts" afmFile = os.path.join(folder, "DarkGardenMK.afm") pfbFile = os.path.join(folder, "DarkGardenMK.pfb") justFace = pdfmetrics.EmbeddedType1Face(afmFile, pfbFile) faceName = "DarkGardenMK" pdfmetrics.registerTypeFace(justFace) justFont = pdfmetrics.Font("DarkGardenMK", faceName, "WinAnsiEncoding") pdfmetrics.registerFont(justFont)
def import_pdf_font(self, base_name, face_name): if self.fonts.get(face_name, None) is None: afm = find(base_name + '.afm') pfb = find(base_name + '.pfb') try: face = pdfmetrics.EmbeddedType1Face(afm, pfb) pdfmetrics.registerTypeFace(face) font = pdfmetrics.Font(face_name, face_name, 'WinAnsiEncoding') pdfmetrics.registerFont(font) except: pass else: self.fonts[face_name] = True
def registerFont0(sourceFile, name, path): "Register Type-1 font for future use, simple version." rl_config.warnOnMissingFontGlyphs = 0 p = os.path.join(os.path.dirname(sourceFile), path) afmFiles = glob.glob(p + '.[aA][fF][mM]') pfbFiles = glob.glob(p + '.[pP][fF][bB]') assert len(afmFiles) == len(pfbFiles) == 1, FontFilesNotFoundError T1face = pdfmetrics.EmbeddedType1Face(afmFiles[0], pfbFiles[0]) T1faceName = name pdfmetrics.registerTypeFace(T1face) T1font = pdfmetrics.Font(name, T1faceName, 'WinAnsiEncoding') pdfmetrics.registerFont(T1font)
def installfont(fontname): """Registers a typeface and font based on the given name.""" fontdir_afm = Path(CONFIG['fonts']['fontdir_afm']) fontdir_pfb = Path(CONFIG['fonts']['fontdir_pfb']) fontfile_stem = fontname afm = (fontdir_afm / fontfile_stem).with_suffix('.afm') pfb = (fontdir_pfb / fontfile_stem).with_suffix('.pfb') try: pdfmetrics.registerTypeFace(pdfmetrics.EmbeddedType1Face(afm, pfb)) pdfmetrics.registerFont( pdfmetrics.Font(fontname, fontname, 'WinAnsiEncoding')) except AssertionError: raise FontFileNotFound(f'Cannot install font {fontname}. ' 'Does its .afm and .pfb files exist?')
def register_fonts(): # Font name : file name # File name should be the same as internal font name fonts = { 'HugoHandwriting': 'Hugohandwriting-Regular' } font_dir = Path.cwd() / 'tests' / 'data' / 'fonts' for font_name, font_file in fonts.items(): font_path_afm = font_dir / (font_file + '.afm') font_path_pfb = font_dir / (font_file + '.pfb') face = pdfmetrics.EmbeddedType1Face(font_path_afm, font_path_pfb) pdfmetrics.registerTypeFace(face) font = pdfmetrics.Font(font_name, font_file, 'WinAnsiEncoding') pdfmetrics.registerFont(font)
def cyrillic(c, n): fname = 'font' faceName = 'TimesNewRomanPSMT' cyrFace = pdfmetrics.EmbeddedType1Face(fname + '.afm', fname + '.pfb') cyrEnc = pdfmetrics.Encoding('CP1251') cp1251 = ( 'afii10051', 'afii10052', 'quotesinglbase', 'afii10100', 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'Euro', 'perthousand', 'afii10058', 'guilsinglleft', 'afii10059', 'afii10061', 'afii10060', 'afii10145', 'afii10099', 'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark', 'afii10106', 'guilsinglright', 'afii10107', 'afii10109', 'afii10108', 'afii10193', 'space', 'afii10062', 'afii10110', 'afii10057', 'currency', 'afii10050', 'brokenbar', 'section', 'afii10023', 'copyright', 'afii10053', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', 'afii10056', 'degree', 'plusminus', 'afii10055', 'afii10103', 'afii10098', 'mu1', 'paragraph', 'periodcentered', 'afii10071', 'afii61352', 'afii10101', 'guillemotright', 'afii10105', 'afii10054', 'afii10102', 'afii10104', 'afii10017', 'afii10018', 'afii10019', 'afii10020', 'afii10021', 'afii10022', 'afii10024', 'afii10025', 'afii10026', 'afii10027', 'afii10028', 'afii10029', 'afii10030', 'afii10031', 'afii10032', 'afii10033', 'afii10034', 'afii10035', 'afii10036', 'afii10037', 'afii10038', 'afii10039', 'afii10040', 'afii10041', 'afii10042', 'afii10043', 'afii10044', 'afii10045', 'afii10046', 'afii10047', 'afii10048', 'afii10049', 'afii10065', 'afii10066', 'afii10067', 'afii10068', 'afii10069', 'afii10070', 'afii10072', 'afii10073', 'afii10074', 'afii10075', 'afii10076', 'afii10077', 'afii10078', 'afii10079', 'afii10080', 'afii10081', 'afii10082', 'afii10083', 'afii10084', 'afii10085', 'afii10086', 'afii10087', 'afii10088', 'afii10089', 'afii10090', 'afii10091', 'afii10092', 'afii10093', 'afii10094', 'afii10095', 'afii10096', 'afii10097') for i in range(128, 256): cyrEnc[i] = cp1251[i - 128] pdfmetrics.registerEncoding(cyrEnc) pdfmetrics.registerTypeFace(cyrFace) pdfmetrics.registerFont( pdfmetrics.Font(faceName + '1251', faceName, 'CP1251')) c.setFont(faceName + '1251', n)
def registerFont(faceName, afm, pfb): """ Helvetica BUT AS AFM The below section is NOT equal to:: _baseFontName ='Helvetica' _baseFontNameB ='Helvetica-Bold' _baseFontNameI ='Helvetica-Oblique' _baseFontNameBI='Helvetica-BoldOblique' we will mapp afm files from matplotlib with pfb files from reportlab this will give embedded Type1 Face Fonts """ afm = os.path.join(__font_dir__, "".join(afm, ".afm")) pfb = os.path.join(__font_dir__, "".join(pfb, ".pfb")) face = pdfmetrics.EmbeddedType1Face(afm, pfb) pdfmetrics.registerTypeFace(face) font = pdfmetrics.Font(faceName, faceName, 'WinAnsiEncoding') pdfmetrics.registerFont(font)
def import_pdf_font(self, base_name, face_name): if self.fonts.get(face_name, None) is None: afm = find(base_name + '.afm') pfb = find(base_name + '.pfb') ttf = find(base_name + '.ttf') if afm: try: face = pdfmetrics.EmbeddedType1Face(afm, pfb) pdfmetrics.registerTypeFace(face) font = pdfmetrics.Font(face_name, face_name, 'WinAnsiEncoding') pdfmetrics.registerFont(font) except: pass elif ttf: pdfmetrics.registerFont(TTFont(face_name, ttf)) else: raise Exception( 'Cannot find font %s (tried .afm, .pfb and .ttf)' % base_name) else: self.fonts[face_name] = True
def process(self): args = self.getAttributeValues(valuesOnly=True) face = pdfmetrics.EmbeddedType1Face(*args) pdfmetrics.registerTypeFace(face)
def loadFont(self, names, src, encoding="WinAnsiEncoding", bold=0, italic=0): # XXX Just works for local filenames! if names and src: file = src src = file.uri log.debug("Load font %r", src) if type(names) is types.ListType: fontAlias = names else: fontAlias = (x.lower().strip() for x in names.split(",") if x) # XXX Problems with unicode here fontAlias = [str(x) for x in fontAlias] fontName = fontAlias[0] parts = src.split(".") baseName, suffix = ".".join(parts[:-1]), parts[-1] suffix = suffix.lower() if suffix in ["ttc", "ttf"]: # determine full font name according to weight and style fullFontName = "%s_%d%d" % (fontName, bold, italic) # check if font has already been registered if fullFontName in self.fontList: log.warn( self.warning( "Repeated font embed for %s, skip new embed ", fullFontName)) else: # Register TTF font and special name filename = file.getNamedFile() pdfmetrics.registerFont(TTFont(fullFontName, filename)) # Add or replace missing styles for bold in (0, 1): for italic in (0, 1): if ("%s_%d%d" % (fontName, bold, italic)) not in self.fontList: addMapping(fontName, bold, italic, fullFontName) # Register "normal" name and the place holder for style self.registerFont(fontName, fontAlias + [fullFontName]) elif suffix in ("afm", "pfb"): if suffix == "afm": afm = file.getNamedFile() tfile = pisaFileObject(baseName + ".pfb") pfb = tfile.getNamedFile() else: pfb = file.getNamedFile() tfile = pisaFileObject(baseName + ".afm") afm = tfile.getNamedFile() # determine full font name according to weight and style fullFontName = "%s_%d%d" % (fontName, bold, italic) # check if font has already been registered if fullFontName in self.fontList: log.warn( self.warning( "Repeated font embed for %s, skip new embed", fontName)) else: # Include font face = pdfmetrics.EmbeddedType1Face(afm, pfb) fontNameOriginal = face.name pdfmetrics.registerTypeFace(face) # print fontName, fontNameOriginal, fullFontName justFont = pdfmetrics.Font(fullFontName, fontNameOriginal, encoding) pdfmetrics.registerFont(justFont) # Add or replace missing styles for bold in (0, 1): for italic in (0, 1): if ("%s_%d%d" % (fontName, bold, italic)) not in self.fontList: addMapping(fontName, bold, italic, fontNameOriginal) # Register "normal" name and the place holder for style self.registerFont( fontName, fontAlias + [fullFontName, fontNameOriginal]) else: log.warning(self.warning("wrong attributes for <pdf:font>"))
def autoEmbed(fname): """Given a font name, does a best-effort of embedding said font and its variants. Returns a list of the font names it registered with ReportLab. """ log.info("Trying to embed %s" % fname) fontList = [] variants = [] f = findFont(fname) if f: # We have this font located if f[0].lower().endswith(".afm"): # Type 1 font family = families[f[2]] # Register the whole family of faces faces = [ pdfmetrics.EmbeddedType1Face(*fonts[fn.lower()][:2]) for fn in family ] for face in faces: pdfmetrics.registerTypeFace(face) for face, name in zip(faces, family): fontList.append(name) font = pdfmetrics.Font(face, name, "WinAnsiEncoding") log.info("Registering font: %s from %s" % (name, face.getFontFiles())) pdfmetrics.registerFont(font) # Map the variants regular, italic, bold, bolditalic = family for n in fname, regular: addMapping(n, 0, 0, regular) addMapping(n, 0, 1, italic) addMapping(n, 1, 0, bold) addMapping(n, 1, 1, bolditalic) log.info("Embedding as %s" % fontList) return fontList else: # A TTF font variants = [fonts[x.lower()][0] for x in families[f[2]]] if not variants: # Try fc-match variants = findTTFont(fname) # It is a TT Font and we found it using fc-match (or found *something*) if variants: for variant in variants: vname = os.path.basename(variant)[:-4] try: if vname not in pdfmetrics._fonts: _font = TTFont(vname, variant) log.info("Registering font: %s from %s" % (vname, variant)) pdfmetrics.registerFont(_font) except TTFError: log.error("Error registering font: %s from %s" % (vname, variant)) else: fontList.append(vname) regular, bold, italic, bolditalic = [ os.path.basename(variant)[:-4] for variant in variants ] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) log.info("Embedding via findTTFont as %s" % fontList) return fontList
def getExamples(): """Returns all the example flowable objects""" styleSheet = getSampleStyleSheet() story = [] #make a style with indents and spacing sty = ParagraphStyle('obvious', None) sty.leftIndent = 18 sty.rightIndent = 18 sty.firstLineIndent = 18 sty.spaceBefore = 6 sty.spaceAfter = 6 story.append( Paragraph( """Now for some demo stuff - we need some on this page, even before we explain the concepts fully""", styleSheet['BodyText'])) p = Paragraph( """ Platypus is all about fitting objects into frames on the page. You are looking at a fairly simple Platypus paragraph in Debug mode. It has some gridlines drawn around it to show the left and right indents, and the space before and after, all of which are attributes set in the style sheet. To be specific, this paragraph has left and right indents of 18 points, a first line indent of 36 points, and 6 points of space before and after itself. A paragraph object fills the width of the enclosing frame, as you would expect.""", sty) p.debug = 1 #show me the borders story.append(p) story.append( Paragraph( """Same but with justification 1.5 extra leading and green text.""", styleSheet['BodyText'])) p = Paragraph( """ <para align=justify leading="+1.5" fg=green><font color=red>Platypus</font> is all about fitting objects into frames on the page. You are looking at a fairly simple Platypus paragraph in Debug mode. It has some gridlines drawn around it to show the left and right indents, and the space before and after, all of which are attributes set in the style sheet. To be specific, this paragraph has left and right indents of 18 points, a first line indent of 36 points, and 6 points of space before and after itself. A paragraph object fills the width of the enclosing frame, as you would expect.</para>""", sty) p.debug = 1 #show me the borders story.append(p) story.append( platypus.XBox(4 * inch, 0.75 * inch, 'This is a box with a fixed size')) story.append( Paragraph( """ All of this is being drawn within a text frame which was defined on the page. This frame is in 'debug' mode so you can see the border, and also see the margins which it reserves. A frame does not have to have margins, but they have been set to 6 points each to create a little space around the contents. """, styleSheet['BodyText'])) story.append(FrameBreak()) ####################################################################### # Examples Page 2 ####################################################################### story.append( Paragraph( """ Here's the base class for Flowable... """, styleSheet['Italic'])) code = '''class Flowable: """Abstract base class for things to be drawn. Key concepts: 1. It knows its size 2. It draws in its own coordinate system (this requires the base API to provide a translate() function. """ def __init__(self): self.width = 0 self.height = 0 self.wrapped = 0 def drawOn(self, canvas, x, y): "Tell it to draw itself on the canvas. Do not override" self.canv = canvas self.canv.saveState() self.canv.translate(x, y) self.draw() #this is the bit you overload self.canv.restoreState() del self.canv def wrap(self, availWidth, availHeight): """This will be called by the enclosing frame before objects are asked their size, drawn or whatever. It returns the size actually used.""" return (self.width, self.height) ''' story.append(Preformatted(code, styleSheet['Code'], dedent=4)) story.append(FrameBreak()) ####################################################################### # Examples Page 3 ####################################################################### story.append( Paragraph("Here are some examples of the remaining objects above.", styleSheet['Italic'])) story.append( Paragraph("This is a bullet point", styleSheet['Bullet'], bulletText='O')) story.append( Paragraph("Another bullet point", styleSheet['Bullet'], bulletText='O')) story.append( Paragraph( """Here is a Table, which takes all kinds of formatting options...""", styleSheet['Italic'])) story.append(platypus.Spacer(0, 12)) g = platypus.Table( (('', 'North', 'South', 'East', 'West'), ('Quarter 1', 100, 200, 300, 400), ('Quarter 2', 100, 200, 300, 400), ('Total', 200, 400, 600, 800)), (72, 36, 36, 36, 36), (24, 16, 16, 18)) style = platypus.TableStyle([ ('ALIGN', (1, 1), (-1, -1), 'RIGHT'), ('ALIGN', (0, 0), (-1, 0), 'CENTRE'), ('GRID', (0, 0), (-1, -1), 0.25, colors.black), ('LINEBELOW', (0, 0), (-1, 0), 2, colors.black), ('LINEBELOW', (1, -1), (-1, -1), 2, (0.5, 0.5, 0.5)), ('TEXTCOLOR', (0, 1), (0, -1), colors.black), ('BACKGROUND', (0, 0), (-1, 0), (0, 0.7, 0.7)) ]) g.setStyle(style) story.append(g) story.append(FrameBreak()) ####################################################################### # Examples Page 4 - custom fonts ####################################################################### # custom font with LettError-Robot font import reportlab.rl_config reportlab.rl_config.warnOnMissingFontGlyphs = 0 from reportlab.pdfbase import pdfmetrics fontDir = os.path.join(_RL_DIR, 'fonts') face = pdfmetrics.EmbeddedType1Face( os.path.join(fontDir, 'DarkGardenMK.afm'), os.path.join(fontDir, 'DarkGardenMK.pfb')) faceName = face.name # should be 'DarkGardenMK' pdfmetrics.registerTypeFace(face) font = pdfmetrics.Font(faceName, faceName, 'WinAnsiEncoding') pdfmetrics.registerFont(font) # put it inside a paragraph. story.append( Paragraph( """This is an ordinary paragraph, which happens to contain text in an embedded font: <font name="DarkGardenMK">DarkGardenMK</font>. Now for the real challenge...""", styleSheet['Normal'])) styRobot = ParagraphStyle('Robot', styleSheet['Normal']) styRobot.fontSize = 16 styRobot.leading = 20 styRobot.fontName = 'DarkGardenMK' story.append( Paragraph("This whole paragraph is 16-point DarkGardenMK.", styRobot)) story.append(FrameBreak()) if _GIF: story.append( Paragraph( "Here is an Image flowable obtained from a string filename.", styleSheet['Italic'])) story.append(platypus.Image(_GIF)) story.append( Paragraph( "Here is an Image flowable obtained from a utf8 filename.", styleSheet['Italic'])) #story.append(platypus.Image(fileName2FSEnc(_GIF))) story.append( Paragraph( "Here is an Image flowable obtained from a string file url.", styleSheet['Italic'])) story.append(platypus.Image(getFurl(_GIF))) story.append( Paragraph("Here is an Image flowable obtained from an open file.", styleSheet['Italic'])) story.append(platypus.Image(open_for_read(_GIF, 'b'))) story.append(FrameBreak()) try: img = platypus.Image( 'http://www.reportlab.com/rsrc/encryption.gif') story.append( Paragraph( "Here is an Image flowable obtained from a string http url.", styleSheet['Italic'])) story.append(img) except: story.append( Paragraph( "The image could not be obtained from a string http url.", styleSheet['Italic'])) story.append(FrameBreak()) if _JPG: img = platypus.Image(_JPG) story.append( Paragraph( "Here is an JPEG Image flowable obtained from a filename.", styleSheet['Italic'])) story.append(img) story.append( Paragraph( "Here is an JPEG Image flowable obtained from an open file.", styleSheet['Italic'])) img = platypus.Image(open_for_read(_JPG, 'b')) story.append(img) story.append(FrameBreak()) return story
fontSize=size)) d.add(String(130, 120, 'Hello World', fontName='Courier', fontSize=36)) d.add(String(150, 160, 'Hello World', fontName='DarkGardenMK', fontSize=36)) """) from reportlab.pdfbase import pdfmetrics from reportlab import rl_config rl_config.warnOnMissingFontGlyphs = 0 afmFile, pfbFile = getJustFontPaths() T1face = pdfmetrics.EmbeddedType1Face(afmFile, pfbFile) T1faceName = 'DarkGardenMK' pdfmetrics.registerTypeFace(T1face) T1font = pdfmetrics.Font(T1faceName, T1faceName, 'WinAnsiEncoding') pdfmetrics.registerFont(T1font) d = Drawing(400, 200) for size in range(12, 36, 4): d.add( String(10 + size * 2, 10 + size * 2, 'Hello World', fontName='Times-Roman', fontSize=size)) d.add(String(130, 120, 'Hello World', fontName='Courier', fontSize=36))
def __init__(self, flist, font_path=None, style_path=None, def_dpi=300): log.info('Using stylesheets: %s' % ','.join(flist)) # find base path if hasattr(sys, 'frozen'): self.PATH = abspath(dirname(sys.executable)) else: self.PATH = abspath(dirname(__file__)) # flist is a list of stylesheet filenames. # They will be loaded and merged in order. # but the two default stylesheets will always # be loaded first flist = [ join(self.PATH, 'styles', 'styles.style'), join(self.PATH, 'styles', 'default.style') ] + flist self.def_dpi = def_dpi if font_path is None: font_path = [] font_path += ['.', os.path.join(self.PATH, 'fonts')] self.FontSearchPath = list(map(os.path.expanduser, font_path)) if style_path is None: style_path = [] style_path += [ '.', os.path.join(self.PATH, 'styles'), '~/.rst2pdf/styles' ] self.StyleSearchPath = list(map(os.path.expanduser, style_path)) # Remove duplicates but preserve order. Not very efficient, but these are short lists self.FontSearchPath = [x for (i,x) in enumerate(self.FontSearchPath) if self.FontSearchPath.index(x) == i] self.StyleSearchPath = [x for (i,x) in enumerate(self.StyleSearchPath) if self.StyleSearchPath.index(x) == i] log.info('FontPath:%s' % self.FontSearchPath) log.info('StylePath:%s' % self.StyleSearchPath) findfonts.flist = self.FontSearchPath # Page width, height self.pw = 0 self.ph = 0 # Page size [w,h] self.ps = None # Margins (top,bottom,left,right,gutter) self.tm = 0 self.bm = 0 self.lm = 0 self.rm = 0 self.gm = 0 # text width self.tw = 0 # Default emsize, later it will be the fontSize of the base style self.emsize = 10 self.languages = [] ssdata = self.readSheets(flist) # Get pageSetup data from all stylessheets in order: self.ps = pagesizes.A4 self.page = {} for data, ssname in ssdata: page = data.get('pageSetup', {}) if page: self.page.update(page) pgs = page.get('size', None) if pgs: # A standard size pgs = pgs.upper() if pgs in pagesizes.__dict__: self.ps = list(pagesizes.__dict__[pgs]) self.psname = pgs if 'width' in self.page: del(self.page['width']) if 'height' in self.page: del(self.page['height']) elif pgs.endswith('-LANDSCAPE'): self.psname = pgs.split('-')[0] self.ps = list(pagesizes.landscape(pagesizes.__dict__[self.psname])) if 'width' in self.page: del(self.page['width']) if 'height' in self.page: del(self.page['height']) else: log.critical('Unknown page size %s in stylesheet %s' % (page['size'], ssname)) continue else: # A custom size if 'size'in self.page: del(self.page['size']) # The sizes are expressed in some unit. # For example, 2cm is 2 centimeters, and we need # to do 2*cm (cm comes from reportlab.lib.units) if 'width' in page: self.ps[0] = self.adjustUnits(page['width']) if 'height' in page: self.ps[1] = self.adjustUnits(page['height']) self.pw, self.ph = self.ps if 'margin-left' in page: self.lm = self.adjustUnits(page['margin-left']) if 'margin-right' in page: self.rm = self.adjustUnits(page['margin-right']) if 'margin-top' in page: self.tm = self.adjustUnits(page['margin-top']) if 'margin-bottom' in page: self.bm = self.adjustUnits(page['margin-bottom']) if 'margin-gutter' in page: self.gm = self.adjustUnits(page['margin-gutter']) if 'spacing-header' in page: self.ts = self.adjustUnits(page['spacing-header']) if 'spacing-footer' in page: self.bs = self.adjustUnits(page['spacing-footer']) if 'firstTemplate' in page: self.firstTemplate = page['firstTemplate'] # tw is the text width. # We need it to calculate header-footer height # and compress literal blocks. self.tw = self.pw - self.lm - self.rm - self.gm # Get page templates from all stylesheets self.pageTemplates = {} for data, ssname in ssdata: templates = data.get('pageTemplates', {}) # templates is a dictionary of pageTemplates for key in templates: template = templates[key] # template is a dict. # template[´frames'] is a list of frames if key in self.pageTemplates: self.pageTemplates[key].update(template) else: self.pageTemplates[key] = template # Get font aliases from all stylesheets in order self.fontsAlias = {} for data, ssname in ssdata: self.fontsAlias.update(data.get('fontsAlias', {})) embedded_fontnames = [] self.embedded = [] # Embed all fonts indicated in all stylesheets for data, ssname in ssdata: embedded = data.get('embeddedFonts', []) for font in embedded: try: # Just a font name, try to embed it if isinstance(font, six.string_types): # See if we can find the font fname, pos = findfonts.guessFont(font) if font in embedded_fontnames: pass else: fontList = findfonts.autoEmbed(font) if fontList: embedded_fontnames.append(font) if not fontList: if (fname, pos) in embedded_fontnames: fontList = None else: fontList = findfonts.autoEmbed(fname) if fontList is not None: self.embedded += fontList # Maybe the font we got is not called # the same as the one we gave # so check that out suff = ["", "-Oblique", "-Bold", "-BoldOblique"] if not fontList[0].startswith(font): # We need to create font aliases, and use them for fname, aliasname in zip( fontList, [font + suffix for suffix in suff]): self.fontsAlias[aliasname] = fname continue # Each "font" is a list of four files, which will be # used for regular / bold / italic / bold+italic # versions of the font. # If your font doesn't have one of them, just repeat # the regular font. # Example, using the Tuffy font from # http://tulrich.com/fonts/ # "embeddedFonts" : [ # ["Tuffy.ttf", # "Tuffy_Bold.ttf", # "Tuffy_Italic.ttf", # "Tuffy_Bold_Italic.ttf"] # ], # The fonts will be registered with the file name, # minus the extension. if font[0].lower().endswith('.ttf'): # A True Type font for variant in font: location = self.findFont(variant) pdfmetrics.registerFont( TTFont(str(variant.split('.')[0]), location)) log.info('Registering font: %s from %s' % (str( variant.split('.')[0]), location)) self.embedded.append(str(variant.split('.')[0])) # And map them all together regular, bold, italic, bolditalic = [ variant.split('.')[0] for variant in font] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) else: # A Type 1 font # For type 1 fonts we require # [FontName,regular,italic,bold,bolditalic] # where each variant is a (pfbfile,afmfile) pair. # For example, for the URW palladio from TeX: # ["Palatino",("uplr8a.pfb","uplr8a.afm"), # ("uplri8a.pfb","uplri8a.afm"), # ("uplb8a.pfb","uplb8a.afm"), # ("uplbi8a.pfb","uplbi8a.afm")] regular = pdfmetrics.EmbeddedType1Face(*font[1]) italic = pdfmetrics.EmbeddedType1Face(*font[2]) bold = pdfmetrics.EmbeddedType1Face(*font[3]) bolditalic = pdfmetrics.EmbeddedType1Face(*font[4]) except Exception as e: try: if isinstance(font, list): fname = font[0] else: fname = font log.error("Error processing font %s: %s", os.path.splitext(fname)[0], str(e)) log.error("Registering %s as Helvetica alias", fname) self.fontsAlias[fname] = 'Helvetica' except Exception as e: log.critical("Error processing font %s: %s", fname, str(e)) continue # Go though all styles in all stylesheets and find all fontNames. # Then decide what to do with them for data, ssname in ssdata: for [skey, style] in self.stylepairs(data): for key in style: if key == 'fontName' or key.endswith('FontName'): # It's an alias, replace it if style[key] in self.fontsAlias: style[key] = self.fontsAlias[style[key]] # Embedded already, nothing to do if style[key] in self.embedded: continue # Standard font, nothing to do if style[key] in ( "Courier", "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique", "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique", "Helvetica-Oblique", "Symbol", "Times-Bold", "Times-BoldItalic", "Times-Italic", "Times-Roman", "ZapfDingbats"): continue # Now we need to do something # See if we can find the font fname, pos = findfonts.guessFont(style[key]) if style[key] in embedded_fontnames: pass else: fontList = findfonts.autoEmbed(style[key]) if fontList: embedded_fontnames.append(style[key]) if not fontList: if (fname, pos) in embedded_fontnames: fontList = None else: fontList = findfonts.autoEmbed(fname) if fontList: embedded_fontnames.append((fname, pos)) if fontList: self.embedded += fontList # Maybe the font we got is not called # the same as the one we gave so check that out suff = ["", "-Bold", "-Oblique", "-BoldOblique"] if not fontList[0].startswith(style[key]): # We need to create font aliases, and use them basefname = style[key].split('-')[0] for fname, aliasname in zip( fontList, [basefname + suffix for suffix in suff]): self.fontsAlias[aliasname] = fname style[key] = self.fontsAlias[basefname + suff[pos]] else: log.error("Unknown font: \"%s\"," "replacing with Helvetica", style[key]) style[key] = "Helvetica" # Get styles from all stylesheets in order self.stylesheet = {} self.styles = [] self.linkColor = 'navy' # FIXME: linkColor should probably not be a global # style, and tocColor should probably not # be a special case, but for now I'm going # with the flow... self.tocColor = None for data, ssname in ssdata: self.linkColor = data.get('linkColor') or self.linkColor self.tocColor = data.get('tocColor') or self.tocColor for [skey, style] in self.stylepairs(data): sdict = {} # FIXME: this is done completely backwards for key in style: # Handle color references by name if key == 'color' or key.endswith('Color') and style[key]: style[key] = formatColor(style[key]) elif key == 'commands': style[key] = validateCommands(style[key]) # Handle alignment constants elif key == 'alignment': style[key] = dict(TA_LEFT=0, LEFT=0, TA_CENTER=1, CENTER=1, TA_CENTRE=1, CENTRE=1, TA_RIGHT=2, RIGHT=2, TA_JUSTIFY=4, JUSTIFY=4, DECIMAL=8, )[style[key].upper()] elif key == 'language': if not style[key] in self.languages: self.languages.append(style[key]) sdict[key] = style[key] sdict['name'] = skey # If the style already exists, update it if skey in self.stylesheet: self.stylesheet[skey].update(sdict) else: # New style self.stylesheet[skey] = sdict self.styles.append(sdict) # If the stylesheet has a style name docutils won't reach # make a copy with a sanitized name. # This may make name collisions possible but that should be # rare (who would have custom_name and custom-name in the # same stylesheet? ;-) # Issue 339 styles2 = [] for s in self.styles: if not re.match("^[a-z](-?[a-z0-9]+)*$", s['name']): s2 = copy(s) s2['name'] = docutils.nodes.make_id(s['name']) log.warning( '%s is an invalid docutils class name, adding alias %s' % (s['name'], s2['name'])) styles2.append(s2) self.styles.extend(styles2) # And create reportlabs stylesheet self.StyleSheet = StyleSheet1() dirty = True while dirty: dirty = False for s in self.styles: if s['name'] in self.StyleSheet: continue try: if 'parent' in s: if s['parent'] is None: if s['name'] != 'base': s['parent'] = self.StyleSheet['base'] else: del(s['parent']) else: s['parent'] = self.StyleSheet[s['parent']] else: if s['name'] != 'base': s['parent'] = self.StyleSheet['base'] except KeyError: dirty = True continue # If the style has no bulletFontName but it has a fontName, set it if ('bulletFontName' not in s) and ('fontName' in s): s['bulletFontName'] = s['fontName'] hasFS = True # Adjust fontsize units if 'fontSize' not in s: s['fontSize'] = s['parent'].fontSize s['trueFontSize'] = None hasFS = False elif 'parent' in s: # This means you can set the fontSize to # "2cm" or to "150%" which will be calculated # relative to the parent style s['fontSize'] = self.adjustUnits(s['fontSize'], s['parent'].fontSize) s['trueFontSize'] = s['fontSize'] else: # If s has no parent, it's base, which has # an explicit point size by default and % # makes no sense, but guess it as % of 10pt s['fontSize'] = self.adjustUnits(s['fontSize'], 10) # If the leading is not set, but the size is, set it if 'leading' not in s and hasFS: s['leading'] = 1.2*s['fontSize'] # If the bullet font size is not set, set it as fontSize if ('bulletFontSize' not in s) and ('fontSize' in s): s['bulletFontSize'] = s['fontSize'] # If the borderPadding is a list and wordaxe <=0.3.2, # convert it to an integer. Workaround for Issue if 'borderPadding' in s and ( ((HAS_WORDAXE and wordaxe_version <= 'wordaxe 0.3.2') or reportlab.Version < "2.3") and isinstance(s['borderPadding'], list)): log.warning( 'Using a borderPadding list in ' 'style %s with wordaxe <= 0.3.2 or Reportlab < 2.3. That is not ' 'supported, so it will probably look wrong' % s['name']) s['borderPadding'] = s['borderPadding'][0] if 'spaceBefore' in s: if isinstance(s['spaceBefore'], str) and s['spaceBefore'].startswith('-'): log.warning('A negative spaceBefore is the same as 0') s['spaceBefore'] = self.adjustUnits(s['spaceBefore']) if 'spaceAfter' in s: if isinstance(s['spaceAfter'], str) and s['spaceAfter'].startswith('-'): log.warning('A negative spaceAfter is the same as 0') s['spaceAfter'] = self.adjustUnits(s['spaceAfter']) self.StyleSheet.add(ParagraphStyle(**s)) self.emsize = self['base'].fontSize # Make stdFont the basefont, for Issue 65 reportlab.rl_config.canvas_basefontname = self['base'].fontName # Make stdFont the default font for table cell styles (Issue 65) reportlab.platypus.tables.CellStyle.fontname = self['base'].fontName
def loadFont(self, names, src, encoding="WinAnsiEncoding", bold=0, italic=0): if names and src: if type(names) is types.ListType: fontAlias = names else: fontAlias = [x.lower().strip() for x in names.split(",") if x] # XXX Problems with unicode here fontAlias = [str(x) for x in fontAlias] src = str(src) fontName = fontAlias[0] parts = src.split(".") baseName, suffix = ".".join(parts[:-1]), parts[-1] suffix = suffix.lower() try: if suffix == "ttf": # determine full font name according to weight and style fullFontName = "%s_%d%d" % (fontName, bold, italic) # check if font has already been registered if fullFontName in self.fontList: log.warn( self.warning( "Repeated font embed for %s, skip new embed ", fullFontName)) else: # Register TTF font and special name pdfmetrics.registerFont(TTFont(fullFontName, src)) # Add or replace missing styles for bold in (0, 1): for italic in (0, 1): if ("%s_%d%d" % (fontName, bold, italic)) not in self.fontList: addMapping(fontName, bold, italic, fullFontName) # Register "normal" name and the place holder for style self.registerFont(fontName, fontAlias + [fullFontName]) elif suffix in ("afm", "pfb"): afm = baseName + ".afm" pfb = baseName + ".pfb" # determine full font name according to weight and style fullFontName = "%s_%d%d" % (fontName, bold, italic) #fontNameOriginal = "" #for line in open(afm).readlines()[:-1]: # if line[:16] == 'StartCharMetrics': # self.error("Font name not found") # if line[:8] == 'FontName': # fontNameOriginal = line[9:].strip() # break # check if font has already been registered if fullFontName in self.fontList: log.warn( self.warning( "Repeated font embed for %s, skip new embed", fontName)) else: # Include font face = pdfmetrics.EmbeddedType1Face(afm, pfb) fontNameOriginal = face.name pdfmetrics.registerTypeFace(face) # print fontName, fontNameOriginal, fullFontName justFont = pdfmetrics.Font(fullFontName, fontNameOriginal, encoding) pdfmetrics.registerFont(justFont) # Add or replace missing styles for bold in (0, 1): for italic in (0, 1): if ("%s_%d%d" % (fontName, bold, italic)) not in self.fontList: addMapping(fontName, bold, italic, fontNameOriginal) # Register "normal" name and the place holder for style self.registerFont( fontName, fontAlias + [fullFontName, fontNameOriginal]) #import pprint #pprint.pprint(self.fontList) else: log.warning( self.warning("wrong attributes for <pdf:font>")) except Exception, e: log.warn(self.warning("Loading font '%s'", fontName), exc_info=1)
def autoEmbed(fname): """Given a font name, does a best-effort of embedding said font and its variants. Returns a list of the font names it registered with ReportLab. """ log.info('Trying to embed %s' % fname) fontList = [] f = findFont(fname) if f: # It's a Type 1 font, and we have it family = families[f[2]] # Register the whole family of faces faces = [pdfmetrics.EmbeddedType1Face(*fonts[fn][:2]) for fn in family] for face in faces: pdfmetrics.registerTypeFace(face) for face, name in zip(faces, family): fontList.append(name) font = pdfmetrics.Font(face, name, "WinAnsiEncoding") log.info('Registering font: %s from %s'%\ (face,name)) pdfmetrics.registerFont(font) # Map the variants regular, italic, bold, bolditalic = family addMapping(fname, 0, 0, regular) addMapping(fname, 0, 1, italic) addMapping(fname, 1, 0, bold) addMapping(fname, 1, 1, bolditalic) addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) log.info('Embedding as %s' % fontList) return fontList variants = findTTFont(fname) # It is a TT Font and we found it using fc-match (or found *something*) if variants: for variant in variants: vname = os.path.basename(variant)[:-4] try: if vname not in pdfmetrics._fonts: _font = TTFont(vname, variant, validate=1) log.info('Registering font: %s from %s'%\ (vname,variant)) pdfmetrics.registerFont(_font) except TTFError: log.error('Error registering font: %s from %s' % (vname, variant)) else: fontList.append(vname) regular, bold, italic, bolditalic = [ os.path.basename(variant)[:-4] for variant in variants ] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) log.info('Embedding via findTTFont as %s' % fontList) return fontList
from reportlab.pdfgen import canvas from reportlab.pdfbase import pdfmetrics # Create a new canvas for cyrillic.pdf file c = canvas.Canvas('cyrillic.pdf') # fname - the font file name without extension fname = 'a010013l' # faceName - view a010013l.AFM file as a plain text and look at # row beginning with 'FontName' word (it's usually the fourth row). # The word after 'FontName' is the faceName ('URWGothicL-Book' in this case). faceName = 'URWGothicL-Book' # Define new Type 1 font cyrFace = pdfmetrics.EmbeddedType1Face(fname + '.afm', fname + '.pfb') # Create a new encoding called 'CP1251' cyrenc = pdfmetrics.Encoding('CP1251') # Fill in the tuple with Unicode glyphs in accordance with cp1251 (win1251) # encoding cp1251 = ('afii10051', 'afii10052', 'quotesinglbase', 'afii10100', 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'Euro', 'perthousand', 'afii10058', 'guilsinglleft', 'afii10059', 'afii10061', 'afii10060', 'afii10145', 'afii10099', 'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark', 'afii10106', 'guilsinglright', 'afii10107', 'afii10109', 'afii10108', 'afii10193', 'space', 'afii10062', 'afii10110', 'afii10057', 'currency', 'afii10050', 'brokenbar', 'section', 'afii10023', 'copyright', 'afii10053',
def __registerFont__(fontname, afmFilename, pfbFilename): justFace = pdfmetrics.EmbeddedType1Face(afmFilename, pfbFilename) pdfmetrics.registerTypeFace(justFace) justFont = pdfmetrics.Font(fontname, fontname, 'WinAnsiEncoding') pdfmetrics.registerFont(justFont)
def test0(self): """Make documents with embedded fonts. Just vam Rossum has kindly donated a font which we may use for testing purposes. You need to contact him at [email protected] if you want to use it for real.""" #LettError fonts should always be there. The others are voluntary. ok = 1 c = Canvas(outputfile('test_pdfbase_fontembed.pdf')) c.setPageCompression(0) c.setFont('Helvetica', 12) c.drawString( 100, 700, 'This is Helvetica. The text below should be different fonts...') if os.path.isfile('GDB_____.AFM') and os.path.isfile('GDB_____.PFB'): # a normal text font garaFace = pdfmetrics.EmbeddedType1Face('GDB_____.AFM', 'GDB_____.PFB') faceName = 'AGaramond-Bold' # pulled from AFM file pdfmetrics.registerTypeFace(garaFace) garaFont = pdfmetrics.Font('MyGaramondBold', faceName, 'WinAnsiEncoding') pdfmetrics.registerFont(garaFont) c.setFont('AGaramond-Bold', 12) c.drawString(100, 650, 'This should be in AGaramond-Bold') if os.path.isfile('CR______.AFM') and os.path.isfile('CR______.PFB'): # one with a custom encoding cartaFace = pdfmetrics.EmbeddedType1Face('CR______.AFM', 'CR______.PFB') faceName = 'Carta' # pulled from AFM file pdfmetrics.registerTypeFace(cartaFace) cartaFont = pdfmetrics.Font('Carta', 'Carta', 'CartaEncoding') pdfmetrics.registerFont(cartaFont) text = 'This should be in Carta, a map symbol font:' c.setFont('Helvetica', 12) c.drawString(100, 600, text) w = c.stringWidth(text, 'Helvetica', 12) c.setFont('Carta', 12) c.drawString(100 + w, 600, ' Hello World') # LettError sample - creates on demand, we hope y = 550 ## dgmkFace = pdfmetrics.EmbeddedType1Face('DarkGardenMK.afm','DarkGardenMK.PFB') ## ## faceName = 'DarkGardenMK' # pulled from AFM file ## pdfmetrics.registerTypeFace(dgmkFace) ## ## dgmkFont = pdfmetrics.Font('DarkGardenMK', faceName, 'WinAnsiEncoding') ## pdfmetrics.registerFont(dgmk) c.setFont('DarkGardenMK', 12) c.drawString(100, y, 'This should be in DarkGardenMK') def testNamedFont(canv, fontName): canv.showPage() makeWidthTestForAllGlyphs(canv, fontName, outlining=0) testNamedFont(c, 'DarkGardenMK') c.save()
def __init__(self, flist, font_path=None, style_path=None, def_dpi=300): log.info('Using stylesheets: %s' % ','.join(flist)) # find base path if hasattr(sys, 'frozen'): self.PATH = abspath(dirname(sys.executable)) else: self.PATH = abspath(dirname(__file__)) # flist is a list of stylesheet filenames. # They will be loaded and merged in order. # but the two default stylesheets will always # be loaded first flist = [join(self.PATH, 'styles', 'styles.style'), join(self.PATH, 'styles', 'default.style')] + flist self.def_dpi=def_dpi if font_path is None: font_path=[] font_path+=['.', os.path.join(self.PATH, 'fonts')] self.FontSearchPath = map(os.path.expanduser, font_path) if style_path is None: style_path=[] style_path+=['.', os.path.join(self.PATH, 'styles'), '~/.rst2pdf/styles'] self.StyleSearchPath = map(os.path.expanduser, style_path) self.FontSearchPath=list(set(self.FontSearchPath)) self.StyleSearchPath=list(set(self.StyleSearchPath)) log.info('FontPath:%s'%self.FontSearchPath) log.info('StylePath:%s'%self.StyleSearchPath) findfonts.flist = self.FontSearchPath # Page width, height self.pw = 0 self.ph = 0 # Page size [w,h] self.ps = None # Margins (top,bottom,left,right,gutter) self.tm = 0 self.bm = 0 self.lm = 0 self.rm = 0 self.gm = 0 #text width self.tw = 0 # Default emsize, later it will be the fontSize of the base style self.emsize=10 self.languages = [] ssdata = self.readSheets(flist) # Get pageSetup data from all stylessheets in order: self.ps = pagesizes.A4 self.page={} for data, ssname in ssdata: page = data.get('pageSetup', {}) if page: self.page.update(page) pgs=page.get('size', None) if pgs: # A standard size pgs=pgs.upper() if pgs in pagesizes.__dict__: self.ps = list(pagesizes.__dict__[pgs]) self.psname = pgs if 'width' in self.page: del(self.page['width']) if 'height' in self.page: del(self.page['height']) elif pgs.endswith('-LANDSCAPE'): self.psname = pgs.split('-')[0] self.ps = list(pagesizes.landscape(pagesizes.__dict__[self.psname])) if 'width' in self.page: del(self.page['width']) if 'height' in self.page: del(self.page['height']) else: log.critical('Unknown page size %s in stylesheet %s'%\ (page['size'], ssname)) continue else: #A custom size if 'size'in self.page: del(self.page['size']) # The sizes are expressed in some unit. # For example, 2cm is 2 centimeters, and we need # to do 2*cm (cm comes from reportlab.lib.units) if 'width' in page: self.ps[0] = self.adjustUnits(page['width']) if 'height' in page: self.ps[1] = self.adjustUnits(page['height']) self.pw, self.ph = self.ps if 'margin-left' in page: self.lm = self.adjustUnits(page['margin-left']) if 'margin-right' in page: self.rm = self.adjustUnits(page['margin-right']) if 'margin-top' in page: self.tm = self.adjustUnits(page['margin-top']) if 'margin-bottom' in page: self.bm = self.adjustUnits(page['margin-bottom']) if 'margin-gutter' in page: self.gm = self.adjustUnits(page['margin-gutter']) if 'spacing-header' in page: self.ts = self.adjustUnits(page['spacing-header']) if 'spacing-footer' in page: self.bs = self.adjustUnits(page['spacing-footer']) if 'firstTemplate' in page: self.firstTemplate = page['firstTemplate'] # tw is the text width. # We need it to calculate header-footer height # and compress literal blocks. self.tw = self.pw - self.lm - self.rm - self.gm # Get page templates from all stylesheets self.pageTemplates = {} for data, ssname in ssdata: templates = data.get('pageTemplates', {}) # templates is a dictionary of pageTemplates for key in templates: template = templates[key] # template is a dict. # template[´frames'] is a list of frames if key in self.pageTemplates: self.pageTemplates[key].update(template) else: self.pageTemplates[key] = template # Get font aliases from all stylesheets in order self.fontsAlias = {} for data, ssname in ssdata: self.fontsAlias.update(data.get('fontsAlias', {})) embedded_fontnames = [] self.embedded = [] # Embed all fonts indicated in all stylesheets for data, ssname in ssdata: embedded = data.get('embeddedFonts', []) for font in embedded: try: # Just a font name, try to embed it if isinstance(font, unicode): # See if we can find the font fname, pos = findfonts.guessFont(font) if font in embedded_fontnames: pass else: fontList = findfonts.autoEmbed(font) if fontList: embedded_fontnames.append(font) if not fontList: if (fname, pos) in embedded_fontnames: fontList = None else: fontList = findfonts.autoEmbed(fname) if fontList is not None: self.embedded += fontList # Maybe the font we got is not called # the same as the one we gave # so check that out suff = ["", "-Oblique", "-Bold", "-BoldOblique"] if not fontList[0].startswith(font): # We need to create font aliases, and use them for fname, aliasname in zip( fontList, [font + suffix for suffix in suff]): self.fontsAlias[aliasname] = fname continue # Each "font" is a list of four files, which will be # used for regular / bold / italic / bold+italic # versions of the font. # If your font doesn't have one of them, just repeat # the regular font. # Example, using the Tuffy font from # http://tulrich.com/fonts/ # "embeddedFonts" : [ # ["Tuffy.ttf", # "Tuffy_Bold.ttf", # "Tuffy_Italic.ttf", # "Tuffy_Bold_Italic.ttf"] # ], # The fonts will be registered with the file name, # minus the extension. if font[0].lower().endswith('.ttf'): # A True Type font for variant in font: location=self.findFont(variant) pdfmetrics.registerFont( TTFont(str(variant.split('.')[0]), location)) log.info('Registering font: %s from %s'%\ (str(variant.split('.')[0]),location)) self.embedded.append(str(variant.split('.')[0])) # And map them all together regular, bold, italic, bolditalic = [ variant.split('.')[0] for variant in font] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) else: # A Type 1 font # For type 1 fonts we require # [FontName,regular,italic,bold,bolditalic] # where each variant is a (pfbfile,afmfile) pair. # For example, for the URW palladio from TeX: # ["Palatino",("uplr8a.pfb","uplr8a.afm"), # ("uplri8a.pfb","uplri8a.afm"), # ("uplb8a.pfb","uplb8a.afm"), # ("uplbi8a.pfb","uplbi8a.afm")] faceName = font[0] regular = pdfmetrics.EmbeddedType1Face(*font[1]) italic = pdfmetrics.EmbeddedType1Face(*font[2]) bold = pdfmetrics.EmbeddedType1Face(*font[3]) bolditalic = pdfmetrics.EmbeddedType1Face(*font[4]) except Exception, e: try: if isinstance(font, list): fname = font[0] else: fname = font log.error("Error processing font %s: %s", os.path.splitext(fname)[0], str(e)) log.error("Registering %s as Helvetica alias", fname) self.fontsAlias[fname] = 'Helvetica' except Exception, e: log.critical("Error processing font %s: %s", fname, str(e)) continue
import os from reportlab.pdfbase import pdfmetrics, pdfdoc for afm in os.listdir('.'): if not afm.endswith('.afm'): continue title = afm[:-4] pfb = title + '.pfb' if not os.path.exists(pfb): print "%s doesn't exist!" % pfb continue face = pdfmetrics.EmbeddedType1Face(afm, pfb) if face.name != title: os.rename(afm, face.name + '.afm') os.rename(pfb, face.name + '.pfb')
] addMapping(regular, 0, 0, regular) addMapping(regular, 0, 1, italic) addMapping(regular, 1, 0, bold) addMapping(regular, 1, 1, bolditalic) else: # A Type 1 font # For type 1 fonts we require # [FontName,regular,italic,bold,bolditalic] # where each variant is a (pfbfile,afmfile) pair. # For example, for the URW palladio from TeX: # ["Palatino",("uplr8a.pfb","uplr8a.afm"), # ("uplri8a.pfb","uplri8a.afm"), # ("uplb8a.pfb","uplb8a.afm"), # ("uplbi8a.pfb","uplbi8a.afm")] faceName = font[0] regular = pdfmetrics.EmbeddedType1Face(*font[1]) italic = pdfmetrics.EmbeddedType1Face(*font[2]) bold = pdfmetrics.EmbeddedType1Face(*font[3]) bolditalic = pdfmetrics.EmbeddedType1Face(*font[4]) except Exception, e: try: if isinstance(font, list): fname = font[0] else: fname = font log.error("Error processing font %s: %s", os.path.splitext(fname)[0], str(e)) log.error("Registering %s as Helvetica alias", fname) self.fontsAlias[fname] = 'Helvetica' except Exception, e: