def setFillColor(self, aColor, alpha=None): """Takes a color object, allowing colors to be referred to by name""" if self._enforceColorSpace: aColor = self._enforceColorSpace(aColor) if isinstance(aColor, CMYKColor): d = aColor.density c,m,y,k = (d*aColor.cyan, d*aColor.magenta, d*aColor.yellow, d*aColor.black) self._fillColorObj = aColor name = self._checkSeparation(aColor) if name: self._code.append('/%s cs %s scn' % (name,fp_str(d))) else: self._code.append('%s k' % fp_str(c, m, y, k)) elif isinstance(aColor, Color): rgb = (aColor.red, aColor.green, aColor.blue) self._fillColorObj = aColor self._code.append('%s rg' % fp_str(rgb) ) elif isinstance(aColor,(tuple,list)): l = len(aColor) if l==3: self._fillColorObj = aColor self._code.append('%s rg' % fp_str(aColor) ) elif l==4: self._fillColorObj = aColor self._code.append('%s k' % fp_str(aColor)) else: raise ValueError('Unknown color %r' % aColor) elif isStr(aColor): self.setFillColor(toColor(aColor)) else: raise ValueError('Unknown color %r' % aColor) if alpha is not None: self.setFillAlpha(alpha) elif getattr(aColor, 'alpha', None) is not None: self.setFillAlpha(aColor.alpha)
def circleArcStream(size, r, arcs=(0,1,2,3), rotated=False): R = [].append rlen = R.__self__.__len__ hsize = size * 0.5 f = size / 20.0 size *= f hsize *= f r *= f cp = fp_str(0.55231 * r) r = fp_str(r) hsize = fp_str(hsize) mx = '0.7071 0.7071 -0.7071 0.7071' if rotated else '1 0 0 1' R('%(mx)s %(hsize)s %(hsize)s cm') if 0 in arcs: if rlen()==1: R('%(r)s 0 m') R('%(r)s %(cp)s %(cp)s %(r)s 0 %(r)s c') if 1 in arcs: if rlen()==1: R('0 %(r)s m') R('-%(cp)s %(r)s -%(r)s %(cp)s -%(r)s 0 c') if 2 in arcs: if rlen()==1: R('-%(r)s 0 m') R('-%(r)s -%(cp)s -%(cp)s -%(r)s 0 -%(r)s c') if 3 in arcs: if rlen()==1: R('0 -%(r)s m') R('%(cp)s -%(r)s %(r)s -%(cp)s %(r)s 0 c') return '\n'.join(R.__self__) % vars()
def _issueT1String(self,fontObj,x,y,s): fc = fontObj code_append = self.code_append fontSize = self._fontSize fontsUsed = self._fontsUsed escape = self._escape if not isUnicode(s): try: s = s.decode('utf8') except UnicodeDecodeError as e: i,j = e.args[2:4] raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],s[i-10:i],s[i:j],s[j:j+10]),))) for f, t in unicode2T1(s,[fontObj]+fontObj.substitutionFonts): if f!=fc: psName = asNative(f.face.name) code_append('(%s) findfont %s scalefont setfont' % (psName,fp_str(fontSize))) if psName not in fontsUsed: fontsUsed.append(psName) fc = f code_append('%s m (%s) show ' % (fp_str(x,y),escape(t))) x += f.stringWidth(t.decode(f.encName),fontSize) if fontObj!=fc: self._font = None self.setFont(fontObj.face.name,fontSize)
def __repr__(self): return "%s(%s%s%s%s%s)" % (self.__class__.__name__, fp_str(self.cyan*100, self.magenta*100, self.yellow*100, self.black*100).replace(' ',','), (self.spotName and (',spotName='+repr(self.spotName)) or ''), (self.density!=1 and (',density='+fp_str(self.density*100)) or ''), (self.knockout is not None and (',knockout=%d' % self.knockout) or ''), (self.alpha is not None and (',alpha=%s' % (fp_str(self.alpha*100))) or ''), )
def setColor(self, color): if self._color!=color: self._color = color if color: if hasattr(color, "cyan"): self.code_append('%s setcmykcolor' % fp_str(color.cyan, color.magenta, color.yellow, color.black)) else: self.code_append('%s setrgbcolor' % fp_str(color.red, color.green, color.blue))
def setTextOrigin(self, x, y): if self._canvas.bottomup: self._code.append('1 0 0 1 %s Tm' % fp_str(x, y)) #bottom up else: self._code.append('1 0 0 -1 %s Tm' % fp_str(x, y)) #top down # The current cursor position is at the text origin self._x0 = self._x = x self._y0 = self._y = y
def lines(self, lineList, color=None, width=None): # print "### lineList", lineList return if self._strokeColor != None: self._setColor(self._strokeColor) codeline = '%s m %s l stroke' for line in lineList: self.code.append(codeline % (fp_str(line[0]), fp_str(line[1])))
def drawCurve(self, x1, y1, x2, y2, x3, y3, x4, y4, closed=0): codeline = '%s m %s curveto' data = (fp_str(x1, y1), fp_str(x2, y2, x3, y3, x4, y4)) if self._fillColor != None: self.setColor(self._fillColor) self.code_append((codeline % data) + ' eofill') if self._strokeColor != None: self.setColor(self._strokeColor) self.code_append((codeline % data) + ((closed and ' closepath') or '') + ' stroke')
def ttf2ps(font, doc): """ create analytic fonts for inclusion in a postscript document """ state = font._assignState(doc,asciiReadable=False,namePrefix='.RLF') state.frozen = 1 PS = [] unitsPerEm = font.face.unitsPerEm scale = lambda x: int(x*unitsPerEm/1000. + 0.1) _fontBBox = list(map(scale,font.face.bbox)) fontBBox = fp_str(*_fontBBox) for i,subset in enumerate(state.subsets): n = len(subset) psName = font.getSubsetInternalName(i,doc)[1:] metrics = [] bboxes = [] chardefs = [] charmaps = [] nglyphs = 0 for c in range(n): g = subset[c] if g==32 and g!=c: continue u = uniChr(g).encode('utf8') try: P = u2P(font,u) except: P = [] nglyphs += 1 #if c==0 and g==0: # P=[('moveTo', 30, 1473), ('lineTo', 30, 0), ('lineTo', 603, 0),('lineTo',603,1473), 'closePath',('moveTo',40,1463),('lineTo',593,1463),('lineTo',593,10),('lineTo',40,10),'closePath'] #else: # continue gn = glyphName(c) if g==0 and c==0: uw = 633 else: uw = font.stringWidth(u,unitsPerEm) if P: bb = definePath(P).getBounds() else: bb = [0,0,uw,0] bboxes.append('/%s [%s] def' % (gn,fp_str(*bb))) metrics.append('/%s %s def' % (gn, fp_str(uw))) chardefs.append(P2PSDef(c,P)) charmaps.append(char2glyph(c,c==n-1)) if nglyphs<=0: continue metrics = '\n'.join(metrics) chardefs = '\n'.join(chardefs) charmaps = '\n'.join(charmaps) bboxes = '\n'.join(bboxes) uid = rl_config.eps_ttf_embed_uid and getUID(doc,metrics+chardefs+charmaps+bboxes+str(unitsPerEm)+fontBBox) or '' PS.append(_template % locals()) return '\n'.join(PS) del font.state[doc]
def setColor(self, color): if self._color != color: self._color = color if color: if hasattr(color, "cyan"): self.code_append('%s setcmykcolor' % fp_str( color.cyan, color.magenta, color.yellow, color.black)) else: self.code_append( '%s setrgbcolor' % fp_str(color.red, color.green, color.blue))
def __repr__(self): return "%s(%s%s%s%s%s)" % ( self.__class__.__name__, fp_str(self.cyan, self.magenta, self.yellow, self.black).replace( ' ', ','), (self.spotName and (',spotName=' + repr(self.spotName)) or ''), (self.density != 1 and (',density=' + fp_str(self.density)) or ''), (self.knockout is not None and (',knockout=%d' % self.knockout) or ''), (self.alpha is not None and (',alpha=%s' % self.alpha) or ''), )
def _setCMYKColor(self, c): KO = getattr(c, 'knockout', None) if KO is None: KO = getattr(rl_config, 'PS_SEP_KNOCKOUT', 1) over = KO and 'false' or 'true' spotName = getattr(c, 'spotName', None) if spotName: return '%s (%s) 0\n/tint exch def\nfindcmykcustomcolor %s setoverprint\ntint %s exch sub setcustomcolor' % ( fp_str(c.cmyk()), spotName, over, c._density_str()) else: d = c.density return '%s setcmykcolor %s setoverprint' % (fp_str( c.cyan * d, c.magenta * d, c.yellow * d, c.black * d), over)
def polygon(self, p, closed=0, stroke=1, fill=1): assert len(p) >= 2, 'Polygon must have 2 or more points' start = p[0] p = p[1:] poly = [] a = poly.append a("%s m" % fp_str(start)) for point in p: a("%s l" % fp_str(point)) if closed: a("closepath") self._fillAndStroke(poly, stroke=stroke, fill=fill)
def polygon(self, p, closed=0, stroke=1, fill=1): assert len(p) >= 2, 'Polygon must have 2 or more points' start = p[0] p = p[1:] poly = [] a = poly.append a("%s m" % fp_str(start)) for point in p: a("%s l" % fp_str(point)) if closed: a("closepath") self._fillAndStroke(poly,stroke=stroke,fill=fill)
def setFont(self, psfontname, size, leading = None): """Sets the font. If leading not specified, defaults to 1.2 x font size. Raises a readable exception if an illegal font is supplied. Font names are case-sensitive! Keeps track of font anme and size for metrics.""" self._fontname = psfontname self._fontsize = size if leading is None: leading = size * 1.2 self._leading = leading font = pdfmetrics.getFont(self._fontname) if font._dynamicFont: self._curSubset = -1 else: pdffontname = self._canvas._doc.getInternalFontName(psfontname) self._code.append('%s %s Tf %s TL' % (pdffontname, fp_str(size), fp_str(leading)))
def _rgbFind(self,color): "see if it matches any existing color in my list" C = self.cmykColors if isinstance(color,(list,tuple)): if len(color)==3: color = Color(color[0],color[1],color[2]) elif len(color)==4: color = CMYKColor(color[0],color[1],color[2],color[3]) else: raise ValueError("bad color %s"%repr(color)) isCMYK = isinstance(color, CMYKColor) if not isCMYK: if isinstance(color,str): color = toColor(color) if colorDistance(color,black)<1e-8: isCMYK = 1 color = PCMYKColor(0,0,0,100,100) elif colorDistance(color,white)<1e-8: isCMYK = 1 color = PCMYKColor(0,0,0,0,100) rgb = color.red, color.green, color.blue if isCMYK: if color not in C: C.append(color) return self._setCMYKColor(color) else: for c in C: if (c.red, c.green, c.blue) == rgb: return self._setCMYKColor(c) return '%s setrgbcolor' % fp_str(rgb)
def _textOut(self, x, y, s, textRenderMode=0): if textRenderMode == 3: return xy = fp_str(x, y) s = self._escape(s) if textRenderMode == 0: #the standard case self.setColor(self._fillColor) self.code_append('%s m (%s) show ' % (xy, s)) return fill = textRenderMode == 0 or textRenderMode == 2 or textRenderMode == 4 or textRenderMode == 6 stroke = textRenderMode == 1 or textRenderMode == 2 or textRenderMode == 5 or textRenderMode == 6 addToClip = textRenderMode >= 4 if fill and stroke: if self._fillColor is None: op = '' else: op = 'fill ' self.setColor(self._fillColor) self.code_append('%s m (%s) true charpath gsave %s' % (xy, s, op)) self.code_append('grestore ') if self._strokeColor is not None: self.setColor(self._strokeColor) self.code_append('stroke ') else: #can only be stroke alone self.setColor(self._strokeColor) self.code_append('%s m (%s) true charpath stroke ' % (xy, s))
def tag_format(ttag): tag, attrs, content, where = ttag b = '\n!!!!! ' + (len(tag) + 2) * '\x20' if attrs: attrs = b + b.join( ('%s=%r' % (k, v) for k, v in sorted(attrs.items()))) else: attrs = '' haveObj = isinstance(ttag, TagAndObj) objName = ttag.name if haveObj else '' if objName: objName = ' (%s)' % objName xtra = [].append if haveObj: if isinstance(ttag.obj, Table): irow = getattr(ttag.obj, '__rml_initial_row__', 0) rowH = [(h, i) for i, h in enumerate(ttag.obj._rowHeights) if h is not None and h > 0] rowH.sort(reverse=True) if rowH: xtra(b + 'largest row heights = [%s]' % ', '.join( ('|%d|=%s%s' % (irow + i + 1, fp_str(h), whereFormat(whereFromSeq( ttag.obj._cellvalues[i]))) for h, i in rowH[:5]))) xtra = xtra.__self__ if xtra: xtra = '\n'.join(xtra) return '\n!!!!! <%s%s>%s%s%s' % (tag, attrs, objName, whereFormat(where), xtra)
def _rgbFind(self, color): "see if it matches any existing color in my list" C = self.cmykColors if isinstance(color, (list, tuple)): if len(color) == 3: color = Color(color[0], color[1], color[2]) elif len(color) == 4: color = CMYKColor(color[0], color[1], color[2], color[3]) else: raise ValueError("bad color %s" % repr(color)) isCMYK = isinstance(color, CMYKColor) if not isCMYK: if isinstance(color, str): color = toColor(color) if colorDistance(color, black) < 1e-8: isCMYK = 1 color = PCMYKColor(0, 0, 0, 100, 100) elif colorDistance(color, white) < 1e-8: isCMYK = 1 color = PCMYKColor(0, 0, 0, 0, 100) rgb = color.red, color.green, color.blue if isCMYK: if color not in C: C.append(color) return self._setCMYKColor(color) else: for c in C: if (c.red, c.green, c.blue) == rgb: return self._setCMYKColor(c) return '%s setrgbcolor' % fp_str(rgb)
def _issueT1String(self, fontObj, x, y, s, textRenderMode=0): fc = fontObj code_append = self.code_append fontSize = self._fontSize fontsUsed = self._fontsUsed escape = self._escape if not isUnicode(s): try: s = s.decode('utf8') except UnicodeDecodeError as e: i, j = e.args[2:4] raise UnicodeDecodeError( *(e.args[:4] + ('%s\n%s-->%s<--%s' % (e.args[4], s[i - 10:i], s[i:j], s[j:j + 10]), ))) for f, t in unicode2T1(s, [fontObj] + fontObj.substitutionFonts): if f != fc: psName = asNative(f.face.name) code_append('(%s) findfont %s scalefont setfont' % (psName, fp_str(fontSize))) if psName not in fontsUsed: fontsUsed.append(psName) fc = f self._textOut(x, y, t, textRenderMode) x += f.stringWidth(t.decode(f.encName), fontSize) if fontObj != fc: self._font = None self.setFont(fontObj.face.name, fontSize)
def polyLine(self, points): assert len(points) >= 1, 'Polyline must have 1 or more points' if self._strokeColor != None: pts = ', '.join([fp_str(*p) for p in points]) polyline = transformNode(self.doc, "polyline", points=pts, style=self._formatStyle(AREA_STYLES,fill=None)) self.currGroup.appendChild(polyline)
def drawInlineImage(self, canvas, preserveAspectRatio=False,anchor='sw'): """Draw an Image into the specified rectangle. If width and height are omitted, they are calculated from the image size. Also allow file names as well as images. This allows a caching mechanism""" width = self.width height = self.height if width<1e-6 or height<1e-6: return False x,y,self.width,self.height, scaled = aspectRatioFix(preserveAspectRatio,anchor,self.x,self.y,width,height,self.imgwidth,self.imgheight) # this says where and how big to draw it if not canvas.bottomup: y = y+height canvas._code.append('q %s 0 0 %s cm' % (fp_str(self.width), fp_str(self.height, x, y))) # self._code.extend(imagedata) if >=python-1.5.2 for line in self.imageData: canvas._code.append(line) canvas._code.append('Q') return True
def drawString(self, x, y, s, angle=0, text_anchor='left', textRenderMode=0): needFill = textRenderMode in (0, 2, 4, 6) needStroke = textRenderMode in (1, 2, 5, 6) if needFill or needStroke: if text_anchor != 'left': textLen = stringWidth(s, self._font, self._fontSize) if text_anchor == 'end': x -= textLen elif text_anchor == 'middle': x -= textLen / 2. elif text_anchor == 'numeric': x -= numericXShift(text_anchor, s, textLen, self._font, self._fontSize) fontObj = getFont(self._font) if not self.code[self._fontCodeLoc]: psName = asNative(fontObj.face.name) self.code[ self. _fontCodeLoc] = '(%s) findfont %s scalefont setfont' % ( psName, fp_str(self._fontSize)) if psName not in self._fontsUsed: self._fontsUsed.append(psName) if angle != 0: self.code_append('gsave %s translate %s rotate' % (fp_str(x, y), fp_str(angle))) x = y = 0 oldColor = self._color if fontObj._dynamicFont: self._textOut(self, x, y, s, textRenderMode=textRenderMode) else: self._issueT1String(fontObj, x, y, s, textRenderMode=textRenderMode) self.setColor(oldColor) if angle != 0: self.code_append('grestore')
def scaledRender(self,size,ds=0): ''' >>> print(cbmarks['check'].scaledRender(20)) 12.97075 14.68802 m 15.00139 17.16992 l 15.9039 18.1727 17.93454 18.67409 19.2883 18.67409 c 19.46379 18.27298 l 17.13231 15.51532 l 11.91783 8.62117 l 8.307799 3.030641 l 7.430362 1.526462 l 7.305014 1.275766 7.154596 .97493 6.9039 .824513 c 6.577994 .674095 5.825905 .674095 5.47493 .674095 c 4.672702 .674095 4.497214 .674095 4.321727 .799443 c 4.071031 .97493 3.945682 1.325905 3.770195 1.67688 c 3.218663 2.830084 2.240947 5.337047 2.240947 6.590529 c 2.240947 7.016713 2.491643 7.21727 2.817549 7.442897 c 3.344011 7.818942 4.0961 8.245125 4.747911 8.245125 c 5.249304 8.245125 5.299443 7.818942 5.449861 7.417827 c 5.951253 6.239554 l 6.026462 6.038997 6.252089 5.337047 6.527855 5.337047 c 6.778552 5.337047 7.079387 5.913649 7.179666 6.089136 c 12.97075 14.68802 l h f >>> print(cbmarks['cross'].scaledRender(20)) 19.9104 17.43931 m 12.41908 10 l 19.9104 2.534682 l 18.37572 1 l 10.9104 8.491329 l 3.445087 1 l 1.910405 2.534682 l 9.427746 10 l 1.910405 17.46532 l 3.445087 19 l 10.9104 11.50867 l 18.37572 19 l 19.9104 17.43931 l h f >>> print(cbmarks['circle'].scaledRender(20)) 1.872576 9.663435 m 1.872576 14.64958 5.936288 18.61357 10.89751 18.61357 c 15.8338 18.61357 19.87258 14.59972 19.87258 9.663435 c 19.87258 4.727147 15.8338 .688366 10.89751 .688366 c 5.936288 .688366 1.872576 4.677285 1.872576 9.663435 c h f >>> print(cbmarks['star'].scaledRender(20)) 10.85542 18.3253 m 12.90361 11.84337 l 19.84337 11.84337 l 14.25301 7.650602 l 16.42169 1 l 10.85542 5.096386 l 5.289157 1 l 7.481928 7.650602 l 1.843373 11.84337 l 8.759036 11.84337 l 10.85542 18.3253 l h f >>> print(cbmarks['diamond'].scaledRender(20)) 17.43533 9.662031 m 15.63282 7.484006 l 10.85118 .649513 l 8.422809 4.329624 l 5.919332 7.659249 l 4.267038 9.662031 l 6.16968 12.0153 l 10.85118 18.64951 l 12.75382 15.4701 15.00695 12.49096 17.43533 9.662031 c h f ''' #work out the scale and translation W = H = size - 2*ds xmin = self.xmin ymin = self.ymin w = self.xmax-xmin h = self.ymax-ymin slack = self.slack*min(W,H) sx = (W - 2*slack)/float(w) sy = (H - 2*slack)/float(h) sx = sy = min(sx,sy) w *= sx h *= sy dx = ds+(W - w)*0.5 dy = ds+(H - h)*0.5 xsc = lambda v: fp_str((v-xmin)*sx+dx) ysc = lambda v: fp_str((v-ymin)*sy+dy) opNames = self.opNames opCount = self.opCount C = [].append i = 0 points = self.points for op in self.ops: c = opCount[op] for _ in xrange(c): C(xsc(points[i])) C(ysc(points[i+1])) i += 2 C(opNames[op]) C('f') return ' '.join(C.__self__)
def scaledRender(self, size, ds=0): ''' >>> print(cbmarks['check'].scaledRender(20)) 12.97075 14.68802 m 15.00139 17.16992 l 15.9039 18.1727 17.93454 18.67409 19.2883 18.67409 c 19.46379 18.27298 l 17.13231 15.51532 l 11.91783 8.62117 l 8.307799 3.030641 l 7.430362 1.526462 l 7.305014 1.275766 7.154596 .97493 6.9039 .824513 c 6.577994 .674095 5.825905 .674095 5.47493 .674095 c 4.672702 .674095 4.497214 .674095 4.321727 .799443 c 4.071031 .97493 3.945682 1.325905 3.770195 1.67688 c 3.218663 2.830084 2.240947 5.337047 2.240947 6.590529 c 2.240947 7.016713 2.491643 7.21727 2.817549 7.442897 c 3.344011 7.818942 4.0961 8.245125 4.747911 8.245125 c 5.249304 8.245125 5.299443 7.818942 5.449861 7.417827 c 5.951253 6.239554 l 6.026462 6.038997 6.252089 5.337047 6.527855 5.337047 c 6.778552 5.337047 7.079387 5.913649 7.179666 6.089136 c 12.97075 14.68802 l h f >>> print(cbmarks['cross'].scaledRender(20)) 19.9104 17.43931 m 12.41908 10 l 19.9104 2.534682 l 18.37572 1 l 10.9104 8.491329 l 3.445087 1 l 1.910405 2.534682 l 9.427746 10 l 1.910405 17.46532 l 3.445087 19 l 10.9104 11.50867 l 18.37572 19 l 19.9104 17.43931 l h f >>> print(cbmarks['circle'].scaledRender(20)) 1.872576 9.663435 m 1.872576 14.64958 5.936288 18.61357 10.89751 18.61357 c 15.8338 18.61357 19.87258 14.59972 19.87258 9.663435 c 19.87258 4.727147 15.8338 .688366 10.89751 .688366 c 5.936288 .688366 1.872576 4.677285 1.872576 9.663435 c h f >>> print(cbmarks['star'].scaledRender(20)) 10.85542 18.3253 m 12.90361 11.84337 l 19.84337 11.84337 l 14.25301 7.650602 l 16.42169 1 l 10.85542 5.096386 l 5.289157 1 l 7.481928 7.650602 l 1.843373 11.84337 l 8.759036 11.84337 l 10.85542 18.3253 l h f >>> print(cbmarks['diamond'].scaledRender(20)) 17.43533 9.662031 m 15.63282 7.484006 l 10.85118 .649513 l 8.422809 4.329624 l 5.919332 7.659249 l 4.267038 9.662031 l 6.16968 12.0153 l 10.85118 18.64951 l 12.75382 15.4701 15.00695 12.49096 17.43533 9.662031 c h f ''' #work out the scale and translation W = H = size - 2 * ds xmin = self.xmin ymin = self.ymin w = self.xmax - xmin h = self.ymax - ymin slack = self.slack * min(W, H) sx = (W - 2 * slack) / float(w) sy = (H - 2 * slack) / float(h) sx = sy = min(sx, sy) w *= sx h *= sy dx = ds + (W - w) * 0.5 dy = ds + (H - h) * 0.5 xsc = lambda v: fp_str((v - xmin) * sx + dx) ysc = lambda v: fp_str((v - ymin) * sy + dy) opNames = self.opNames opCount = self.opCount C = [].append i = 0 points = self.points for op in self.ops: c = opCount[op] for _ in range(c): C(xsc(points[i])) C(ysc(points[i + 1])) i += 2 C(opNames[op]) C('f') return ' '.join(C.__self__)
def drawString(self, x, y, s, angle=0): if self._fillColor != None: fontObj = getFont(self._font) if not self.code[self._fontCodeLoc]: psName = asNative(fontObj.face.name) self.code[self._fontCodeLoc]='(%s) findfont %s scalefont setfont' % (psName,fp_str(self._fontSize)) if psName not in self._fontsUsed: self._fontsUsed.append(psName) self.setColor(self._fillColor) if angle!=0: self.code_append('gsave %s translate %s rotate' % (fp_str(x,y),fp_str(angle))) x = y = 0 if fontObj._dynamicFont: s = self._escape(s) self.code_append('%s m (%s) show ' % (fp_str(x,y),s)) else: self._issueT1String(fontObj,x,y,s) if angle!=0: self.code_append('grestore')
def _setCMYKColor(self,c): KO = getattr(c,'knockout',None) if KO is None: KO = getattr(rl_config,'PS_SEP_KNOCKOUT',1) over = KO and 'false' or 'true' spotName = getattr(c,'spotName',None) if spotName: return '%s (%s) 0\n/tint exch def\nfindcmykcustomcolor %s setoverprint\ntint %s exch sub setcustomcolor' % (fp_str(c.cmyk()),spotName,over,c._density_str()) else: d = c.density return '%s setcmykcolor %s setoverprint' % (fp_str(c.cyan*d,c.magenta*d,c.yellow*d,c.black*d),over)
def _formatText(self, text): "Generates PDF text output operator(s)" if log2vis and self.direction in ('LTR','RTL'): # Use pyfribidi to write the text in the correct visual order. text = log2vis(text, directionsMap.get(self.direction.upper(),DIR_ON),clean=True) canv = self._canvas font = pdfmetrics.getFont(self._fontname) R = [] if font._dynamicFont: #it's a truetype font and should be utf8. If an error is raised, for subset, t in font.splitString(text, canv._doc): if subset!=self._curSubset: pdffontname = font.getSubsetInternalName(subset, canv._doc) R.append("%s %s Tf %s TL" % (pdffontname, fp_str(self._fontsize), fp_str(self._leading))) self._curSubset = subset R.append("(%s) Tj" % canv._escape(t)) elif font._multiByte: #all the fonts should really work like this - let them know more about PDF... R.append("%s %s Tf %s TL" % ( canv._doc.getInternalFontName(font.fontName), fp_str(self._fontsize), fp_str(self._leading) )) R.append("(%s) Tj" % font.formatForPdf(text)) else: #convert to T1 coding fc = font if isBytes(text): try: text = text.decode('utf8') except UnicodeDecodeError as e: i,j = e.args[2:4] raise UnicodeDecodeError(*(e.args[:4]+('%s\n%s-->%s<--%s' % (e.args[4],text[max(i-10,0):i],text[i:j],text[j:j+10]),))) for f, t in pdfmetrics.unicode2T1(text,[font]+font.substitutionFonts): if f!=fc: R.append("%s %s Tf %s TL" % (canv._doc.getInternalFontName(f.fontName), fp_str(self._fontsize), fp_str(self._leading))) fc = f R.append("(%s) Tj" % canv._escape(t)) if font!=fc: R.append("%s %s Tf %s TL" % (canv._doc.getInternalFontName(self._fontname), fp_str(self._fontsize), fp_str(self._leading))) return ' '.join(R)
def polygon(self, points, closed=0, link_info=None): assert len(points) >= 2, 'Polygon must have 2 or more points' if self._strokeColor!=None or self._fillColor!=None: pts = ', '.join([fp_str(*p) for p in points]) polyline = transformNode(self.doc, "polygon", points=pts, style=self._formatStyle(AREA_STYLES)) if link_info: polyline = self._add_link(polyline, link_info) self.currGroup.appendChild(polyline)
def drawFigure(self, partList, closed=0): figureCode = [] a = figureCode.append first = 1 for part in partList: op = part[0] args = list(part[1:]) if op == figureLine: if first: first = 0 a("%s m" % fp_str(args[:2])) else: a("%s l" % fp_str(args[:2])) a("%s l" % fp_str(args[2:])) elif op == figureArc: first = 0 x1,y1,x2,y2,startAngle,extent = args[:6] a(self._genArcCode(x1,y1,x2,y2,startAngle,extent)) elif op == figureCurve: if first: first = 0 a("%s m" % fp_str(args[:2])) else: a("%s l" % fp_str(args[:2])) a("%s curveto" % fp_str(args[2:])) else: raise TypeError("unknown figure operator: "+op) if closed: a("closepath") self._fillAndStroke(figureCode)
def drawFigure(self, partList, closed=0): figureCode = [] a = figureCode.append first = 1 for part in partList: op = part[0] args = list(part[1:]) if op == figureLine: if first: first = 0 a("%s m" % fp_str(args[:2])) else: a("%s l" % fp_str(args[:2])) a("%s l" % fp_str(args[2:])) elif op == figureArc: first = 0 x1, y1, x2, y2, startAngle, extent = args[:6] a(self._genArcCode(x1, y1, x2, y2, startAngle, extent)) elif op == figureCurve: if first: first = 0 a("%s m" % fp_str(args[:2])) else: a("%s l" % fp_str(args[:2])) a("%s curveto" % fp_str(args[2:])) else: raise TypeError("unknown figure operator: " + op) if closed: a("closepath") self._fillAndStroke(figureCode)
def setTextTransform(self, a, b, c, d, e, f): "Like setTextOrigin, but does rotation, scaling etc." if not self._canvas.bottomup: c = -c #reverse bottom row of the 2D Transform d = -d self._code.append('%s Tm' % fp_str(a, b, c, d, e, f)) # The current cursor position is at the text origin Note that # we aren't keeping track of all the transform on these # coordinates: they are relative to the rotations/sheers # defined in the matrix. self._x0 = self._x = e self._y0 = self._y = f
def drawString(self, x, y, s, angle=0): if self._fillColor != None: fontSize = self._fontSize fontObj = getFont(self._font) dynamicFont = fontObj._dynamicFont embedding = self._ttf_embed and dynamicFont if not embedding and not self.code[self._fontCodeLoc]: psName = fontObj.face.name self.code[self._fontCodeLoc]='(%s) findfont %s scalefont setfont' % (psName,fp_str(fontSize)) if psName not in self._fontsUsed: self._fontsUsed.append(psName) self.setColor(self._fillColor) if angle!=0: self.code_append('gsave %s translate %s rotate' % (fp_str(x,y),fp_str(angle))) x = y = 0 if embedding: i = 0 s = asUnicode(s) for subset, t in fontObj.splitString(s, self): if subset!=self._curSubset: psName = fontObj.getSubsetInternalName(subset, self)[1:] sf = '(%s) findfont %s scalefont setfont' % (psName,fp_str(fontSize)) if not self.code[self._fontCodeLoc]: self.code[self._fontCodeLoc] = sf else: self.code_append(sf) self._curSubset = subset self.code_append('%s m (%s) show ' % (fp_str(x,y),self._escape(t))) j = i + len(t) x += fontObj.stringWidth(s[i:j],fontSize) i = j elif dynamicFont: s = self._escape(s) self.code_append('%s m (%s) show ' % (fp_str(x,y),s)) else: self._issueT1String(fontObj,x,y,s) if angle!=0: self.code_append('grestore')
def _setFont(self, psfontname, size): """Sets the font and fontSize Raises a readable exception if an illegal font is supplied. Font names are case-sensitive! Keeps track of font anme and size for metrics.""" self._fontname = psfontname self._fontsize = size font = pdfmetrics.getFont(self._fontname) if font._dynamicFont: self._curSubset = -1 else: pdffontname = self._canvas._doc.getInternalFontName(psfontname) self._code.append('%s %s Tf' % (pdffontname, fp_str(size)))
def setFillColor(self, aColor, alpha=None): """Takes a color object, allowing colors to be referred to by name""" if self._enforceColorSpace: aColor = self._enforceColorSpace(aColor) if isinstance(aColor, CMYKColor): d = aColor.density c, m, y, k = (d * aColor.cyan, d * aColor.magenta, d * aColor.yellow, d * aColor.black) self._fillColorObj = aColor name = self._checkSeparation(aColor) if name: self._code.append('/%s cs %s scn' % (name, fp_str(d))) else: self._code.append('%s k' % fp_str(c, m, y, k)) elif isinstance(aColor, Color): rgb = (aColor.red, aColor.green, aColor.blue) self._fillColorObj = aColor self._code.append('%s rg' % fp_str(rgb)) elif isinstance(aColor, (tuple, list)): l = len(aColor) if l == 3: self._fillColorObj = aColor self._code.append('%s rg' % fp_str(aColor)) elif l == 4: self._fillColorObj = aColor self._code.append('%s k' % fp_str(aColor)) else: raise ValueError('Unknown color %r' % aColor) elif isStr(aColor): self.setFillColor(toColor(aColor)) else: raise ValueError('Unknown color %r' % aColor) if alpha is not None: self.setFillAlpha(alpha) elif getattr(aColor, 'alpha', None) is not None: self.setFillAlpha(aColor.alpha)
def P2PSC(P): C = [] aC = C.append n = 0 for p in P: if n>=80: aC('\n') n = 0 if isinstance(p,tuple): aC(fp_str(*p[1:])) aC(p[0][0].lower()) n += 2+sum(map(len,C[-2:])) else: aC(p.lower()) n += 1+len(C[-1]) return C
def moveCursor(self, dx, dy): """Starts a new line at an offset dx,dy from the start of the current line. This does not move the cursor relative to the current position, and it changes the current offset of every future line drawn (i.e. if you next do a textLine() call, it will move the cursor to a position one line lower than the position specificied in this call. """ # Check if we have a previous move cursor call, and combine # them if possible. if self._code and self._code[-1][-3:]==' Td': L = self._code[-1].split() if len(L)==3: del self._code[-1] else: self._code[-1] = ''.join(L[:-4]) # Work out the last movement lastDx = float(L[-3]) lastDy = float(L[-2]) # Combine the two movement dx += lastDx dy -= lastDy # We will soon add the movement to the line origin, so if # we've already done this for lastDx, lastDy, remove it # first (so it will be right when added back again). self._x0 -= lastDx self._y0 -= lastDy # Output the move text cursor call. self._code.append('%s Td' % fp_str(dx, -dy)) # Keep track of the new line offsets and the cursor position self._x0 += dx self._y0 += dy self._x = self._x0 self._y = self._y0
def moveCursor(self, dx, dy): """Starts a new line at an offset dx,dy from the start of the current line. This does not move the cursor relative to the current position, and it changes the current offset of every future line drawn (i.e. if you next do a textLine() call, it will move the cursor to a position one line lower than the position specificied in this call. """ # Check if we have a previous move cursor call, and combine # them if possible. if self._code and self._code[-1][-3:] == ' Td': L = self._code[-1].split() if len(L) == 3: del self._code[-1] else: self._code[-1] = ''.join(L[:-4]) # Work out the last movement lastDx = float(L[-3]) lastDy = float(L[-2]) # Combine the two movement dx += lastDx dy -= lastDy # We will soon add the movement to the line origin, so if # we've already done this for lastDx, lastDy, remove it # first (so it will be right when added back again). self._x0 -= lastDx self._y0 -= lastDy # Output the move text cursor call. self._code.append('%s Td' % fp_str(dx, -dy)) # Keep track of the new line offsets and the cursor position self._x0 += dx self._y0 += dy self._x = self._x0 self._y = self._y0
def drawString(self, x, y, s, angle=0): if self._fillColor != None: fontSize = self._fontSize fontObj = getFont(self._font) dynamicFont = fontObj._dynamicFont embedding = self._ttf_embed and dynamicFont if not embedding and not self.code[self._fontCodeLoc]: psName = fontObj.face.name self.code[ self. _fontCodeLoc] = '(%s) findfont %s scalefont setfont' % ( psName, fp_str(fontSize)) if psName not in self._fontsUsed: self._fontsUsed.append(psName) self.setColor(self._fillColor) if angle != 0: self.code_append('gsave %s translate %s rotate' % (fp_str(x, y), fp_str(angle))) x = y = 0 if embedding: i = 0 s = asUnicode(s) for subset, t in fontObj.splitString(s, self): if subset != self._curSubset: psName = fontObj.getSubsetInternalName(subset, self)[1:] sf = '(%s) findfont %s scalefont setfont' % ( psName, fp_str(fontSize)) if not self.code[self._fontCodeLoc]: self.code[self._fontCodeLoc] = sf else: self.code_append(sf) self._curSubset = subset self.code_append('%s m (%s) show ' % (fp_str(x, y), self._escape(t))) j = i + len(t) x += fontObj.stringWidth(s[i:j], fontSize) i = j elif dynamicFont: s = self._escape(s) self.code_append('%s m (%s) show ' % (fp_str(x, y), s)) else: self._issueT1String(fontObj, x, y, s) if angle != 0: self.code_append('grestore')
def __repr__(self): return "Color(%s)" % fp_str(*(self.red, self.green, self.blue, self.alpha)).replace(' ', ',')
def _density_str(self): return fp_str(self.density)
def curveTo(self, x1, y1, x2, y2, x3, y3): self._code_append('%s c' % fp_str(x1, y1, x2, y2, x3, y3))
def lineTo(self, x, y): self._code_append('%s l' % fp_str(x,y))
def setLeading(self, leading): "How far to move down at the end of a line." self._leading = leading self._code.append('%s TL' % fp_str(leading))
def setRise(self, rise): "Move text baseline up or down to allow superscript/subscripts" self._rise = rise self._y = self._y - rise # + ? _textLineMatrix? self._code.append('%s Ts' % fp_str(rise))
def setHorizScale(self, horizScale): "Stretches text out horizontally" self._horizScale = 100 + horizScale self._code.append('%s Tz' % fp_str(horizScale))
def setWordSpace(self, wordSpace): """Adjust inter-word spacing. This can be used to flush-justify text - you get the width of the words, and add some space between them.""" self._wordSpace = wordSpace self._code.append('%s Tw' % fp_str(wordSpace))
def setCharSpace(self, charSpace): """Adjusts inter-character spacing""" self._charSpace = charSpace self._code.append('%s Tc' % fp_str(charSpace))
def rect(self, x, y, width, height): """Adds a rectangle to the path""" self._code_append('%s re' % fp_str((x, y, width, height)))
def setStrokeGray(self, gray, alpha=None): """Sets the gray level; 0.0=black, 1.0=white""" self._strokeColorObj = (gray, gray, gray) self._code.append('%s G' % fp_str(gray)) if alpha is not None: self.setFillAlpha(alpha)