def test_get_size_simple(self): res = getSize('12pt') self.assertEqual(res, 12.00) # Memoized... res = getSize('12pt') self.assertEqual(res, 12.00)
def test_get_size_for_none_str(self): res = getSize("none") self.assertEqual(res, 0.0) res = getSize("0") self.assertEqual(res, 0.0) res = getSize("auto") # Really? self.assertEqual(res, 0.0)
def __init__(self, path, debug=0, capacity=-1): self.fontList = copy.copy(xhtml2pdf.default.DEFAULT_FONT) self.path = [] self.capacity = capacity self.node = None self.toc = PmlTableOfContents() self.story = [] self.indexing_story = None self.text = [] self.log = [] self.err = 0 self.warn = 0 self.text = u"" self.uidctr = 0 self.multiBuild = False self.pageSize = A4 self.template = None self.templateList = {} self.frameList = [] self.frameStatic = {} self.frameStaticList = [] self.pisaBackgroundList = [] self.keepInFrameIndex = None self.baseFontSize = getSize("12pt") self.anchorFrag = [] self.anchorName = [] self.tableData = None self.frag = self.fragBlock = getParaFrag(ParagraphStyle("default%d" % self.UID())) self.fragList = [] self.fragAnchor = [] self.fragStack = [] self.fragStrip = True self.listCounter = 0 self.cssText = "" self.cssDefaultText = "" self.image = None self.imageData = {} self.force = False self.pathCallback = None # External callback function for path calculations # Store path to document self.pathDocument = path or "__dummy__" parts = urlparse.urlparse(self.pathDocument) if not parts.scheme: self.pathDocument = os.path.abspath(self.pathDocument) self.pathDirectory = getDirName(self.pathDocument) self.meta = dict(author="", title="", subject="", keywords="", pagesize=A4)
def _height(value=None): if value is None: return None value = str(value) if value.endswith("%"): return value return getSize(value)
def start(self, c): if self.attr["color"] is not None: c.frag.textColor = getColor(self.attr["color"]) if self.attr["face"] is not None: c.frag.fontName = c.getFontName(self.attr["face"]) if self.attr["size"] is not None: size = getSize(self.attr["size"], c.frag.fontSize, c.baseFontSize) c.frag.fontSize = max(size, 1.0)
def __init__(self, path, debug=0, capacity=-1): self.fontList = copy.copy(xhtml2pdf.default.DEFAULT_FONT) set_value(self, ('path', 'story', 'text', 'log', 'frameStaticList', 'pisaBackgroundList', 'frameList', 'anchorFrag', 'anchorName', 'fragList', 'fragAnchor', 'fragStack' ), [], _copy=True) set_value(self, ('node', 'indexing_story', 'template', 'keepInFrameIndex', 'tableData', 'image'), None) set_value(self, ('err', 'warn', 'uidctr', 'listCounter'), 0) set_value(self, ('text', 'cssText', 'cssDefaultText'), "") set_value(self, ('templateList', 'frameStatic', 'imageData'), {}, _copy=True) self.capacity = capacity self.toc = PmlTableOfContents() self.multiBuild = False self.pageSize = A4 self.baseFontSize = getSize("12pt") self.frag = self.fragBlock = getParaFrag( ParagraphStyle('default%d' % self.UID())) self.fragStrip = True self.force = False # External callback function for path calculations self.pathCallback = None # Store path to document self.pathDocument = path or "__dummy__" parts = urlparse.urlparse(self.pathDocument) if not parts.scheme: self.pathDocument = os.path.abspath(self.pathDocument) self.pathDirectory = getDirName(self.pathDocument) self.meta = dict( author="", title="", subject="", keywords="", pagesize=A4, )
def atPage(self, name, pseudopage, declarations): c = self.c data = {} name = name or "body" pageBorder = None if declarations: result = self.ruleset([self.selector('*')], declarations) if declarations: data = list(result[0].values())[0] pageBorder = data.get("-pdf-frame-border", None) if name in c.templateList: log.warning(self.c.warning("template '%s' has already been defined", name)) if "-pdf-page-size" in data: c.pageSize = xhtml2pdf.default.PML_PAGESIZES.get(str(data["-pdf-page-size"]).lower(), c.pageSize) isLandscape = False if "size" in data: size = data["size"] if type(size) is not list: size = [size] sizeList = [] for value in size: valueStr = str(value).lower() if type(value) is tuple: sizeList.append(getSize(value)) elif valueStr == "landscape": isLandscape = True elif valueStr in xhtml2pdf.default.PML_PAGESIZES: c.pageSize = xhtml2pdf.default.PML_PAGESIZES[valueStr] else: log.warning(c.warning("Unknown size value for @page")) if len(sizeList) == 2: c.pageSize = tuple(sizeList) if isLandscape: c.pageSize = landscape(c.pageSize) padding_top = self._getFromData(data, 'padding-top', 0, getSize) padding_left = self._getFromData(data, 'padding-left', 0, getSize) padding_right = self._getFromData(data, 'padding-right', 0, getSize) padding_bottom = self._getFromData(data, 'padding-bottom', 0, getSize) border_color = self._getFromData(data, ('border-top-color', 'border-bottom-color',\ 'border-left-color', 'border-right-color'), None, getColor) border_width = self._getFromData(data, ('border-top-width', 'border-bottom-width',\ 'border-left-width', 'border-right-width'), 0, getSize) for prop in ("margin-top", "margin-left", "margin-right", "margin-bottom", "top", "left", "right", "bottom", "width", "height"): if prop in data: c.frameList.append(self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize)) break # Frames have to be calculated after we know the pagesize frameList = [] staticList = [] for fname, static, border, x, y, w, h, fdata in c.frameList: fpadding_top = self._getFromData(fdata, 'padding-top', padding_top, getSize) fpadding_left = self._getFromData(fdata, 'padding-left', padding_left, getSize) fpadding_right = self._getFromData(fdata, 'padding-right', padding_right, getSize) fpadding_bottom = self._getFromData(fdata, 'padding-bottom', padding_bottom, getSize) fborder_color = self._getFromData(fdata, ('border-top-color', 'border-bottom-color',\ 'border-left-color', 'border-right-color'), border_color, getColor) fborder_width = self._getFromData(fdata, ('border-top-width', 'border-bottom-width',\ 'border-left-width', 'border-right-width'), border_width, getSize) if border or pageBorder: frame_border = ShowBoundaryValue() else: frame_border = ShowBoundaryValue(color=fborder_color, width=fborder_width) #fix frame sizing problem. if static: x, y, w, h = getFrameDimensions(fdata, c.pageSize[0], c.pageSize[1]) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warning(self.c.warning("Negative width or height of frame. Check @frame definitions.")) frame = Frame( x, y, w, h, id=fname, leftPadding=fpadding_left, rightPadding=fpadding_right, bottomPadding=fpadding_bottom, topPadding=fpadding_top, showBoundary=frame_border) if static: frame.pisaStaticStory = [] c.frameStatic[static] = [frame] + c.frameStatic.get(static, []) staticList.append(frame) else: frameList.append(frame) background = data.get("background-image", None) if background: #should be relative to the css file background = self.c.getFile(background, relative=self.c.cssParser.rootPath) if not frameList: log.warning(c.warning("missing explicit frame definition for content or just static frames")) fname, static, border, x, y, w, h, data = self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warning(c.warning("Negative width or height of frame. Check @page definitions.")) if border or pageBorder: frame_border = ShowBoundaryValue() else: frame_border = ShowBoundaryValue(color=border_color, width=border_width) frameList.append(Frame( x, y, w, h, id=fname, leftPadding=padding_left, rightPadding=padding_right, bottomPadding=padding_bottom, topPadding=padding_top, showBoundary=frame_border)) pt = PmlPageTemplate( id=name, frames=frameList, pagesize=c.pageSize, ) pt.pisaStaticList = staticList pt.pisaBackground = background pt.pisaBackgroundList = c.pisaBackgroundList if isLandscape: pt.pageorientation = pt.LANDSCAPE c.templateList[name] = pt c.template = None c.frameList = [] c.frameStaticList = [] return {}, {}
def test_get_size_for_mm(self): res = getSize("1mm") self.assertEqual(res, 2.8346456692913385)
def addPara(self, force=False, incols=None): force = (force or self.force) self.force = False # Cleanup the trail rfragList = reversed(self.fragList) # Find maximum lead maxLeading = 0 #fontSize = 0 for frag in self.fragList: leading = getSize(frag.leadingSource, frag.fontSize) + frag.leadingSpace maxLeading = max(leading, frag.fontSize + frag.leadingSpace, maxLeading) frag.leading = leading if force or (self.text.strip() and self.fragList): # Update paragraph style by style of first fragment first = self.fragBlock style = self.toParagraphStyle(first) # style.leading = first.leading + first.leadingSpace if first.leadingSpace: style.leading = maxLeading else: style.leading = getSize(first.leadingSource, first.fontSize) + first.leadingSpace bulletText = copy.copy(first.bulletText) first.bulletText = None # Add paragraph to story if force or len(self.fragAnchor + self.fragList) > 0: # We need this empty fragment to work around problems in # Reportlab paragraphs regarding backGround etc. if self.fragList: self.fragList.append(self.fragList[-1].clone(text='')) else: blank = self.frag.clone() blank.fontName = "Helvetica" blank.text = '' self.fragList.append(blank) self.dumpPara(self.fragAnchor + self.fragList, style) if hasattr(self, 'language'): language = self.__getattribute__('language') detect_language_result = arabic_format(self.text, language) if detect_language_result != None: self.text = detect_language_result para = PmlParagraph(self.text, style, frags=self.fragAnchor + self.fragList, bulletText=bulletText) para.outline = first.outline para.outlineLevel = first.outlineLevel para.outlineOpen = first.outlineOpen para.keepWithNext = first.keepWithNext para.autoLeading = "max" if self.image: para = PmlParagraphAndImage(para, self.image, side=self.imageData.get( "align", "left")) if isinstance(para, PmlParagraph): para.frags[0].inCols = incols self.addStory(para) self.fragAnchor = [] first.bulletText = None # Reset data self.image = None self.imageData = {} self.clearFrag()
def test_get_size_for_cm(self): res = getSize("1cm") self.assertEqual(res, 28.346456692913385)
def test_get_size_for_inch(self): res = getSize("1in") self.assertEqual(res, 72.00)
def pisaLoop(node, context, path=None, **kw): if path is None: path = [] # Initialize KW if not kw: kw = { "margin-top": 0, "margin-bottom": 0, "margin-left": 0, "margin-right": 0, } else: kw = copy.copy(kw) #indent = len(path) * " " # only used for debug print statements # TEXT if node.nodeType == Node.TEXT_NODE: # print indent, "#", repr(node.data) #, context.frag context.addFrag(node.data) # context.text.append(node.value) # ELEMENT elif node.nodeType == Node.ELEMENT_NODE: node.tagName = node.tagName.replace(":", "").lower() if node.tagName in ("style", "script"): return path = copy.copy(path) + [node.tagName] # Prepare attributes attr = pisaGetAttributes(context, node.tagName, node.attributes) #log.debug(indent + "<%s %s>" % (node.tagName, attr) + repr(node.attributes.items())) #, path # Calculate styles context.cssAttr = CSSCollect(node, context) context.cssAttr = mapNonStandardAttrs(context.cssAttr, node, attr) context.node = node # Block? PAGE_BREAK = 1 PAGE_BREAK_RIGHT = 2 PAGE_BREAK_LEFT = 3 pageBreakAfter = False frameBreakAfter = False display = lower(context.cssAttr.get("display", "inline")) # print indent, node.tagName, display, context.cssAttr.get("background-color", None), attr isBlock = (display == "block") if isBlock: context.addPara() # Page break by CSS if "-pdf-next-page" in context.cssAttr: context.addStory(NextPageTemplate(str(context.cssAttr["-pdf-next-page"]))) if "-pdf-page-break" in context.cssAttr: if str(context.cssAttr["-pdf-page-break"]).lower() == "before": context.addStory(PageBreak()) if "-pdf-frame-break" in context.cssAttr: if str(context.cssAttr["-pdf-frame-break"]).lower() == "before": context.addStory(FrameBreak()) if str(context.cssAttr["-pdf-frame-break"]).lower() == "after": frameBreakAfter = True if "page-break-before" in context.cssAttr: if str(context.cssAttr["page-break-before"]).lower() == "always": context.addStory(PageBreak()) if str(context.cssAttr["page-break-before"]).lower() == "right": context.addStory(PageBreak()) context.addStory(PmlRightPageBreak()) if str(context.cssAttr["page-break-before"]).lower() == "left": context.addStory(PageBreak()) context.addStory(PmlLeftPageBreak()) if "page-break-after" in context.cssAttr: if str(context.cssAttr["page-break-after"]).lower() == "always": pageBreakAfter = PAGE_BREAK if str(context.cssAttr["page-break-after"]).lower() == "right": pageBreakAfter = PAGE_BREAK_RIGHT if str(context.cssAttr["page-break-after"]).lower() == "left": pageBreakAfter = PAGE_BREAK_LEFT if display == "none": # print "none!" return # Translate CSS to frags # Save previous frag styles context.pushFrag() # Map styles to Reportlab fragment properties CSS2Frag(context, kw, isBlock) # EXTRAS if "-pdf-keep-with-next" in context.cssAttr: context.frag.keepWithNext = getBool(context.cssAttr["-pdf-keep-with-next"]) if "-pdf-outline" in context.cssAttr: context.frag.outline = getBool(context.cssAttr["-pdf-outline"]) if "-pdf-outline-level" in context.cssAttr: context.frag.outlineLevel = int(context.cssAttr["-pdf-outline-level"]) if "-pdf-outline-open" in context.cssAttr: context.frag.outlineOpen = getBool(context.cssAttr["-pdf-outline-open"]) if "-pdf-word-wrap" in context.cssAttr: context.frag.wordWrap = context.cssAttr["-pdf-word-wrap"] # handle keep-in-frame keepInFrameMode = None keepInFrameMaxWidth = 0 keepInFrameMaxHeight = 0 if "-pdf-keep-in-frame-mode" in context.cssAttr: value = str(context.cssAttr["-pdf-keep-in-frame-mode"]).strip().lower() if value in ("shrink", "error", "overflow", "truncate"): keepInFrameMode = value if "-pdf-keep-in-frame-max-width" in context.cssAttr: keepInFrameMaxWidth = getSize("".join(context.cssAttr["-pdf-keep-in-frame-max-width"])) if "-pdf-keep-in-frame-max-height" in context.cssAttr: keepInFrameMaxHeight = getSize("".join(context.cssAttr["-pdf-keep-in-frame-max-height"])) # ignore nested keep-in-frames, tables have their own KIF handling keepInFrame = keepInFrameMode is not None and context.keepInFrameIndex is None if keepInFrame: # keep track of current story index, so we can wrap everythink # added after this point in a KeepInFrame context.keepInFrameIndex = len(context.story) # BEGIN tag klass = globals().get("pisaTag%s" % node.tagName.replace(":", "").upper(), None) obj = None # Static block elementId = attr.get("id", None) staticFrame = context.frameStatic.get(elementId, None) if staticFrame: context.frag.insideStaticFrame += 1 oldStory = context.swapStory() # Tag specific operations if klass is not None: obj = klass(node, attr) obj.start(context) # Visit child nodes context.fragBlock = fragBlock = copy.copy(context.frag) for nnode in node.childNodes: pisaLoop(nnode, context, path, **kw) context.fragBlock = fragBlock # END tag if obj: obj.end(context) # Block? if isBlock: context.addPara() # XXX Buggy! # Page break by CSS if pageBreakAfter: context.addStory(PageBreak()) if pageBreakAfter == PAGE_BREAK_RIGHT: context.addStory(PmlRightPageBreak()) if pageBreakAfter == PAGE_BREAK_LEFT: context.addStory(PmlLeftPageBreak()) if frameBreakAfter: context.addStory(FrameBreak()) if keepInFrame: # get all content added after start of -pdf-keep-in-frame and wrap # it in a KeepInFrame substory = context.story[context.keepInFrameIndex:] context.story = context.story[:context.keepInFrameIndex] context.story.append( KeepInFrame( content=substory, maxWidth=keepInFrameMaxWidth, maxHeight=keepInFrameMaxHeight)) context.keepInFrameIndex = None # Static block, END if staticFrame: context.addPara() for frame in staticFrame: frame.pisaStaticStory = context.story context.swapStory(oldStory) context.frag.insideStaticFrame -= 1 # context.debug(1, indent, "</%s>" % (node.tagName)) # Reset frag style context.pullFrag() # Unknown or not handled else: # context.debug(1, indent, "???", node, node.nodeType, repr(node)) # Loop over children for node in node.childNodes: pisaLoop(node, context, path, **kw)
def addPara(self, force=False): force = (force or self.force) self.force = False # Cleanup the trail try: rfragList = reversed(self.fragList) except: # For Python 2.3 compatibility rfragList = copy.copy(self.fragList) rfragList.reverse() # Find maximum lead maxLeading = 0 #fontSize = 0 for frag in self.fragList: leading = getSize(frag.leadingSource, frag.fontSize) + frag.leadingSpace maxLeading = max(leading, frag.fontSize + frag.leadingSpace, maxLeading) frag.leading = leading if force or (self.text.strip() and self.fragList): # Update paragraph style by style of first fragment first = self.fragBlock style = self.toParagraphStyle(first) # style.leading = first.leading + first.leadingSpace if first.leadingSpace: style.leading = maxLeading else: style.leading = getSize(first.leadingSource, first.fontSize) + first.leadingSpace bulletText = copy.copy(first.bulletText) first.bulletText = None # Add paragraph to story if force or len(self.fragAnchor + self.fragList) > 0: # We need this empty fragment to work around problems in # Reportlab paragraphs regarding backGround etc. if self.fragList: self.fragList.append(self.fragList[-1].clone(text='')) else: blank = self.frag.clone() blank.fontName = "Helvetica" blank.text = '' self.fragList.append(blank) self.dumpPara(self.fragAnchor + self.fragList, style) para = PmlParagraph(self.text, style, frags=self.fragAnchor + self.fragList, bulletText=bulletText) para.outline = first.outline para.outlineLevel = first.outlineLevel para.outlineOpen = first.outlineOpen para.keepWithNext = first.keepWithNext para.autoLeading = "max" if self.image: para = PmlParagraphAndImage(para, self.image, side=self.imageData.get( "align", "left")) self.addStory(para) self.fragAnchor = [] first.bulletText = None # Reset data self.image = None self.imageData = {} self.clearFrag()
def test_get_size_for_float(self): res = getSize(12.00) self.assertEqual(res, 12.00)
def test_get_size_for_tuple(self): # TODO: This is a really strange case. Probably should not work this way. res = getSize(("12", ".12")) self.assertEqual(res, 12.12)
def _pisaDimensions(self, data, page_width, page_height): """Calculate dimensions of a frame Returns left, top, width and height of the frame in points. """ box = data.get("-pdf-frame-box", []) if len(box) == 4: return [getSize(x) for x in box] top = getSize(data.get("top", 0)) left = getSize(data.get("left", 0)) bottom = getSize(data.get("bottom", 0)) right = getSize(data.get("right", 0)) if "height" in data: height = getSize(data["height"]) if "top" in data: top = getSize(data["top"]) bottom = page_height - (top + height) elif "bottom" in data: bottom = getSize(data["bottom"]) top = page_height - (bottom + height) if "width" in data: width = getSize(data["width"]) if "left" in data: left = getSize(data["left"]) right = page_width - (left + width) elif "right" in data: right = getSize(data["right"]) left = page_width - (right + width) top += getSize(data.get("margin-top", 0)) left += getSize(data.get("margin-left", 0)) bottom += getSize(data.get("margin-bottom", 0)) right += getSize(data.get("margin-right", 0)) width = page_width - (left + right) height = page_height - (top + bottom) return left, top, width, height
def test_get_size_for_none(self): res = getSize(None, relative='TOKEN') self.assertEqual(res, 'TOKEN')
def CSS2Frag(c, kw, isBlock): def safeGetColor(color, default=None): try: return getColor(color) except ValueError: # the css parser is responsible for calculating of inherited values so inherit do not work here return getColor(default) # COLORS if c.cssAttr.has_key("color"): c.frag.textColor = safeGetColor(c.cssAttr["color"], default="#000000") if c.cssAttr.has_key("background-color"): c.frag.backColor = safeGetColor(c.cssAttr["background-color"], default="#ffffff") # FONT SIZE, STYLE, WEIGHT if c.cssAttr.has_key("font-family"): c.frag.fontName = c.getFontName(c.cssAttr["font-family"]) if c.cssAttr.has_key("font-size"): # XXX inherit c.frag.fontSize = max( getSize("".join(c.cssAttr["font-size"]), c.frag.fontSize, c.baseFontSize), 1.0) if c.cssAttr.has_key("line-height"): leading = "".join(c.cssAttr["line-height"]) c.frag.leading = getSize(leading, c.frag.fontSize) c.frag.leadingSource = leading else: c.frag.leading = getSize(c.frag.leadingSource, c.frag.fontSize) if c.cssAttr.has_key("-pdf-line-spacing"): c.frag.leadingSpace = getSize("".join(c.cssAttr["-pdf-line-spacing"])) # print "line-spacing", c.cssAttr["-pdf-line-spacing"], c.frag.leading if c.cssAttr.has_key("font-weight"): value = c.cssAttr["font-weight"].lower() if value in ("bold", "bolder", "500", "600", "700", "800", "900"): c.frag.bold = 1 else: c.frag.bold = 0 for value in toList(c.cssAttr.get("text-decoration", "")): if "underline" in value: c.frag.underline = 1 if "line-through" in value: c.frag.strike = 1 if "none" in value: c.frag.underline = 0 c.frag.strike = 0 if c.cssAttr.has_key("font-style"): value = c.cssAttr["font-style"].lower() if value in ("italic", "oblique"): c.frag.italic = 1 else: c.frag.italic = 0 if c.cssAttr.has_key("white-space"): # normal | pre | nowrap c.frag.whiteSpace = str(c.cssAttr["white-space"]).lower() # ALIGN & VALIGN if c.cssAttr.has_key("text-align"): c.frag.alignment = getAlign(c.cssAttr["text-align"]) if c.cssAttr.has_key("vertical-align"): c.frag.vAlign = c.cssAttr["vertical-align"] # HEIGHT & WIDTH if c.cssAttr.has_key("height"): c.frag.height = "".join(toList( c.cssAttr["height"])) # XXX Relative is not correct! if c.frag.height in ("auto", ): c.frag.height = None if c.cssAttr.has_key("width"): # print c.cssAttr["width"] c.frag.width = "".join(toList( c.cssAttr["width"])) # XXX Relative is not correct! if c.frag.width in ("auto", ): c.frag.width = None # ZOOM if c.cssAttr.has_key("zoom"): # print c.cssAttr["width"] zoom = "".join(toList( c.cssAttr["zoom"])) # XXX Relative is not correct! if zoom.endswith("%"): zoom = float(zoom[:-1]) / 100.0 c.frag.zoom = float(zoom) # MARGINS & LIST INDENT, STYLE if isBlock: if c.cssAttr.has_key("margin-top"): c.frag.spaceBefore = getSize(c.cssAttr["margin-top"], c.frag.fontSize) if c.cssAttr.has_key("margin-bottom"): c.frag.spaceAfter = getSize(c.cssAttr["margin-bottom"], c.frag.fontSize) if c.cssAttr.has_key("margin-left"): c.frag.bulletIndent = kw["margin-left"] # For lists kw["margin-left"] += getSize(c.cssAttr["margin-left"], c.frag.fontSize) c.frag.leftIndent = kw["margin-left"] # print "MARGIN LEFT", kw["margin-left"], c.frag.bulletIndent if c.cssAttr.has_key("margin-right"): kw["margin-right"] += getSize(c.cssAttr["margin-right"], c.frag.fontSize) c.frag.rightIndent = kw["margin-right"] # print c.frag.rightIndent if c.cssAttr.has_key("text-indent"): c.frag.firstLineIndent = getSize(c.cssAttr["text-indent"], c.frag.fontSize) if c.cssAttr.has_key("list-style-type"): c.frag.listStyleType = str(c.cssAttr["list-style-type"]).lower() if c.cssAttr.has_key("list-style-image"): c.frag.listStyleImage = c.getFile(c.cssAttr["list-style-image"]) # PADDINGS if isBlock: if c.cssAttr.has_key("padding-top"): c.frag.paddingTop = getSize(c.cssAttr["padding-top"], c.frag.fontSize) if c.cssAttr.has_key("padding-bottom"): c.frag.paddingBottom = getSize(c.cssAttr["padding-bottom"], c.frag.fontSize) if c.cssAttr.has_key("padding-left"): c.frag.paddingLeft = getSize(c.cssAttr["padding-left"], c.frag.fontSize) if c.cssAttr.has_key("padding-right"): c.frag.paddingRight = getSize(c.cssAttr["padding-right"], c.frag.fontSize) # BORDERS if isBlock: if c.cssAttr.has_key("border-top-width"): c.frag.borderTopWidth = getSize(c.cssAttr["border-top-width"], c.frag.fontSize) if c.cssAttr.has_key("border-bottom-width"): c.frag.borderBottomWidth = getSize( c.cssAttr["border-bottom-width"], c.frag.fontSize) if c.cssAttr.has_key("border-left-width"): c.frag.borderLeftWidth = getSize(c.cssAttr["border-left-width"], c.frag.fontSize) if c.cssAttr.has_key("border-right-width"): c.frag.borderRightWidth = getSize(c.cssAttr["border-right-width"], c.frag.fontSize) if c.cssAttr.has_key("border-top-style"): c.frag.borderTopStyle = c.cssAttr["border-top-style"] if c.cssAttr.has_key("border-bottom-style"): c.frag.borderBottomStyle = c.cssAttr["border-bottom-style"] if c.cssAttr.has_key("border-left-style"): c.frag.borderLeftStyle = c.cssAttr["border-left-style"] if c.cssAttr.has_key("border-right-style"): c.frag.borderRightStyle = c.cssAttr["border-right-style"] if c.cssAttr.has_key("border-top-color"): c.frag.borderTopColor = safeGetColor(c.cssAttr["border-top-color"], default="#ffffff") if c.cssAttr.has_key("border-bottom-color"): c.frag.borderBottomColor = safeGetColor( c.cssAttr["border-bottom-color"], default="#ffffff") if c.cssAttr.has_key("border-left-color"): c.frag.borderLeftColor = safeGetColor( c.cssAttr["border-left-color"], default="#ffffff") if c.cssAttr.has_key("border-right-color"): c.frag.borderRightColor = safeGetColor( c.cssAttr["border-right-color"], default="#ffffff")
def test_get_size_for_pc(self): res = getSize("1pc") self.assertEqual(res, 12.00)
def _parseAtPage(self, src): """page : PAGE_SYM S* IDENT? pseudo_page? S* '{' S* declaration [ ';' S* declaration ]* '}' S* ; """ data = {} pageBorder = None isLandscape = False ctxsrc = src src = src[len('@page'):].lstrip() page, src = self._getIdent(src) if src[:1] == ':': pseudopage, src = self._getIdent(src[1:]) page = page + '_' + pseudopage else: pseudopage = None #src, properties = self._parseDeclarationGroup(src.lstrip()) # Containing @ where not found and parsed stylesheetElements = [] src = src.lstrip() properties = [] # XXX Extended for PDF use if not src.startswith('{'): raise self.ParseError('Ruleset opening \'{\' not found', src, ctxsrc) else: src = src[1:].lstrip() while src and not src.startswith('}'): if src.startswith('@'): # @media, @page, @font-face src, atResults = self._parseAtKeyword(src) if atResults is not None: stylesheetElements.extend(atResults) else: src, nproperties = self._parseDeclarationGroup(src.lstrip(), braces=False) properties += nproperties # Set pagesize, orientation (landscape, portrait) data = {} pageBorder = None if properties: result = self.cssBuilder.ruleset([self.cssBuilder.selector('*')], properties) try: data = result[0].values()[0] except Exception: data = result[0].popitem()[1] pageBorder = data.get("-pdf-frame-border", None) if "-pdf-page-size" in data: self.c.pageSize = xhtml2pdf.default.PML_PAGESIZES.get( str(data["-pdf-page-size"]).lower(), self.c.pageSize) isLandscape = False if "size" in data: size = data["size"] if not isinstance(size, list): size = [size] sizeList = [] for value in size: valueStr = str(value).lower() if isinstance(value, tuple): sizeList.append(getSize(value)) elif valueStr == "landscape": isLandscape = True elif valueStr == "portrait": isLandscape = False elif valueStr in xhtml2pdf.default.PML_PAGESIZES: self.c.pageSize = xhtml2pdf.default.PML_PAGESIZES[valueStr] else: raise RuntimeError("Unknown size value for @page") if len(sizeList) == 2: self.c.pageSize = tuple(sizeList) if isLandscape: self.c.pageSize = landscape(self.c.pageSize) src = src.lstrip() result = [self.cssBuilder.atPage(page, pseudopage, data, isLandscape, pageBorder)] return src[1:].lstrip(), result
def _pisaDimensions(self, data, width, height): " Calculate dimensions of a box " # print data, width, height box = data.get("-pdf-frame-box", []) # print 123, box if len(box) == 4: return [getSize(x) for x in box] top = getSize(data.get("top", 0), height) left = getSize(data.get("left", 0), width) bottom = - getSize(data.get("bottom", 0), height) right = - getSize(data.get("right", 0), width) w = getSize(data.get("width", 0), width, default=None) h = getSize(data.get("height", 0), height, default=None) #print width, height, top, left, bottom, right, w, h if "height" in data: if "bottom" in data: top = bottom - h else: bottom = top + h if "width" in data: if "right" in data: # print right, w left = right - w else: right = left + w top += getSize(data.get("margin-top", 0), height) left += getSize(data.get("margin-left", 0), width) bottom -= getSize(data.get("margin-bottom", 0), height) right -= getSize(data.get("margin-right", 0), width) # box = getCoords(left, top, width, height, self.c.pageSize) # print "BOX", box # print top, left, w, h return left, top, right, bottom
def CSS2Frag(c, kw, isBlock): # COLORS if "color" in c.cssAttr: c.frag.textColor = getColor(c.cssAttr["color"]) if "background-color" in c.cssAttr: c.frag.backColor = getColor(c.cssAttr["background-color"]) # FONT SIZE, STYLE, WEIGHT if "font-family" in c.cssAttr: c.frag.fontName = c.getFontName(c.cssAttr["font-family"]) if "font-size" in c.cssAttr: # XXX inherit try: c.frag.fontSize = max(getSize("".join(c.cssAttr["font-size"]), c.frag.fontSize, c.baseFontSize), 1.0) except TypeError: # sequence item 0: expected string, tuple found c.frag.fontSize = max(getSize("".join(c.cssAttr["font-size"][0]), c.frag.fontSize, c.baseFontSize), 1.0) if "line-height" in c.cssAttr: leading = "".join(c.cssAttr["line-height"]) c.frag.leading = getSize(leading, c.frag.fontSize) c.frag.leadingSource = leading else: c.frag.leading = getSize(c.frag.leadingSource, c.frag.fontSize) if "letter-spacing" in c.cssAttr: c.frag.letterSpacing = c.cssAttr["letter-spacing"] if "-pdf-line-spacing" in c.cssAttr: c.frag.leadingSpace = getSize("".join(c.cssAttr["-pdf-line-spacing"])) # print "line-spacing", c.cssAttr["-pdf-line-spacing"], c.frag.leading if "font-weight" in c.cssAttr: value = lower(c.cssAttr["font-weight"]) if value in ("bold", "bolder", "500", "600", "700", "800", "900"): c.frag.bold = 1 else: c.frag.bold = 0 for value in toList(c.cssAttr.get("text-decoration", "")): if "underline" in value: c.frag.underline = 1 if "line-through" in value: c.frag.strike = 1 if "none" in value: c.frag.underline = 0 c.frag.strike = 0 if "font-style" in c.cssAttr: value = lower(c.cssAttr["font-style"]) if value in ("italic", "oblique"): c.frag.italic = 1 else: c.frag.italic = 0 if "white-space" in c.cssAttr: # normal | pre | nowrap c.frag.whiteSpace = str(c.cssAttr["white-space"]).lower() # ALIGN & VALIGN if "text-align" in c.cssAttr: c.frag.alignment = getAlign(c.cssAttr["text-align"]) if "vertical-align" in c.cssAttr: c.frag.vAlign = c.cssAttr["vertical-align"] # HEIGHT & WIDTH if "height" in c.cssAttr: try: c.frag.height = "".join(toList(c.cssAttr["height"])) # XXX Relative is not correct! except TypeError: # sequence item 0: expected string, tuple found c.frag.height = "".join(toList(c.cssAttr["height"][0])) if c.frag.height in ("auto",): c.frag.height = None if "width" in c.cssAttr: try: c.frag.width = "".join(toList(c.cssAttr["width"])) # XXX Relative is not correct! except TypeError: c.frag.width = "".join(toList(c.cssAttr["width"][0])) if c.frag.width in ("auto",): c.frag.width = None # ZOOM if "zoom" in c.cssAttr: zoom = "".join(toList(c.cssAttr["zoom"])) # XXX Relative is not correct! if zoom.endswith("%"): zoom = float(zoom[: - 1]) / 100.0 c.frag.zoom = float(zoom) # MARGINS & LIST INDENT, STYLE if isBlock: if "margin-top" in c.cssAttr: c.frag.spaceBefore = getSize(c.cssAttr["margin-top"], c.frag.fontSize) if "margin-bottom" in c.cssAttr: c.frag.spaceAfter = getSize(c.cssAttr["margin-bottom"], c.frag.fontSize) if "margin-left" in c.cssAttr: c.frag.bulletIndent = kw["margin-left"] # For lists kw["margin-left"] += getSize(c.cssAttr["margin-left"], c.frag.fontSize) c.frag.leftIndent = kw["margin-left"] if "margin-right" in c.cssAttr: kw["margin-right"] += getSize(c.cssAttr["margin-right"], c.frag.fontSize) c.frag.rightIndent = kw["margin-right"] if "text-indent" in c.cssAttr: c.frag.firstLineIndent = getSize(c.cssAttr["text-indent"], c.frag.fontSize) if "list-style-type" in c.cssAttr: c.frag.listStyleType = str(c.cssAttr["list-style-type"]).lower() if "list-style-image" in c.cssAttr: c.frag.listStyleImage = c.getFile(c.cssAttr["list-style-image"]) # PADDINGS if isBlock: if "padding-top" in c.cssAttr: c.frag.paddingTop = getSize(c.cssAttr["padding-top"], c.frag.fontSize) if "padding-bottom" in c.cssAttr: c.frag.paddingBottom = getSize(c.cssAttr["padding-bottom"], c.frag.fontSize) if "padding-left" in c.cssAttr: c.frag.paddingLeft = getSize(c.cssAttr["padding-left"], c.frag.fontSize) if "padding-right" in c.cssAttr: c.frag.paddingRight = getSize(c.cssAttr["padding-right"], c.frag.fontSize) # BORDERS if isBlock: if "border-top-width" in c.cssAttr: c.frag.borderTopWidth = getSize(c.cssAttr["border-top-width"], c.frag.fontSize) if "border-bottom-width" in c.cssAttr: c.frag.borderBottomWidth = getSize(c.cssAttr["border-bottom-width"], c.frag.fontSize) if "border-left-width" in c.cssAttr: c.frag.borderLeftWidth = getSize(c.cssAttr["border-left-width"], c.frag.fontSize) if "border-right-width" in c.cssAttr: c.frag.borderRightWidth = getSize(c.cssAttr["border-right-width"], c.frag.fontSize) if "border-top-style" in c.cssAttr: c.frag.borderTopStyle = c.cssAttr["border-top-style"] if "border-bottom-style" in c.cssAttr: c.frag.borderBottomStyle = c.cssAttr["border-bottom-style"] if "border-left-style" in c.cssAttr: c.frag.borderLeftStyle = c.cssAttr["border-left-style"] if "border-right-style" in c.cssAttr: c.frag.borderRightStyle = c.cssAttr["border-right-style"] if "border-top-color" in c.cssAttr: c.frag.borderTopColor = getColor(c.cssAttr["border-top-color"]) if "border-bottom-color" in c.cssAttr: c.frag.borderBottomColor = getColor(c.cssAttr["border-bottom-color"]) if "border-left-color" in c.cssAttr: c.frag.borderLeftColor = getColor(c.cssAttr["border-left-color"]) if "border-right-color" in c.cssAttr: c.frag.borderRightColor = getColor(c.cssAttr["border-right-color"])
def pisaGetAttributes(c, tag, attributes): global TAGS attrs = {} if attributes: for k, v in attributes.items(): try: attrs[str(k)] = str(v) # XXX no Unicode! Reportlab fails with template names except: attrs[k] = v nattrs = {} if tag in TAGS: block, adef = TAGS[tag] adef["id"] = STRING # print block, adef try: iteritems = adef.iteritems() except Exception: iteritems = iter(adef.items()) for k, v in iteritems: nattrs[k] = None # print k, v # defaults, wenn vorhanden if type(v) == tuple: if v[1] == MUST: if k not in attrs: log.warn(c.warning("Attribute '%s' must be set!", k)) nattrs[k] = None continue nv = attrs.get(k, v[1]) dfl = v[1] v = v[0] else: nv = attrs.get(k, None) dfl = None if nv is not None: if type(v) == list: nv = nv.strip().lower() if nv not in v: #~ raise PML_EXCEPTION, "attribute '%s' of wrong value, allowed is one of: %s" % (k, repr(v)) log.warn(c.warning("Attribute '%s' of wrong value, allowed is one of: %s", k, repr(v))) nv = dfl elif v == BOOL: nv = nv.strip().lower() nv = nv in ("1", "y", "yes", "true", str(k)) elif v == SIZE: try: nv = getSize(nv) except: log.warn(c.warning("Attribute '%s' expects a size value", k)) elif v == BOX: nv = getBox(nv, c.pageSize) elif v == POS: nv = getPos(nv, c.pageSize) elif v == INT: nv = int(nv) elif v == COLOR: nv = getColor(nv) elif v == FILE: nv = c.getFile(nv) elif v == FONT: nv = c.getFontName(nv) nattrs[k] = nv return AttrContainer(nattrs)
def atPage(self, name, pseudopage, declarations): c = self.c data = {} name = name or "body" pageBorder = None if declarations: result = self.ruleset([self.selector('*')], declarations) # print "@PAGE", name, pseudopage, declarations, result if declarations: data = result[0].values()[0] pageBorder = data.get("-pdf-frame-border", None) if name in c.templateList: log.warn(self.c.warning("template '%s' has already been defined", name)) if "-pdf-page-size" in data: c.pageSize = xhtml2pdf.default.PML_PAGESIZES.get(str(data["-pdf-page-size"]).lower(), c.pageSize) isLandscape = False if "size" in data: size = data["size"] # print size, c.pageSize if type(size) is not types.ListType: size = [size] sizeList = [] for value in size: valueStr = str(value).lower() if type(value) is types.TupleType: sizeList.append(getSize(value)) elif valueStr == "landscape": isLandscape = True elif valueStr in xhtml2pdf.default.PML_PAGESIZES: c.pageSize = xhtml2pdf.default.PML_PAGESIZES[valueStr] else: log.warn(c.warning("Unknown size value for @page")) if len(sizeList) == 2: c.pageSize = sizeList if isLandscape: c.pageSize = landscape(c.pageSize) for prop in ("margin-top", "margin-left", "margin-right", "margin-bottom", "top", "left", "right", "bottom", "width", "height"): if prop in data: c.frameList.append(self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize)) break # self._drawing = PmlPageDrawing(self._pagesize) #if not c.frameList: # c.warning("missing frame definitions for template") # return {}, {} # Frames have to be calculated after we know the pagesize frameList = [] staticList = [] for fname, static, border, x, y, w, h, fdata in c.frameList: #fix frame sizing problem. if static: x, y, w, h = getFrameDimensions(fdata, c.pageSize[0], c.pageSize[1]) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warn(self.c.warning("Negative width or height of frame. Check @frame definitions.")) frame = Frame( x, y, w, h, id=fname, leftPadding=0, rightPadding=0, bottomPadding=0, topPadding=0, showBoundary=border or pageBorder) if static: frame.pisaStaticStory = [] c.frameStatic[static] = [frame] + c.frameStatic.get(static, []) staticList.append(frame) else: frameList.append(frame) background = data.get("background-image", None) if background: background = self.c.getFile(background) # print background # print frameList if not frameList: # print 999 log.warn(c.warning("missing explicit frame definition for content or just static frames")) fname, static, border, x, y, w, h, data = self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warn(c.warning("Negative width or height of frame. Check @page definitions.")) frameList.append(Frame( x, y, w, h, id=fname, leftPadding=0, rightPadding=0, bottomPadding=0, topPadding=0, showBoundary=border or pageBorder)) pt = PmlPageTemplate( id=name, frames=frameList, pagesize=c.pageSize, ) pt.pisaStaticList = staticList pt.pisaBackground = background pt.pisaBackgroundList = c.pisaBackgroundList if isLandscape: pt.pageorientation = pt.LANDSCAPE # self._pagesize) # pt.pml_statics = self._statics # pt.pml_draw = self._draw # pt.pml_drawing = self._drawing # pt.pml_background = attrs.background # pt.pml_bgstory = self._bgstory c.templateList[name] = pt c.template = None c.frameList = [] c.frameStaticList = [] return {}, {}
def test_get_size_for_tuple(self): # TODO: This is a really strange case. Probably should not work this # way. res = getSize(("12", ".12")) self.assertEqual(res, 12.12)
def start(self, c): attr = self.attr log.debug("Parsing img tag, src: {}".format(attr.src)) log.debug("Attrs: {}".format(attr)) if attr.src and (not attr.src.notFound()): try: align = attr.align or c.frag.vAlign or "baseline" width = c.frag.width height = c.frag.height if attr.width: width = attr.width * dpi96 if attr.height: height = attr.height * dpi96 img = PmlImage(attr.src.getData(), width=None, height=None) img.pisaZoom = c.frag.zoom img.drawHeight *= dpi96 img.drawWidth *= dpi96 if (width is None) and (height is not None): factor = getSize(height, default=img.drawHeight) / img.drawHeight img.drawWidth *= factor img.drawHeight = getSize(height, default=img.drawHeight) elif (height is None) and (width is not None): factor = getSize(width, default=img.drawWidth) / img.drawWidth img.drawHeight *= factor img.drawWidth = getSize(width, default=img.drawWidth) elif (width is not None) and (height is not None): img.drawWidth = getSize(width, default=img.drawWidth) img.drawHeight = getSize(height, default=img.drawHeight) img.drawWidth *= img.pisaZoom img.drawHeight *= img.pisaZoom img.spaceBefore = c.frag.spaceBefore img.spaceAfter = c.frag.spaceAfter # print "image", id(img), img.drawWidth, img.drawHeight ''' TODO: - Apply styles - vspace etc. - Borders - Test inside tables ''' c.force = True if align in ["left", "right"]: c.image = img c.imageData = dict(align=align) else: # Important! Make sure that cbDefn is not inherited by other # fragments because of a bug in Reportlab! # afrag = c.frag.clone() valign = align if valign in ["texttop"]: valign = "top" elif valign in ["absmiddle"]: valign = "middle" elif valign in ["absbottom", "baseline"]: valign = "bottom" afrag = c.frag.clone() afrag.text = "" afrag.fontName = "Helvetica" # Fix for a nasty bug!!! afrag.cbDefn = ABag( kind="img", image=img, # .getImage(), # XXX Inline? valign=valign, fontName="Helvetica", fontSize=img.drawHeight, width=img.drawWidth, height=img.drawHeight) c.fragList.append(afrag) c.fontSize = img.drawHeight except Exception: # TODO: Kill catch-all log.warn(c.warning("Error in handling image"), exc_info=1) else: log.warn(c.warning("Need a valid file name!"))
def __init__(self, path, debug=0, capacity=-1): self.fontList = copy.copy(xhtml2pdf.default.DEFAULT_FONT) self.path = [] self.capacity = capacity self.node = None self.toc = PmlTableOfContents() self.story = [] self.indexing_story = None self.text = [] self.log = [] self.err = 0 self.warn = 0 self.text = u"" self.uidctr = 0 self.multiBuild = False self.pageSize = A4 self.template = None self.templateList = {} self.frameList = [] self.frameStatic = {} self.frameStaticList = [] self.pisaBackgroundList = [] self.keepInFrameIndex = None self.baseFontSize = getSize("12pt") self.anchorFrag = [] self.anchorName = [] self.tableData = None self.frag = self.fragBlock = getParaFrag(ParagraphStyle('default%d' % self.UID())) self.fragList = [] self.fragAnchor = [] self.fragStack = [] self.fragStrip = True self.listCounter = 0 self.cssText = "" self.cssDefaultText = "" self.image = None self.imageData = {} self.force = False self.pathCallback = None # External callback function for path calculations # Store path to document self.pathDocument = path or "__dummy__" parts = urlparse.urlparse(self.pathDocument) if not parts.scheme: self.pathDocument = os.path.abspath(self.pathDocument) self.pathDirectory = getDirName(self.pathDocument) self.meta = dict( author="", title="", subject="", keywords="", pagesize=A4, )
def atPage(self, name, pseudopage, declarations): c = self.c data = {} name = name or "body" pageBorder = None if declarations: result = self.ruleset([self.selector('*')], declarations) # print "@PAGE", name, pseudopage, declarations, result if declarations: data = result[0].values()[0] pageBorder = data.get("-pdf-frame-border", None) if name in c.templateList: log.warn( self.c.warning("template '%s' has already been defined", name)) if "-pdf-page-size" in data: c.pageSize = xhtml2pdf.default.PML_PAGESIZES.get( str(data["-pdf-page-size"]).lower(), c.pageSize) isLandscape = False if "size" in data: size = data["size"] # print size, c.pageSize if type(size) is not types.ListType: size = [size] sizeList = [] for value in size: valueStr = str(value).lower() if type(value) is types.TupleType: sizeList.append(getSize(value)) elif valueStr == "landscape": isLandscape = True elif valueStr in xhtml2pdf.default.PML_PAGESIZES: c.pageSize = xhtml2pdf.default.PML_PAGESIZES[valueStr] else: log.warn(c.warning("Unknown size value for @page")) if len(sizeList) == 2: c.pageSize = sizeList if isLandscape: c.pageSize = landscape(c.pageSize) for prop in ("margin-top", "margin-left", "margin-right", "margin-bottom", "top", "left", "right", "bottom", "width", "height"): if prop in data: c.frameList.append( self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize)) break # self._drawing = PmlPageDrawing(self._pagesize) #if not c.frameList: # c.warning("missing frame definitions for template") # return {}, {} # Frames have to be calculated after we know the pagesize frameList = [] staticList = [] for fname, static, border, x, y, w, h, fdata in c.frameList: #fix frame sizing problem. if static: x, y, w, h = getFrameDimensions(fdata, c.pageSize[0], c.pageSize[1]) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warn( self.c.warning( "Negative width or height of frame. Check @frame definitions." )) frame = Frame(x, y, w, h, id=fname, leftPadding=0, rightPadding=0, bottomPadding=0, topPadding=0, showBoundary=border or pageBorder) if static: frame.pisaStaticStory = [] c.frameStatic[static] = [frame] + c.frameStatic.get(static, []) staticList.append(frame) else: frameList.append(frame) background = data.get("background-image", None) if background: background = self.c.getFile(background) # print background # print frameList if not frameList: # print 999 log.warn( c.warning( "missing explicit frame definition for content or just static frames" )) fname, static, border, x, y, w, h, data = self._pisaAddFrame( name, data, first=True, border=pageBorder, size=c.pageSize) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warn( c.warning( "Negative width or height of frame. Check @page definitions." )) frameList.append( Frame(x, y, w, h, id=fname, leftPadding=0, rightPadding=0, bottomPadding=0, topPadding=0, showBoundary=border or pageBorder)) pt = PmlPageTemplate( id=name, frames=frameList, pagesize=c.pageSize, ) pt.pisaStaticList = staticList pt.pisaBackground = background pt.pisaBackgroundList = c.pisaBackgroundList if isLandscape: pt.pageorientation = pt.LANDSCAPE # self._pagesize) # pt.pml_statics = self._statics # pt.pml_draw = self._draw # pt.pml_drawing = self._drawing # pt.pml_background = attrs.background # pt.pml_bgstory = self._bgstory c.templateList[name] = pt c.template = None c.frameList = [] c.frameStaticList = [] return {}, {}
def addPara(self, force=False): # print self.force, repr(self.text) force = (force or self.force) self.force = False # Cleanup the trail try: rfragList = reversed(self.fragList) except: # For Python 2.3 compatibility rfragList = copy.copy(self.fragList) rfragList.reverse() #for frag in rfragList: # frag.text = frag.text.rstrip() # if frag.text: # break # Find maximum lead maxLeading = 0 #fontSize = 0 for frag in self.fragList: leading = getSize(frag.leadingSource, frag.fontSize) + frag.leadingSpace maxLeading = max(leading, frag.fontSize + frag.leadingSpace, maxLeading) frag.leading = leading if force or (self.text.strip() and self.fragList): # Strip trailing whitespaces #for f in self.fragList: # f.text = f.text.lstrip() # if f.text: # break #self.fragList[-1].lineBreak = self.fragList[-1].text.rstrip() # Update paragraph style by style of first fragment first = self.fragBlock style = self.toParagraphStyle(first) # style.leading = first.leading + first.leadingSpace if first.leadingSpace: style.leading = maxLeading else: style.leading = getSize(first.leadingSource, first.fontSize) + first.leadingSpace # style.leading = maxLeading # + first.leadingSpace #style.fontSize = fontSize # borderRadius: None, # print repr(self.text.strip()), style.leading, "".join([repr(x.text) for x in self.fragList]) # print first.leftIndent, first.listStyleType,repr(self.text) bulletText = copy.copy(first.bulletText) first.bulletText = None # Add paragraph to story if force or len(self.fragAnchor + self.fragList) > 0: # We need this empty fragment to work around problems in # Reportlab paragraphs regarding backGround etc. if self.fragList: self.fragList.append(self.fragList[ - 1].clone(text='')) else: blank = self.frag.clone() blank.fontName = "Helvetica" blank.text = '' self.fragList.append(blank) self.dumpPara(self.fragAnchor + self.fragList, style) para = PmlParagraph( self.text, style, frags=self.fragAnchor + self.fragList, bulletText=bulletText) # Mirrored and BIDI #import unicodedata #for c in self.text: # print unicodedata.bidirectional(c), para.outline = first.outline para.outlineLevel = first.outlineLevel para.outlineOpen = first.outlineOpen para.keepWithNext = first.keepWithNext para.autoLeading = "max" if self.image: para = PmlParagraphAndImage( para, self.image, side=self.imageData.get("align", "left")) self.addStory(para) self.fragAnchor = [] first.bulletText = None # Reset data self.image = None self.imageData = {} self.clearFrag()
def addPara(self, force=False): # print self.force, repr(self.text) force = (force or self.force) self.force = False # Cleanup the trail try: rfragList = reversed(self.fragList) except: # For Python 2.3 compatibility rfragList = copy.copy(self.fragList) rfragList.reverse() #for frag in rfragList: # frag.text = frag.text.rstrip() # if frag.text: # break # Find maximum lead maxLeading = 0 #fontSize = 0 for frag in self.fragList: leading = getSize(frag.leadingSource, frag.fontSize) + frag.leadingSpace maxLeading = max(leading, frag.fontSize + frag.leadingSpace, maxLeading) frag.leading = leading if force or (self.text.strip() and self.fragList): # Strip trailing whitespaces #for f in self.fragList: # f.text = f.text.lstrip() # if f.text: # break #self.fragList[-1].lineBreak = self.fragList[-1].text.rstrip() # Update paragraph style by style of first fragment first = self.fragBlock style = self.toParagraphStyle(first) # style.leading = first.leading + first.leadingSpace if first.leadingSpace: style.leading = maxLeading else: style.leading = getSize(first.leadingSource, first.fontSize) + first.leadingSpace # style.leading = maxLeading # + first.leadingSpace #style.fontSize = fontSize # borderRadius: None, # print repr(self.text.strip()), style.leading, "".join([repr(x.text) for x in self.fragList]) # print first.leftIndent, first.listStyleType,repr(self.text) bulletText = copy.copy(first.bulletText) first.bulletText = None # Add paragraph to story if force or len(self.fragAnchor + self.fragList) > 0: # We need this empty fragment to work around problems in # Reportlab paragraphs regarding backGround etc. if self.fragList: self.fragList.append(self.fragList[-1].clone(text='')) else: blank = self.frag.clone() blank.fontName = "Helvetica" blank.text = '' self.fragList.append(blank) self.dumpPara(self.fragAnchor + self.fragList, style) para = PmlParagraph(self.text, style, frags=self.fragAnchor + self.fragList, bulletText=bulletText) # Mirrored and BIDI #import unicodedata #for c in self.text: # print unicodedata.bidirectional(c), para.outline = first.outline para.outlineLevel = first.outlineLevel para.outlineOpen = first.outlineOpen para.keepWithNext = first.keepWithNext para.autoLeading = "max" if self.image: para = PmlParagraphAndImage(para, self.image, side=self.imageData.get( "align", "left")) self.addStory(para) self.fragAnchor = [] first.bulletText = None # Reset data self.image = None self.imageData = {} self.clearFrag()
def atPage(self, name, pseudopage, declarations): c = self.c data = {} name = name or "body" pageBorder = None if declarations: result = self.ruleset([self.selector('*')], declarations) if declarations: data = result[0].values()[0] pageBorder = data.get("-pdf-frame-border", None) if name in c.templateList: log.warn(self.c.warning("template '%s' has already been defined", name)) if "-pdf-page-size" in data: c.pageSize = xhtml2pdf.default.PML_PAGESIZES.get(str(data["-pdf-page-size"]).lower(), c.pageSize) isLandscape = False if "size" in data: size = data["size"] if type(size) is not types.ListType: size = [size] sizeList = [] for value in size: valueStr = str(value).lower() if type(value) is types.TupleType: sizeList.append(getSize(value)) elif valueStr == "landscape": isLandscape = True elif valueStr in xhtml2pdf.default.PML_PAGESIZES: c.pageSize = xhtml2pdf.default.PML_PAGESIZES[valueStr] else: log.warn(c.warning("Unknown size value for @page")) if len(sizeList) == 2: c.pageSize = tuple(sizeList) if isLandscape: c.pageSize = landscape(c.pageSize) padding_top = self._getFromData(data, 'padding-top', 0, getSize) padding_left = self._getFromData(data, 'padding-left', 0, getSize) padding_right = self._getFromData(data, 'padding-right', 0, getSize) padding_bottom = self._getFromData(data, 'padding-bottom', 0, getSize) border_color = self._getFromData(data, ('border-top-color', 'border-bottom-color',\ 'border-left-color', 'border-right-color'), None, getColor) border_width = self._getFromData(data, ('border-top-width', 'border-bottom-width',\ 'border-left-width', 'border-right-width'), 0, getSize) for prop in ("margin-top", "margin-left", "margin-right", "margin-bottom", "top", "left", "right", "bottom", "width", "height"): if prop in data: c.frameList.append(self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize)) break # Frames have to be calculated after we know the pagesize frameList = [] staticList = [] for fname, static, border, x, y, w, h, fdata in c.frameList: fpadding_top = self._getFromData(fdata, 'padding-top', padding_top, getSize) fpadding_left = self._getFromData(fdata, 'padding-left', padding_left, getSize) fpadding_right = self._getFromData(fdata, 'padding-right', padding_right, getSize) fpadding_bottom = self._getFromData(fdata, 'padding-bottom', padding_bottom, getSize) fborder_color = self._getFromData(fdata, ('border-top-color', 'border-bottom-color',\ 'border-left-color', 'border-right-color'), border_color, getColor) fborder_width = self._getFromData(fdata, ('border-top-width', 'border-bottom-width',\ 'border-left-width', 'border-right-width'), border_width, getSize) if border or pageBorder: frame_border = ShowBoundaryValue() else: frame_border = ShowBoundaryValue(color=fborder_color, width=fborder_width) #fix frame sizing problem. if static: x, y, w, h = getFrameDimensions(fdata, c.pageSize[0], c.pageSize[1]) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warn(self.c.warning("Negative width or height of frame. Check @frame definitions.")) frame = Frame( x, y, w, h, id=fname, leftPadding=fpadding_left, rightPadding=fpadding_right, bottomPadding=fpadding_bottom, topPadding=fpadding_top, showBoundary=frame_border) if static: frame.pisaStaticStory = [] c.frameStatic[static] = [frame] + c.frameStatic.get(static, []) staticList.append(frame) else: frameList.append(frame) background = data.get("background-image", None) if background: #should be relative to the css file background = self.c.getFile(background, relative=self.c.cssParser.rootPath) if not frameList: log.warn(c.warning("missing explicit frame definition for content or just static frames")) fname, static, border, x, y, w, h, data = self._pisaAddFrame(name, data, first=True, border=pageBorder, size=c.pageSize) x, y, w, h = getCoords(x, y, w, h, c.pageSize) if w <= 0 or h <= 0: log.warn(c.warning("Negative width or height of frame. Check @page definitions.")) if border or pageBorder: frame_border = ShowBoundaryValue() else: frame_border = ShowBoundaryValue(color=border_color, width=border_width) frameList.append(Frame( x, y, w, h, id=fname, leftPadding=padding_left, rightPadding=padding_right, bottomPadding=padding_bottom, topPadding=padding_top, showBoundary=frame_border)) pt = PmlPageTemplate( id=name, frames=frameList, pagesize=c.pageSize, ) pt.pisaStaticList = staticList pt.pisaBackground = background pt.pisaBackgroundList = c.pisaBackgroundList if isLandscape: pt.pageorientation = pt.LANDSCAPE c.templateList[name] = pt c.template = None c.frameList = [] c.frameStaticList = [] return {}, {}
def CSS2Frag(c, kw, isBlock): def safeGetColor(color, default = None): try: return getColor(color) except ValueError: # the css parser is responsible for calculating of inherited values so inherit do not work here return getColor(default) # COLORS if c.cssAttr.has_key("color"): c.frag.textColor = safeGetColor(c.cssAttr["color"], default="#000000") if c.cssAttr.has_key("background-color"): c.frag.backColor = safeGetColor(c.cssAttr["background-color"], default="#ffffff") # FONT SIZE, STYLE, WEIGHT if c.cssAttr.has_key("font-family"): c.frag.fontName = c.getFontName(c.cssAttr["font-family"]) if c.cssAttr.has_key("font-size"): # XXX inherit c.frag.fontSize = max(getSize("".join(c.cssAttr["font-size"]), c.frag.fontSize, c.baseFontSize), 1.0) if c.cssAttr.has_key("line-height"): leading = "".join(c.cssAttr["line-height"]) c.frag.leading = getSize(leading, c.frag.fontSize) c.frag.leadingSource = leading else: c.frag.leading = getSize(c.frag.leadingSource, c.frag.fontSize) if c.cssAttr.has_key("-pdf-line-spacing"): c.frag.leadingSpace = getSize("".join(c.cssAttr["-pdf-line-spacing"])) # print "line-spacing", c.cssAttr["-pdf-line-spacing"], c.frag.leading if c.cssAttr.has_key("font-weight"): value = c.cssAttr["font-weight"].lower() if value in ("bold", "bolder", "500", "600", "700", "800", "900"): c.frag.bold = 1 else: c.frag.bold = 0 for value in toList(c.cssAttr.get("text-decoration", "")): if "underline" in value: c.frag.underline = 1 if "line-through" in value: c.frag.strike = 1 if "none" in value: c.frag.underline = 0 c.frag.strike = 0 if c.cssAttr.has_key("font-style"): value = c.cssAttr["font-style"].lower() if value in ("italic", "oblique"): c.frag.italic = 1 else: c.frag.italic = 0 if c.cssAttr.has_key("white-space"): # normal | pre | nowrap c.frag.whiteSpace = str(c.cssAttr["white-space"]).lower() # ALIGN & VALIGN if c.cssAttr.has_key("text-align"): c.frag.alignment = getAlign(c.cssAttr["text-align"]) if c.cssAttr.has_key("vertical-align"): c.frag.vAlign = c.cssAttr["vertical-align"] # HEIGHT & WIDTH if c.cssAttr.has_key("height"): c.frag.height = "".join(toList(c.cssAttr["height"])) # XXX Relative is not correct! if c.frag.height in ("auto",): c.frag.height = None if c.cssAttr.has_key("width"): # print c.cssAttr["width"] c.frag.width = "".join(toList(c.cssAttr["width"])) # XXX Relative is not correct! if c.frag.width in ("auto",): c.frag.width = None # ZOOM if c.cssAttr.has_key("zoom"): # print c.cssAttr["width"] zoom = "".join(toList(c.cssAttr["zoom"])) # XXX Relative is not correct! if zoom.endswith("%"): zoom = float(zoom[: - 1]) / 100.0 c.frag.zoom = float(zoom) # MARGINS & LIST INDENT, STYLE if isBlock: if c.cssAttr.has_key("margin-top"): c.frag.spaceBefore = getSize(c.cssAttr["margin-top"], c.frag.fontSize) if c.cssAttr.has_key("margin-bottom"): c.frag.spaceAfter = getSize(c.cssAttr["margin-bottom"], c.frag.fontSize) if c.cssAttr.has_key("margin-left"): c.frag.bulletIndent = kw["margin-left"] # For lists kw["margin-left"] += getSize(c.cssAttr["margin-left"], c.frag.fontSize) c.frag.leftIndent = kw["margin-left"] # print "MARGIN LEFT", kw["margin-left"], c.frag.bulletIndent if c.cssAttr.has_key("margin-right"): kw["margin-right"] += getSize(c.cssAttr["margin-right"], c.frag.fontSize) c.frag.rightIndent = kw["margin-right"] # print c.frag.rightIndent if c.cssAttr.has_key("text-indent"): c.frag.firstLineIndent = getSize(c.cssAttr["text-indent"], c.frag.fontSize) if c.cssAttr.has_key("list-style-type"): c.frag.listStyleType = str(c.cssAttr["list-style-type"]).lower() if c.cssAttr.has_key("list-style-image"): c.frag.listStyleImage = c.getFile(c.cssAttr["list-style-image"]) # PADDINGS if isBlock: if c.cssAttr.has_key("padding-top"): c.frag.paddingTop = getSize(c.cssAttr["padding-top"], c.frag.fontSize) if c.cssAttr.has_key("padding-bottom"): c.frag.paddingBottom = getSize(c.cssAttr["padding-bottom"], c.frag.fontSize) if c.cssAttr.has_key("padding-left"): c.frag.paddingLeft = getSize(c.cssAttr["padding-left"], c.frag.fontSize) if c.cssAttr.has_key("padding-right"): c.frag.paddingRight = getSize(c.cssAttr["padding-right"], c.frag.fontSize) # BORDERS if isBlock: if c.cssAttr.has_key("border-top-width"): c.frag.borderTopWidth = getSize(c.cssAttr["border-top-width"], c.frag.fontSize) if c.cssAttr.has_key("border-bottom-width"): c.frag.borderBottomWidth = getSize(c.cssAttr["border-bottom-width"], c.frag.fontSize) if c.cssAttr.has_key("border-left-width"): c.frag.borderLeftWidth = getSize(c.cssAttr["border-left-width"], c.frag.fontSize) if c.cssAttr.has_key("border-right-width"): c.frag.borderRightWidth = getSize(c.cssAttr["border-right-width"], c.frag.fontSize) if c.cssAttr.has_key("border-top-style"): c.frag.borderTopStyle = c.cssAttr["border-top-style"] if c.cssAttr.has_key("border-bottom-style"): c.frag.borderBottomStyle = c.cssAttr["border-bottom-style"] if c.cssAttr.has_key("border-left-style"): c.frag.borderLeftStyle = c.cssAttr["border-left-style"] if c.cssAttr.has_key("border-right-style"): c.frag.borderRightStyle = c.cssAttr["border-right-style"] if c.cssAttr.has_key("border-top-color"): c.frag.borderTopColor = safeGetColor(c.cssAttr["border-top-color"], default="#ffffff") if c.cssAttr.has_key("border-bottom-color"): c.frag.borderBottomColor = safeGetColor(c.cssAttr["border-bottom-color"], default="#ffffff") if c.cssAttr.has_key("border-left-color"): c.frag.borderLeftColor = safeGetColor(c.cssAttr["border-left-color"], default="#ffffff") if c.cssAttr.has_key("border-right-color"): c.frag.borderRightColor = safeGetColor(c.cssAttr["border-right-color"], default="#ffffff")
def CSS2Frag(c, kw, isBlock): # COLORS if "color" in c.cssAttr: c.frag.textColor = getColor(c.cssAttr["color"]) if "background-color" in c.cssAttr: c.frag.backColor = getColor(c.cssAttr["background-color"]) # FONT SIZE, STYLE, WEIGHT if "font-family" in c.cssAttr: c.frag.fontName = c.getFontName(c.cssAttr["font-family"]) if "font-size" in c.cssAttr: # XXX inherit c.frag.fontSize = max( getSize("".join(c.cssAttr["font-size"]), c.frag.fontSize, c.baseFontSize), 1.0) if "line-height" in c.cssAttr: leading = "".join(c.cssAttr["line-height"]) c.frag.leading = getSize(leading, c.frag.fontSize) c.frag.leadingSource = leading else: c.frag.leading = getSize(c.frag.leadingSource, c.frag.fontSize) if "letter-spacing" in c.cssAttr: c.frag.letterSpacing = c.cssAttr["letter-spacing"] if "-pdf-line-spacing" in c.cssAttr: c.frag.leadingSpace = getSize("".join(c.cssAttr["-pdf-line-spacing"])) # print "line-spacing", c.cssAttr["-pdf-line-spacing"], c.frag.leading if "font-weight" in c.cssAttr: value = lower(c.cssAttr["font-weight"]) if value in ("bold", "bolder", "500", "600", "700", "800", "900"): c.frag.bold = 1 else: c.frag.bold = 0 for value in toList(c.cssAttr.get("text-decoration", "")): if "underline" in value: c.frag.underline = 1 if "line-through" in value: c.frag.strike = 1 if "none" in value: c.frag.underline = 0 c.frag.strike = 0 if "font-style" in c.cssAttr: value = lower(c.cssAttr["font-style"]) if value in ("italic", "oblique"): c.frag.italic = 1 else: c.frag.italic = 0 if "white-space" in c.cssAttr: # normal | pre | nowrap c.frag.whiteSpace = str(c.cssAttr["white-space"]).lower() # ALIGN & VALIGN if "text-align" in c.cssAttr: c.frag.alignment = getAlign(c.cssAttr["text-align"]) if "vertical-align" in c.cssAttr: c.frag.vAlign = c.cssAttr["vertical-align"] # HEIGHT & WIDTH if "height" in c.cssAttr: try: c.frag.height = "".join(toList( c.cssAttr["height"])) # XXX Relative is not correct! except TypeError: # sequence item 0: expected string, tuple found c.frag.height = "".join(toList(c.cssAttr["height"][0])) if c.frag.height in ("auto", ): c.frag.height = None if "width" in c.cssAttr: try: c.frag.width = "".join(toList( c.cssAttr["width"])) # XXX Relative is not correct! except TypeError: c.frag.width = "".join(toList(c.cssAttr["width"][0])) if c.frag.width in ("auto", ): c.frag.width = None # ZOOM if "zoom" in c.cssAttr: zoom = "".join(toList( c.cssAttr["zoom"])) # XXX Relative is not correct! if zoom.endswith("%"): zoom = float(zoom[:-1]) / 100.0 c.frag.zoom = float(zoom) # MARGINS & LIST INDENT, STYLE if isBlock: if "margin-top" in c.cssAttr: c.frag.spaceBefore = getSize(c.cssAttr["margin-top"], c.frag.fontSize) if "margin-bottom" in c.cssAttr: c.frag.spaceAfter = getSize(c.cssAttr["margin-bottom"], c.frag.fontSize) if "margin-left" in c.cssAttr: c.frag.bulletIndent = kw["margin-left"] # For lists kw["margin-left"] += getSize(c.cssAttr["margin-left"], c.frag.fontSize) c.frag.leftIndent = kw["margin-left"] if "margin-right" in c.cssAttr: kw["margin-right"] += getSize(c.cssAttr["margin-right"], c.frag.fontSize) c.frag.rightIndent = kw["margin-right"] if "text-indent" in c.cssAttr: c.frag.firstLineIndent = getSize(c.cssAttr["text-indent"], c.frag.fontSize) if "list-style-type" in c.cssAttr: c.frag.listStyleType = str(c.cssAttr["list-style-type"]).lower() if "list-style-image" in c.cssAttr: c.frag.listStyleImage = c.getFile(c.cssAttr["list-style-image"]) # PADDINGS if isBlock: if "padding-top" in c.cssAttr: c.frag.paddingTop = getSize(c.cssAttr["padding-top"], c.frag.fontSize) if "padding-bottom" in c.cssAttr: c.frag.paddingBottom = getSize(c.cssAttr["padding-bottom"], c.frag.fontSize) if "padding-left" in c.cssAttr: c.frag.paddingLeft = getSize(c.cssAttr["padding-left"], c.frag.fontSize) if "padding-right" in c.cssAttr: c.frag.paddingRight = getSize(c.cssAttr["padding-right"], c.frag.fontSize) # BORDERS if isBlock: if "border-top-width" in c.cssAttr: c.frag.borderTopWidth = getSize(c.cssAttr["border-top-width"], c.frag.fontSize) if "border-bottom-width" in c.cssAttr: c.frag.borderBottomWidth = getSize( c.cssAttr["border-bottom-width"], c.frag.fontSize) if "border-left-width" in c.cssAttr: c.frag.borderLeftWidth = getSize(c.cssAttr["border-left-width"], c.frag.fontSize) if "border-right-width" in c.cssAttr: c.frag.borderRightWidth = getSize(c.cssAttr["border-right-width"], c.frag.fontSize) if "border-top-style" in c.cssAttr: c.frag.borderTopStyle = c.cssAttr["border-top-style"] if "border-bottom-style" in c.cssAttr: c.frag.borderBottomStyle = c.cssAttr["border-bottom-style"] if "border-left-style" in c.cssAttr: c.frag.borderLeftStyle = c.cssAttr["border-left-style"] if "border-right-style" in c.cssAttr: c.frag.borderRightStyle = c.cssAttr["border-right-style"] if "border-top-color" in c.cssAttr: c.frag.borderTopColor = getColor(c.cssAttr["border-top-color"]) if "border-bottom-color" in c.cssAttr: c.frag.borderBottomColor = getColor( c.cssAttr["border-bottom-color"]) if "border-left-color" in c.cssAttr: c.frag.borderLeftColor = getColor(c.cssAttr["border-left-color"]) if "border-right-color" in c.cssAttr: c.frag.borderRightColor = getColor(c.cssAttr["border-right-color"])
def pisaLoop(node, context, path=None, **kw): if path is None: path = [] # Initialize KW if not kw: kw = { "margin-top": 0, "margin-bottom": 0, "margin-left": 0, "margin-right": 0, } else: kw = copy.copy(kw) #indent = len(path) * " " # only used for debug print statements # TEXT if node.nodeType == Node.TEXT_NODE: # print indent, "#", repr(node.data) #, context.frag context.addFrag(node.data) # context.text.append(node.value) # ELEMENT elif node.nodeType == Node.ELEMENT_NODE: node.tagName = node.tagName.replace(":", "").lower() if node.tagName in ("style", "script"): return path = copy.copy(path) + [node.tagName] # Prepare attributes attr = pisaGetAttributes(context, node.tagName, node.attributes) #log.debug(indent + "<%s %s>" % (node.tagName, attr) + repr(node.attributes.items())) #, path # Calculate styles context.cssAttr = CSSCollect(node, context) context.cssAttr = mapNonStandardAttrs(context.cssAttr, node, attr) context.node = node # Block? PAGE_BREAK = 1 PAGE_BREAK_RIGHT = 2 PAGE_BREAK_LEFT = 3 pageBreakAfter = False frameBreakAfter = False display = lower(context.cssAttr.get("display", "inline")) # print indent, node.tagName, display, context.cssAttr.get("background-color", None), attr isBlock = (display == "block") if isBlock: context.addPara() # Page break by CSS if "-pdf-next-page" in context.cssAttr: context.addStory( NextPageTemplate(str(context.cssAttr["-pdf-next-page"]))) if "-pdf-page-break" in context.cssAttr: if str(context.cssAttr["-pdf-page-break"]).lower() == "before": context.addStory(PageBreak()) if "-pdf-frame-break" in context.cssAttr: if str(context.cssAttr["-pdf-frame-break"]).lower( ) == "before": context.addStory(FrameBreak()) if str(context.cssAttr["-pdf-frame-break"]).lower() == "after": frameBreakAfter = True if "page-break-before" in context.cssAttr: if str(context.cssAttr["page-break-before"]).lower( ) == "always": context.addStory(PageBreak()) if str(context.cssAttr["page-break-before"]).lower( ) == "right": context.addStory(PageBreak()) context.addStory(PmlRightPageBreak()) if str(context.cssAttr["page-break-before"]).lower() == "left": context.addStory(PageBreak()) context.addStory(PmlLeftPageBreak()) if "page-break-after" in context.cssAttr: if str(context.cssAttr["page-break-after"]).lower( ) == "always": pageBreakAfter = PAGE_BREAK if str(context.cssAttr["page-break-after"]).lower() == "right": pageBreakAfter = PAGE_BREAK_RIGHT if str(context.cssAttr["page-break-after"]).lower() == "left": pageBreakAfter = PAGE_BREAK_LEFT if display == "none": # print "none!" return # Translate CSS to frags # Save previous frag styles context.pushFrag() # Map styles to Reportlab fragment properties CSS2Frag(context, kw, isBlock) # EXTRAS if "-pdf-keep-with-next" in context.cssAttr: context.frag.keepWithNext = getBool( context.cssAttr["-pdf-keep-with-next"]) if "-pdf-outline" in context.cssAttr: context.frag.outline = getBool(context.cssAttr["-pdf-outline"]) if "-pdf-outline-level" in context.cssAttr: context.frag.outlineLevel = int( context.cssAttr["-pdf-outline-level"]) if "-pdf-outline-open" in context.cssAttr: context.frag.outlineOpen = getBool( context.cssAttr["-pdf-outline-open"]) if "-pdf-word-wrap" in context.cssAttr: context.frag.wordWrap = context.cssAttr["-pdf-word-wrap"] # handle keep-in-frame keepInFrameMode = None keepInFrameMaxWidth = 0 keepInFrameMaxHeight = 0 if "-pdf-keep-in-frame-mode" in context.cssAttr: value = str( context.cssAttr["-pdf-keep-in-frame-mode"]).strip().lower() if value in ("shrink", "error", "overflow", "truncate"): keepInFrameMode = value if "-pdf-keep-in-frame-max-width" in context.cssAttr: keepInFrameMaxWidth = getSize("".join( context.cssAttr["-pdf-keep-in-frame-max-width"])) if "-pdf-keep-in-frame-max-height" in context.cssAttr: keepInFrameMaxHeight = getSize("".join( context.cssAttr["-pdf-keep-in-frame-max-height"])) # ignore nested keep-in-frames, tables have their own KIF handling keepInFrame = keepInFrameMode is not None and context.keepInFrameIndex is None if keepInFrame: # keep track of current story index, so we can wrap everythink # added after this point in a KeepInFrame context.keepInFrameIndex = len(context.story) # BEGIN tag klass = globals().get( "pisaTag%s" % node.tagName.replace(":", "").upper(), None) obj = None # Static block elementId = attr.get("id", None) staticFrame = context.frameStatic.get(elementId, None) if staticFrame: context.frag.insideStaticFrame += 1 oldStory = context.swapStory() # Tag specific operations if klass is not None: obj = klass(node, attr) obj.start(context) # Visit child nodes context.fragBlock = fragBlock = copy.copy(context.frag) for nnode in node.childNodes: pisaLoop(nnode, context, path, **kw) context.fragBlock = fragBlock # END tag if obj: obj.end(context) # Block? if isBlock: context.addPara() # XXX Buggy! # Page break by CSS if pageBreakAfter: context.addStory(PageBreak()) if pageBreakAfter == PAGE_BREAK_RIGHT: context.addStory(PmlRightPageBreak()) if pageBreakAfter == PAGE_BREAK_LEFT: context.addStory(PmlLeftPageBreak()) if frameBreakAfter: context.addStory(FrameBreak()) if keepInFrame: # get all content added after start of -pdf-keep-in-frame and wrap # it in a KeepInFrame substory = context.story[context.keepInFrameIndex:] context.story = context.story[:context.keepInFrameIndex] context.story.append( KeepInFrame(content=substory, maxWidth=keepInFrameMaxWidth, maxHeight=keepInFrameMaxHeight)) context.keepInFrameIndex = None # Static block, END if staticFrame: context.addPara() for frame in staticFrame: frame.pisaStaticStory = context.story context.swapStory(oldStory) context.frag.insideStaticFrame -= 1 # context.debug(1, indent, "</%s>" % (node.tagName)) # Reset frag style context.pullFrag() # Unknown or not handled else: # context.debug(1, indent, "???", node, node.nodeType, repr(node)) # Loop over children for node in node.childNodes: pisaLoop(node, context, path, **kw)
def start(self, c): attr = self.attr if attr.src and (not attr.src.notFound()): try: align = attr.align or c.frag.vAlign or "baseline" width = c.frag.width height = c.frag.height if attr.width: width = attr.width * dpi96 if attr.height: height = attr.height * dpi96 img = PmlImage( attr.src.getData(), width=None, height=None) img.pisaZoom = c.frag.zoom img.drawHeight *= dpi96 img.drawWidth *= dpi96 if (width is None) and (height is not None): factor = getSize(height) / img.drawHeight img.drawWidth *= factor img.drawHeight = getSize(height) elif (height is None) and (width is not None): factor = getSize(width) / img.drawWidth img.drawHeight *= factor img.drawWidth = getSize(width) elif (width is not None) and (height is not None): img.drawWidth = getSize(width) img.drawHeight = getSize(height) img.drawWidth *= img.pisaZoom img.drawHeight *= img.pisaZoom img.spaceBefore = c.frag.spaceBefore img.spaceAfter = c.frag.spaceAfter # print "image", id(img), img.drawWidth, img.drawHeight ''' TODO: - Apply styles - vspace etc. - Borders - Test inside tables ''' c.force = True if align in ["left", "right"]: c.image = img c.imageData = dict( align=align ) else: # Important! Make sure that cbDefn is not inherited by other # fragments because of a bug in Reportlab! # afrag = c.frag.clone() valign = align if valign in ["texttop"]: valign = "top" elif valign in ["absmiddle"]: valign = "middle" elif valign in ["absbottom", "baseline"]: valign = "bottom" afrag = c.frag.clone() afrag.text = "" afrag.fontName = "Helvetica" # Fix for a nasty bug!!! afrag.cbDefn = ABag( kind="img", image=img, # .getImage(), # XXX Inline? valign=valign, fontName="Helvetica", fontSize=img.drawHeight, width=img.drawWidth, height=img.drawHeight) c.fragList.append(afrag) c.fontSize = img.drawHeight except Exception: # TODO: Kill catch-all log.warn(c.warning("Error in handling image"), exc_info=1) else: log.warn(c.warning("Need a valid file name!"))
def pisaGetAttributes(c, tag, attributes): global TAGS attrs = {} if attributes: for k, v in attributes.items(): try: attrs[str(k)] = str( v) # XXX no Unicode! Reportlab fails with template names except: attrs[k] = v nattrs = {} if tag in TAGS: block, adef = TAGS[tag] adef["id"] = STRING # print block, adef try: iteritems = adef.iteritems() except Exception: iteritems = iter(adef.items()) for k, v in iteritems: nattrs[k] = None # print k, v # defaults, wenn vorhanden if type(v) == tuple: if v[1] == MUST: if k not in attrs: log.warn(c.warning("Attribute '%s' must be set!", k)) nattrs[k] = None continue nv = attrs.get(k, v[1]) dfl = v[1] v = v[0] else: nv = attrs.get(k, None) dfl = None if nv is not None: if type(v) == list: nv = nv.strip().lower() if nv not in v: #~ raise PML_EXCEPTION, "attribute '%s' of wrong value, allowed is one of: %s" % (k, repr(v)) log.warn( c.warning( "Attribute '%s' of wrong value, allowed is one of: %s", k, repr(v))) nv = dfl elif v == BOOL: nv = nv.strip().lower() nv = nv in ("1", "y", "yes", "true", str(k)) elif v == SIZE: try: nv = getSize(nv) except: log.warn( c.warning("Attribute '%s' expects a size value", k)) elif v == BOX: nv = getBox(nv, c.pageSize) elif v == POS: nv = getPos(nv, c.pageSize) elif v == INT: nv = int(nv) elif v == COLOR: nv = getColor(nv) elif v == FILE: nv = c.getFile(nv) elif v == FONT: nv = c.getFontName(nv) nattrs[k] = nv return AttrContainer(nattrs)
def addPara(self, force=False): force = (force or self.force) self.force = False # Cleanup the trail try: rfragList = reversed(self.fragList) except: # For Python 2.3 compatibility rfragList = copy.copy(self.fragList) rfragList.reverse() # Find maximum lead maxLeading = 0 #fontSize = 0 for frag in self.fragList: leading = getSize(frag.leadingSource, frag.fontSize) + frag.leadingSpace maxLeading = max(leading, frag.fontSize + frag.leadingSpace, maxLeading) frag.leading = leading if force or (self.text.strip() and self.fragList): # Update paragraph style by style of first fragment first = self.fragBlock style = self.toParagraphStyle(first) # style.leading = first.leading + first.leadingSpace if first.leadingSpace: style.leading = maxLeading else: style.leading = getSize(first.leadingSource, first.fontSize) + first.leadingSpace bulletText = copy.copy(first.bulletText) first.bulletText = None # Add paragraph to story if force or len(self.fragAnchor + self.fragList) > 0: # We need this empty fragment to work around problems in # Reportlab paragraphs regarding backGround etc. if self.fragList: self.fragList.append(self.fragList[- 1].clone(text='')) else: blank = self.frag.clone() blank.fontName = "Helvetica" blank.text = '' self.fragList.append(blank) self.dumpPara(self.fragAnchor + self.fragList, style) para = PmlParagraph( self.text, style, frags=self.fragAnchor + self.fragList, bulletText=bulletText) para.outline = first.outline para.outlineLevel = first.outlineLevel para.outlineOpen = first.outlineOpen para.keepWithNext = first.keepWithNext para.autoLeading = "max" if self.image: para = PmlParagraphAndImage( para, self.image, side=self.imageData.get("align", "left")) self.addStory(para) self.fragAnchor = [] first.bulletText = None # Reset data self.image = None self.imageData = {} self.clearFrag()
""" @param c pisaContext @param kw dict @param isBlock boolean """ # COLORS if "color" in c.cssAttr: c.frag.textColor = getColor(c.cssAttr["color"]) if "background-color" in c.cssAttr: c.frag.backColor = getColor(c.cssAttr["background-color"]) # FONT SIZE, STYLE, WEIGHT if "font-family" in c.cssAttr: c.frag.fontName = c.getFontName(c.cssAttr["font-family"]) if "font-size" in c.cssAttr: # XXX inherit c.frag.fontSize = max(getSize("".join(c.cssAttr["font-size"]), c.frag.fontSize, c.baseFontSize), 1.0) if "line-height" in c.cssAttr: leading = "".join(c.cssAttr["line-height"]) c.frag.leading = getSize(leading, c.frag.fontSize) c.frag.leadingSource = leading else: c.frag.leading = getSize(c.frag.leadingSource, c.frag.fontSize) if "-pdf-line-spacing" in c.cssAttr: c.frag.leadingSpace = getSize("".join(c.cssAttr["-pdf-line-spacing"])) # print "line-spacing", c.cssAttr["-pdf-line-spacing"], c.frag.leading if "font-weight" in c.cssAttr: value = c.cssAttr["font-weight"].lower() if value in ("bold", "bolder", "500", "600", "700", "800", "900"): c.frag.bold = 1 else: c.frag.bold = 0