def _expandWidths(self, compactWidthArray): """Expands Adobe nested list structure to get a dictionary of widths. Here is an example of such a structure.:: ( # starting at character ID 1, next n characters have the widths given. 1, (277,305,500,668,668,906,727,305,445,445,508,668,305,379,305,539), # all Characters from ID 17 to 26 are 668 em units wide 17, 26, 668, 27, (305, 305, 668, 668, 668, 566, 871, 727, 637, 652, 699, 574, 555, 676, 687, 242, 492, 664, 582, 789, 707, 734, 582, 734, 605, 605, 641, 668, 727, 945, 609, 609, 574, 445, 668, 445, 668, 668, 590, 555, 609, 547, 602, 574, 391, 609, 582, 234, 277, 539, 234, 895, 582, 605, 602, 602, 387, 508, 441, 582, 562, 781, 531, 570, 555, 449, 246, 449, 668), # these must be half width katakana and the like. 231, 632, 500 ) """ data = compactWidthArray[:] widths = {} while data: start, data = data[0], data[1:] if isSeqType(data[0]): items, data = data[0], data[1:] for offset in range(len(items)): widths[start + offset] = items[offset] else: end, width, data = data[0], data[1], data[2:] for idx in range(start, end+1): widths[idx] = width return widths
def _expandWidths(self, compactWidthArray): """Expands Adobe nested list structure to get a dictionary of widths. Here is an example of such a structure.:: ( # starting at character ID 1, next n characters have the widths given. 1, (277,305,500,668,668,906,727,305,445,445,508,668,305,379,305,539), # all Characters from ID 17 to 26 are 668 em units wide 17, 26, 668, 27, (305, 305, 668, 668, 668, 566, 871, 727, 637, 652, 699, 574, 555, 676, 687, 242, 492, 664, 582, 789, 707, 734, 582, 734, 605, 605, 641, 668, 727, 945, 609, 609, 574, 445, 668, 445, 668, 668, 590, 555, 609, 547, 602, 574, 391, 609, 582, 234, 277, 539, 234, 895, 582, 605, 602, 602, 387, 508, 441, 582, 562, 781, 531, 570, 555, 449, 246, 449, 668), # these must be half width katakana and the like. 231, 632, 500 ) """ data = compactWidthArray[:] widths = {} while data: start, data = data[0], data[1:] if isSeqType(data[0]): items, data = data[0], data[1:] for offset in range(len(items)): widths[start + offset] = items[offset] else: end, width, data = data[0], data[1], data[2:] for idx in range(start, end + 1): widths[idx] = width return widths
def _getStr(s): if isSeqType(s): return map(_getStr,s) elif isinstance(s,(unicode,str)): return s else: return str(s)
def __init__(self,action=()): #must call super init to ensure it has a width and height (of zero), #as in some cases the packer might get called on it... Flowable.__init__(self) if not isSeqType(action): action = (action,) self.action = tuple(action)
def addPageTemplates(self,pageTemplates): 'add one or a sequence of pageTemplates' if not isSeqType(pageTemplates): pageTemplates = [pageTemplates] #this test below fails due to inconsistent imports! #assert filter(lambda x: not isinstance(x,PageTemplate), pageTemplates)==[], "pageTemplates argument error" for t in pageTemplates: self.pageTemplates.append(t)
def __init__(self, enum, *args): if isSeqType(enum): if args != (): raise ValueError( "Either all singleton args or a single sequence argument") self._enum = tuple(enum) + args else: self._enum = (enum, ) + args
def setDash(self, array=[], phase=0): """Two notations. Pass two numbers, or an array and phase.""" if isinstance(array,(float,int)): self.style['stroke-dasharray'] = ', '.join(map(str, ([array, phase]))) elif isSeqType(array) and len(array) > 0: assert phase >= 0, "phase is a length in user space" self.style['stroke-dasharray'] = ', '.join(map(str, (array+[phase])))
def test(self, x): from reportlab.graphics.shapes import Shape if isSeqType(x): answer = 1 for e in x: if not isinstance(e, Shape): answer = 0 return answer else: return False
def setDash(self, array=[], phase=0): """Two notations. Pass two numbers, or an array and phase.""" if isinstance(array, (float, int)): self.style['stroke-dasharray'] = ', '.join( map(str, ([array, phase]))) elif isSeqType(array) and len(array) > 0: assert phase >= 0, "phase is a length in user space" self.style['stroke-dasharray'] = ', '.join( map(str, (array + [phase])))
def _getWidth(s,fontName, fontSize, sepSpace=0): if isSeqType(s): sum = 0 for t in s: m = [stringWidth(x, fontName, fontSize) for x in t.split('\n')] sum += m and max(m) or 0 sum += (len(s)-1)*sepSpace return sum m = [stringWidth(x, fontName, fontSize) for x in s.split('\n')] return m and max(m) or 0
def __init__(self,id=None,frames=[],onPage=_doNothing, onPageEnd=_doNothing, pagesize=None, autoNextPageTemplate=None): frames = frames or [] if not isSeqType(frames): frames = [frames] assert [x for x in frames if not isinstance(x, Frame)]==[], "frames argument error" self.id = id self.frames = frames self.onPage = onPage self.onPageEnd = onPageEnd self.pagesize = pagesize self.autoNextPageTemplate = autoNextPageTemplate
def test(self, x): if isSeqType(x): if len(x) == 6: for element in x: if not isNumber(element): return False return True else: return False else: return False
def test(self, x): if not isSeqType(x): if x is None: return self._NoneOK return False if x == [] or x == (): return self._emptyOK elif not self._lo <= len(x) <= self._hi: return False for e in x: if not self._elemTest(e): return False return True
def structToPDF(structure): "Converts deeply nested structure to PDFdoc dictionary/array objects" if type(structure) is dict: newDict = {} for k, v in structure.items(): newDict[k] = structToPDF(v) return pdfdoc.PDFDictionary(newDict) elif isSeqType(structure): newList = [] for elem in structure: newList.append(structToPDF(elem)) return pdfdoc.PDFArray(newList) else: return structure
def structToPDF(structure): "Converts deeply nested structure to PDFdoc dictionary/array objects" if type(structure) is dict: newDict = {} for k, v in structure.items(): newDict[k] = structToPDF(v) return pdfdoc.PDFDictionary(newDict) elif isSeqType(structure): newList = [] for elem in structure: newList.append(structToPDF(elem)) return pdfdoc.PDFArray(newList) else: return structure
def start_stylesheet(self, args): #makes it the current style sheet. path = self._arg('stylesheet',args,'path') if path=='None': path = [] if not isSeqType(path): path = [path] path.append('styles') path.append(os.getcwd()) modulename = self._arg('stylesheet', args, 'module') funcname = self._arg('stylesheet', args, 'function') try: found = imp.find_module(modulename, path) (file, pathname, description) = found mod = imp.load_module(modulename, file, pathname, description) except ImportError: #last gasp mod = getModule(modulename) #now get the function func = getattr(mod, funcname) pythonpoint.setStyles(func())
def start_stylesheet(self, args): #makes it the current style sheet. path = self._arg('stylesheet', args, 'path') if path == 'None': path = [] if not isSeqType(path): path = [path] path.append('styles') path.append(os.getcwd()) modulename = self._arg('stylesheet', args, 'module') funcname = self._arg('stylesheet', args, 'function') try: found = imp.find_module(modulename, path) (file, pathname, description) = found mod = imp.load_module(modulename, file, pathname, description) except ImportError: #last gasp mod = getModule(modulename) #now get the function func = getattr(mod, funcname) pythonpoint.setStyles(func())
def _getWidths(i, s, fontName, fontSize, subCols): S = [] aS = S.append if isSeqType(s): for j, t in enumerate(s): sc = subCols[j, i] fN = getattr(sc, 'fontName', fontName) fS = getattr(sc, 'fontSize', fontSize) m = [stringWidth(x, fN, fS) for x in t.split('\n')] m = max(sc.minWidth, m and max(m) or 0) aS(m) aS(sc.rpad) del S[-1] else: sc = subCols[0, i] fN = getattr(sc, 'fontName', fontName) fS = getattr(sc, 'fontSize', fontSize) m = [stringWidth(x, fN, fS) for x in s.split('\n')] aS(max(sc.minWidth, m and max(m) or 0)) return S
def _getWidths(i,s, fontName, fontSize, subCols): S = [] aS = S.append if isSeqType(s): for j,t in enumerate(s): sc = subCols[j,i] fN = getattr(sc,'fontName',fontName) fS = getattr(sc,'fontSize',fontSize) m = [stringWidth(x, fN, fS) for x in t.split('\n')] m = max(sc.minWidth,m and max(m) or 0) aS(m) aS(sc.rpad) del S[-1] else: sc = subCols[0,i] fN = getattr(sc,'fontName',fontName) fS = getattr(sc,'fontSize',fontSize) m = [stringWidth(x, fN, fS) for x in s.split('\n')] aS(max(sc.minWidth,m and max(m) or 0)) return S
def __init__(self, name, base=None): self.name = name self.frozen = 0 if name in standardEncodings: assert base is None, "Can't have a base encoding for a standard encoding" self.baseEncodingName = name self.vector = _fontdata.encodings[name] elif base == None: # assume based on the usual one self.baseEncodingName = defaultEncoding self.vector = _fontdata.encodings[defaultEncoding] elif isStrType(base): baseEnc = getEncoding(base) self.baseEncodingName = baseEnc.name self.vector = baseEnc.vector[:] elif isSeqType(base): self.baseEncodingName = defaultEncoding self.vector = base[:] elif isinstance(base, Encoding): # accept a vector self.baseEncodingName = base.name self.vector = base.vector[:]
def __init__(self, name, base=None): self.name = name self.frozen = 0 if name in standardEncodings: assert base is None, "Can't have a base encoding for a standard encoding" self.baseEncodingName = name self.vector = _fontdata.encodings[name] elif base == None: # assume based on the usual one self.baseEncodingName = defaultEncoding self.vector = _fontdata.encodings[defaultEncoding] elif isStrType(base): baseEnc = getEncoding(base) self.baseEncodingName = baseEnc.name self.vector = baseEnc.vector[:] elif isSeqType(base): self.baseEncodingName = defaultEncoding self.vector = base[:] elif isinstance(base, Encoding): # accept a vector self.baseEncodingName = base.name self.vector = base.vector[:]
def handle_nextPageTemplate(self,pt): '''On endPage change to the page template with name or index pt''' if isStrType(pt): if hasattr(self, '_nextPageTemplateCycle'): del self._nextPageTemplateCycle for t in self.pageTemplates: if t.id == pt: self._nextPageTemplateIndex = self.pageTemplates.index(t) return raise ValueError("can't find template('%s')"%pt) elif type(pt) is int: if hasattr(self, '_nextPageTemplateCycle'): del self._nextPageTemplateCycle self._nextPageTemplateIndex = pt elif isSeqType(pt): #used for alternating left/right pages #collect the refs to the template objects, complain if any are bad c = PTCycle() for ptn in pt: found = 0 if ptn=='*': #special case name used to short circuit the iteration c._restart = len(c) continue for t in self.pageTemplates: if t.id == ptn: c.append(t) found = 1 if not found: raise ValueError("Cannot find page template called %s" % ptn) if not c: raise ValueError("No valid page templates in cycle") elif c._restart>len(c): raise ValueError("Invalid cycle restart position") #ensure we start on the first one self._nextPageTemplateCycle = c.cyclicIterator() else: raise TypeError("argument pt should be string or integer or list")
def draw(self): colorNamePairs = self.colorNamePairs autoCP = isAuto(colorNamePairs) if autoCP: chart = getattr(colorNamePairs,'chart',getattr(colorNamePairs,'obj',None)) swatchMarker = None autoCP = Auto(obj=chart) n = chart._seriesCount chartTexts = self._getTexts(colorNamePairs) else: swatchMarker = getattr(self,'swatchMarker',None) if isAuto(swatchMarker): chart = getattr(swatchMarker,'chart',getattr(swatchMarker,'obj',None)) swatchMarker = Auto(obj=chart) n = len(colorNamePairs) dx = self.dx dy = self.dy alignment = self.alignment columnMaximum = self.columnMaximum deltax = self.deltax deltay = self.deltay dxTextSpace = self.dxTextSpace fontName = self.fontName fontSize = self.fontSize fillColor = self.fillColor strokeWidth = self.strokeWidth strokeColor = self.strokeColor subCols = self.subCols leading = fontSize*1.2 yGap = self.yGap if not deltay: deltay = max(dy,leading)+self.autoYPadding ba = self.boxAnchor maxWidth = self._calculateMaxBoundaries(colorNamePairs) nCols = int((n+columnMaximum-1)/(columnMaximum*1.0)) xW = dx+dxTextSpace+self.autoXPadding variColumn = self.variColumn if variColumn: width = reduce(operator.add,[m[-1] for m in maxWidth],0)+xW*nCols else: deltax = max(maxWidth[-1]+xW,deltax) width = maxWidth[-1]+nCols*deltax maxWidth = nCols*[maxWidth] thisx = self.x thisy = self.y - self.dy if ba not in ('ne','n','nw','autoy'): height = self._calcHeight() if ba in ('e','c','w'): thisy += height/2. else: thisy += height if ba not in ('nw','w','sw','autox'): if ba in ('n','c','s'): thisx -= width/2 else: thisx -= width upperlefty = thisy g = Group() ascent=getFont(fontName).face.ascent/1000. if ascent==0: ascent=0.718 # default (from helvetica) ascent *= fontSize # normalize lim = columnMaximum - 1 callout = getattr(self,'callout',None) scallout = getattr(self,'swatchCallout',None) dividerLines = self.dividerLines if dividerLines: dividerWidth = self.dividerWidth dividerColor = self.dividerColor dividerDashArray = self.dividerDashArray dividerOffsX = self.dividerOffsX dividerOffsY = self.dividerOffsY for i in xrange(n): if autoCP: col = autoCP col.index = i name = chartTexts[i] else: col, name = colorNamePairs[i] if isAuto(swatchMarker): col = swatchMarker col.index = i if isAuto(name): name = getattr(swatchMarker,'chart',getattr(swatchMarker,'obj',None)).getSeriesName(i,'series %d' % i) T = _getLines(name) S = [] aS = S.append j = int(i/(columnMaximum*1.0)) jOffs = maxWidth[j] # thisy+dy/2 = y+leading/2 y = y0 = thisy+(dy-ascent)*0.5 if callout: callout(self,g,thisx,y,(col,name)) if alignment == "left": x = thisx xn = thisx+jOffs[-1]+dxTextSpace elif alignment == "right": x = thisx+dx+dxTextSpace xn = thisx else: raise ValueError, "bad alignment" if not isSeqType(name): T = [T] yd = y for k,lines in enumerate(T): y = y0 kk = k*2 x1 = x+jOffs[kk] x2 = x+jOffs[kk+1] sc = subCols[k,i] anchor = sc.align scdx = sc.dx scdy = sc.dy fN = getattr(sc,'fontName',fontName) fS = getattr(sc,'fontSize',fontSize) fC = getattr(sc,'fillColor',fillColor) fL = getattr(sc,'leading',1.2*fontSize) if fN==fontName: fA = (ascent*fS)/fontSize else: fA = getFont(fontName).face.ascent/1000. if fA==0: fA=0.718 fA *= fS if anchor=='left': anchor = 'start' xoffs = x1 elif anchor=='right': anchor = 'end' xoffs = x2 elif anchor=='numeric': xoffs = x2 else: anchor = 'middle' xoffs = 0.5*(x1+x2) for t in lines: aS(String(xoffs+scdx,y+scdy,t,fontName=fN,fontSize=fS,fillColor=fC, textAnchor = anchor)) y -= fL yd = min(yd,y) y += fL for iy, a in ((y-max(fL-fA,0),'underlines'),(y+fA,'overlines')): il = getattr(sc,a,None) if il: if not isinstance(il,(tuple,list)): il = (il,) for l in il: l = copy.copy(l) l.y1 += iy l.y2 += iy l.x1 += x1 l.x2 += x2 aS(l) x = xn y = yd leadingMove = 2*y0-y-thisy if dividerLines: xd = thisx+dx+dxTextSpace+jOffs[-1]+dividerOffsX[1] yd = thisy+dy*0.5+dividerOffsY if ((dividerLines&1) and i%columnMaximum) or ((dividerLines&2) and not i%columnMaximum): g.add(Line(thisx+dividerOffsX[0],yd,xd,yd, strokeColor=dividerColor, strokeWidth=dividerWidth, strokeDashArray=dividerDashArray)) if (dividerLines&4) and (i%columnMaximum==lim or i==(n-1)): yd -= max(deltay,leadingMove)+yGap g.add(Line(thisx+dividerOffsX[0],yd,xd,yd, strokeColor=dividerColor, strokeWidth=dividerWidth, strokeDashArray=dividerDashArray)) # Make a 'normal' color swatch... swatchX = x + getattr(self,'swdx',0) swatchY = thisy + getattr(self,'swdy',0) if isAuto(col): chart = getattr(col,'chart',getattr(col,'obj',None)) c = chart.makeSwatchSample(getattr(col,'index',i),swatchX,swatchY,dx,dy) elif isinstance(col, colors.Color): if isSymbol(swatchMarker): c = uSymbol2Symbol(swatchMarker,swatchX+dx/2.,swatchY+dy/2.,col) else: c = self._defaultSwatch(swatchX,swatchY,dx,dy,fillColor=col,strokeWidth=strokeWidth,strokeColor=strokeColor) elif col is not None: try: c = copy.deepcopy(col) c.x = swatchX c.y = swatchY c.width = dx c.height = dy except: c = None else: c = None if c: g.add(c) if scallout: scallout(self,g,thisx,y0,i,(col,name),c) for s in S: g.add(s) if self.colEndCallout and (i%columnMaximum==lim or i==(n-1)): if alignment == "left": xt = thisx else: xt = thisx+dx+dxTextSpace yd = thisy+dy*0.5+dividerOffsY - (max(deltay,leadingMove)+yGap) self.colEndCallout(self, g, thisx, xt, yd, jOffs[-1], jOffs[-1]+dx+dxTextSpace) if i%columnMaximum==lim: if variColumn: thisx += jOffs[-1]+xW else: thisx = thisx+deltax thisy = upperlefty else: thisy = thisy-max(deltay,leadingMove)-yGap return g
def _getLineCount(s): T = _getLines(s) if isSeqType(s): return max([len(x) for x in T]) else: return len(T)
def _getLines(s): if isSeqType(s): return tuple([(x or '').split('\n') for x in s]) else: return (s or '').split('\n')
def draw(self): colorNamePairs = self.colorNamePairs autoCP = isAuto(colorNamePairs) if autoCP: chart = getattr(colorNamePairs,'chart',getattr(colorNamePairs,'obj',None)) swatchMarker = None autoCP = Auto(obj=chart) n = chart._seriesCount chartTexts = self._getTexts(colorNamePairs) else: swatchMarker = getattr(self,'swatchMarker',None) if isAuto(swatchMarker): chart = getattr(swatchMarker,'chart',getattr(swatchMarker,'obj',None)) swatchMarker = Auto(obj=chart) n = len(colorNamePairs) dx = self.dx dy = self.dy alignment = self.alignment columnMaximum = self.columnMaximum deltax = self.deltax deltay = self.deltay dxTextSpace = self.dxTextSpace fontName = self.fontName fontSize = self.fontSize fillColor = self.fillColor strokeWidth = self.strokeWidth strokeColor = self.strokeColor leading = fontSize*1.2 yGap = self.yGap if not deltay: deltay = max(dy,leading)+self.autoYPadding ba = self.boxAnchor maxWidth = self._calculateMaxWidth(colorNamePairs) nCols = int((n+columnMaximum-1)/columnMaximum) xW = dx+dxTextSpace+self.autoXPadding variColumn = self.variColumn if variColumn: width = reduce(operator.add,maxWidth,0)+xW*(nCols-1) else: deltax = max(maxWidth+xW,deltax) width = maxWidth+(nCols-1)*deltax maxWidth = nCols*[maxWidth] thisx = self.x thisy = self.y - self.dy if ba not in ('ne','n','nw','autoy'): height = self._calcHeight() if ba in ('e','c','w'): thisy += height/2. else: thisy += height if ba not in ('nw','w','sw','autox'): if ba in ('n','c','s'): thisx -= width/2 else: thisx -= width upperlefty = thisy g = Group() def gAdd(t,g=g,fontName=fontName,fontSize=fontSize,fillColor=fillColor): t.fontName = fontName t.fontSize = fontSize t.fillColor = fillColor return g.add(t) ascent=getFont(fontName).face.ascent/1000. if ascent==0: ascent=0.718 # default (from helvetica) ascent *= fontSize # normalize lim = columnMaximum - 1 callout = getattr(self,'callout',None) dividerLines = self.dividerLines if dividerLines: dividerWidth = self.dividerWidth dividerColor = self.dividerColor dividerDashArray = self.dividerDashArray dividerOffsX = self.dividerOffsX dividerOffsY = self.dividerOffsY for i in xrange(n): if autoCP: col = autoCP col.index = i name = chartTexts[i] else: col, name = colorNamePairs[i] if isAuto(swatchMarker): col = swatchMarker col.index = i if isAuto(name): name = getattr(swatchMarker,'chart',getattr(swatchMarker,'obj',None)).getSeriesName(i,'series %d' % i) T = _getLines(name) S = [] j = int(i/columnMaximum) # thisy+dy/2 = y+leading/2 y = y0 = thisy+(dy-ascent)*0.5 if callout: callout(self,g,thisx,y,(col,name)) if alignment == "left": if isSeqType(name): for t in T[0]: S.append(String(thisx,y,t,fontName=fontName,fontSize=fontSize,fillColor=fillColor, textAnchor = "start")) y -= leading yd = y y = y0 for t in T[1]: S.append(String(thisx+maxWidth[j],y,t,fontName=fontName,fontSize=fontSize,fillColor=fillColor, textAnchor = "end")) y -= leading y = min(yd,y) else: for t in T: # align text to left S.append(String(thisx+maxWidth[j],y,t,fontName=fontName,fontSize=fontSize,fillColor=fillColor, textAnchor = "end")) y -= leading x = thisx+maxWidth[j]+dxTextSpace elif alignment == "right": if isSeqType(name): y0 = y for t in T[0]: S.append(String(thisx+dx+dxTextSpace,y,t,fontName=fontName,fontSize=fontSize,fillColor=fillColor, textAnchor = "start")) y -= leading yd = y y = y0 for t in T[1]: S.append(String(thisx+dx+dxTextSpace+maxWidth[j],y,t,fontName=fontName,fontSize=fontSize,fillColor=fillColor, textAnchor = "end")) y -= leading y = min(yd,y) else: for t in T: # align text to right S.append(String(thisx+dx+dxTextSpace,y,t,fontName=fontName,fontSize=fontSize,fillColor=fillColor, textAnchor = "start")) y -= leading x = thisx else: raise ValueError, "bad alignment" leadingMove = 2*y0-y-thisy if dividerLines: xd = thisx+dx+dxTextSpace+maxWidth[j]+dividerOffsX[1] yd = thisy+dy*0.5+dividerOffsY if ((dividerLines&1) and i%columnMaximum) or ((dividerLines&2) and not i%columnMaximum): g.add(Line(thisx+dividerOffsX[0],yd,xd,yd, strokeColor=dividerColor, strokeWidth=dividerWidth, strokeDashArray=dividerDashArray)) if (dividerLines&4) and (i%columnMaximum==lim or i==(n-1)): yd -= max(deltay,leadingMove)+yGap g.add(Line(thisx+dividerOffsX[0],yd,xd,yd, strokeColor=dividerColor, strokeWidth=dividerWidth, strokeDashArray=dividerDashArray)) # Make a 'normal' color swatch... if isAuto(col): chart = getattr(col,'chart',getattr(col,'obj',None)) g.add(chart.makeSwatchSample(getattr(col,'index',i),x,thisy,dx,dy)) elif isinstance(col, colors.Color): if isSymbol(swatchMarker): g.add(uSymbol2Symbol(swatchMarker,x+dx/2.,thisy+dy/2.,col)) else: g.add(self._defaultSwatch(x,thisy,dx,dy,fillColor=col,strokeWidth=strokeWidth,strokeColor=strokeColor)) else: try: c = copy.deepcopy(col) c.x = x c.y = thisy c.width = dx c.height = dy g.add(c) except: pass map(gAdd,S) if self.colEndCallout and (i%columnMaximum==lim or i==(n-1)): if alignment == "left": xt = thisx else: xt = thisx+dx+dxTextSpace yd = thisy+dy*0.5+dividerOffsY - (max(deltay,leadingMove)+yGap) self.colEndCallout(self, g, thisx, xt, yd, maxWidth[j], maxWidth[j]+dx+dxTextSpace) if i%columnMaximum==lim: if variColumn: thisx += maxWidth[j]+xW else: thisx = thisx+deltax thisy = upperlefty else: thisy = thisy-max(deltay,leadingMove)-yGap return g
def _getLineCount(s): T = _getLines(s) if isSeqType(s): return max([len(x) for x in T]) else: return len(T)
def __init__(self, tests, name=None): if not isSeqType(tests): tests = (tests, ) self._tests = tests if name: self._str = name
def breakLines(self, width): """ Returns a broken line structure. There are two cases A) For the simple case of a single formatting input fragment the output is A fragment specifier with - kind = 0 - fontName, fontSize, leading, textColor - lines= A list of lines Each line has two items: 1. unused width in points 2. a list of words B) When there is more than one input formatting fragment the out put is A fragment specifier with - kind = 1 - lines = A list of fragments each having fields: - extraspace (needed for justified) - fontSize - words=word list - each word is itself a fragment with - various settings This structure can be used to easily draw paragraphs with the various alignments. You can supply either a single width or a list of widths; the latter will have its last item repeated until necessary. A 2-element list is useful when there is a different first line indent; a longer list could be created to facilitate custom wraps around irregular objects.""" if not isSeqType(width): maxWidths = [width] else: maxWidths = width lines = [] lineno = 0 maxWidth = maxWidths[lineno] style = self.style fFontSize = float(style.fontSize) requiredWidth = 0 #for bullets, work out width and ensure we wrap the right amount onto line one _handleBulletWidth(self.bulletText,style,maxWidths) self.height = 0 autoLeading = getattr(self,'autoLeading',getattr(style,'autoLeading','')) calcBounds = autoLeading not in ('','off') frags = self.frags nFrags= len(frags) if nFrags==1: f = frags[0] if hasattr(f,'text'): fontSize = f.fontSize fontName = f.fontName ascent, descent = getAscentDescent(fontName,fontSize) kind = 0 L=f.text.split('\n') for l in L: currentWidth = stringWidth(l,fontName,fontSize) requiredWidth = max(currentWidth,requiredWidth) extraSpace = maxWidth-currentWidth lines.append((extraSpace,l.split(' '),currentWidth)) lineno = lineno+1 maxWidth = lineno<len(maxWidths) and maxWidths[lineno] or maxWidths[-1] blPara = f.clone(kind=kind, lines=lines,ascent=ascent,descent=descent,fontSize=fontSize) else: kind = f.kind lines = f.lines for L in lines: if kind==0: currentWidth = L[2] else: currentWidth = L.currentWidth requiredWidth = max(currentWidth,requiredWidth) blPara = f.clone(kind=kind, lines=lines) self.width = max(self.width,requiredWidth) return blPara elif nFrags<=0: return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName, textColor=style.textColor, ascent=style.fontSize,descent=-0.2*style.fontSize, lines=[]) else: for L in _getFragLines(frags): currentWidth, n, w = _getFragWord(L,maxWidth) f = w[0][0] maxSize = f.fontSize maxAscent, minDescent = getAscentDescent(f.fontName,maxSize) words = [f.clone()] words[-1].text = w[0][1] for i in w[1:]: f = i[0].clone() f.text=i[1] words.append(f) fontSize = f.fontSize fontName = f.fontName if calcBounds: cbDefn = getattr(f,'cbDefn',None) if getattr(cbDefn,'width',0): descent,ascent = imgVRange(imgNormV(cbDefn.height,fontSize),cbDefn.valign,fontSize) else: ascent, descent = getAscentDescent(fontName,fontSize) else: ascent, descent = getAscentDescent(fontName,fontSize) maxSize = max(maxSize,fontSize) maxAscent = max(maxAscent,ascent) minDescent = min(minDescent,descent) lineno += 1 maxWidth = lineno<len(maxWidths) and maxWidths[lineno] or maxWidths[-1] requiredWidth = max(currentWidth,requiredWidth) extraSpace = maxWidth - currentWidth lines.append(ParaLines(extraSpace=extraSpace,wordCount=n, words=words, fontSize=maxSize, ascent=maxAscent,descent=minDescent,currentWidth=currentWidth)) self.width = max(self.width,requiredWidth) return ParaLines(kind=1, lines=lines) return lines
def _getStr(s): if isSeqType(s): return map(_getStr,s) else: return _objStr(s)
def _getLines(s): if isSeqType(s): return tuple([(x or '').split('\n') for x in s]) else: return (s or '').split('\n')
def draw(self): colorNamePairs = self.colorNamePairs autoCP = isAuto(colorNamePairs) if autoCP: chart = getattr(colorNamePairs, 'chart', getattr(colorNamePairs, 'obj', None)) swatchMarker = None autoCP = Auto(obj=chart) n = chart._seriesCount chartTexts = self._getTexts(colorNamePairs) else: swatchMarker = getattr(self, 'swatchMarker', None) if isAuto(swatchMarker): chart = getattr(swatchMarker, 'chart', getattr(swatchMarker, 'obj', None)) swatchMarker = Auto(obj=chart) n = len(colorNamePairs) dx = self.dx dy = self.dy alignment = self.alignment columnMaximum = self.columnMaximum deltax = self.deltax deltay = self.deltay dxTextSpace = self.dxTextSpace fontName = self.fontName fontSize = self.fontSize fillColor = self.fillColor strokeWidth = self.strokeWidth strokeColor = self.strokeColor subCols = self.subCols leading = fontSize * 1.2 yGap = self.yGap if not deltay: deltay = max(dy, leading) + self.autoYPadding ba = self.boxAnchor maxWidth = self._calculateMaxBoundaries(colorNamePairs) nCols = int((n + columnMaximum - 1) / (columnMaximum * 1.0)) xW = dx + dxTextSpace + self.autoXPadding variColumn = self.variColumn if variColumn: width = reduce(operator.add, [m[-1] for m in maxWidth], 0) + xW * nCols else: deltax = max(maxWidth[-1] + xW, deltax) width = maxWidth[-1] + nCols * deltax maxWidth = nCols * [maxWidth] thisx = self.x thisy = self.y - self.dy if ba not in ('ne', 'n', 'nw', 'autoy'): height = self._calcHeight() if ba in ('e', 'c', 'w'): thisy += height / 2. else: thisy += height if ba not in ('nw', 'w', 'sw', 'autox'): if ba in ('n', 'c', 's'): thisx -= width / 2 else: thisx -= width upperlefty = thisy g = Group() ascent = getFont(fontName).face.ascent / 1000. if ascent == 0: ascent = 0.718 # default (from helvetica) ascent *= fontSize # normalize lim = columnMaximum - 1 callout = getattr(self, 'callout', None) scallout = getattr(self, 'swatchCallout', None) dividerLines = self.dividerLines if dividerLines: dividerWidth = self.dividerWidth dividerColor = self.dividerColor dividerDashArray = self.dividerDashArray dividerOffsX = self.dividerOffsX dividerOffsY = self.dividerOffsY for i in xrange(n): if autoCP: col = autoCP col.index = i name = chartTexts[i] else: col, name = colorNamePairs[i] if isAuto(swatchMarker): col = swatchMarker col.index = i if isAuto(name): name = getattr(swatchMarker, 'chart', getattr(swatchMarker, 'obj', None)).getSeriesName( i, 'series %d' % i) T = _getLines(name) S = [] aS = S.append j = int(i / (columnMaximum * 1.0)) jOffs = maxWidth[j] # thisy+dy/2 = y+leading/2 y = y0 = thisy + (dy - ascent) * 0.5 if callout: callout(self, g, thisx, y, (col, name)) if alignment == "left": x = thisx xn = thisx + jOffs[-1] + dxTextSpace elif alignment == "right": x = thisx + dx + dxTextSpace xn = thisx else: raise ValueError, "bad alignment" if not isSeqType(name): T = [T] yd = y for k, lines in enumerate(T): y = y0 kk = k * 2 x1 = x + jOffs[kk] x2 = x + jOffs[kk + 1] sc = subCols[k, i] anchor = sc.align fN = getattr(sc, 'fontName', fontName) fS = getattr(sc, 'fontSize', fontSize) fC = getattr(sc, 'fillColor', fillColor) fL = getattr(sc, 'leading', 1.2 * fontSize) if fN == fontName: fA = (ascent * fS) / fontSize else: fA = getFont(fontName).face.ascent / 1000. if fA == 0: fA = 0.718 fA *= fS if anchor == 'left': anchor = 'start' xoffs = x1 elif anchor == 'right': anchor = 'end' xoffs = x2 elif anchor == 'numeric': xoffs = x2 else: anchor = 'middle' xoffs = 0.5 * (x1 + x2) for t in lines: aS( String(xoffs, y, t, fontName=fN, fontSize=fS, fillColor=fC, textAnchor=anchor)) y -= fL yd = min(yd, y) y += fL for iy, a in ((y - max(fL - fA, 0), 'underlines'), (y + fA, 'overlines')): il = getattr(sc, a, None) if il: if not isinstance(il, (tuple, list)): il = (il, ) for l in il: l = copy.copy(l) l.y1 += iy l.y2 += iy l.x1 += x1 l.x2 += x2 aS(l) x = xn y = yd leadingMove = 2 * y0 - y - thisy if dividerLines: xd = thisx + dx + dxTextSpace + jOffs[-1] + dividerOffsX[1] yd = thisy + dy * 0.5 + dividerOffsY if ((dividerLines & 1) and i % columnMaximum) or ( (dividerLines & 2) and not i % columnMaximum): g.add( Line(thisx + dividerOffsX[0], yd, xd, yd, strokeColor=dividerColor, strokeWidth=dividerWidth, strokeDashArray=dividerDashArray)) if (dividerLines & 4) and (i % columnMaximum == lim or i == (n - 1)): yd -= max(deltay, leadingMove) + yGap g.add( Line(thisx + dividerOffsX[0], yd, xd, yd, strokeColor=dividerColor, strokeWidth=dividerWidth, strokeDashArray=dividerDashArray)) # Make a 'normal' color swatch... if isAuto(col): chart = getattr(col, 'chart', getattr(col, 'obj', None)) c = chart.makeSwatchSample(getattr(col, 'index', i), x, thisy, dx, dy) elif isinstance(col, colors.Color): if isSymbol(swatchMarker): c = uSymbol2Symbol(swatchMarker, x + dx / 2., thisy + dy / 2., col) else: c = self._defaultSwatch(x, thisy, dx, dy, fillColor=col, strokeWidth=strokeWidth, strokeColor=strokeColor) elif col is not None: try: c = copy.deepcopy(col) c.x = x c.y = thisy c.width = dx c.height = dy except: c = None else: c = None if c: g.add(c) if scallout: scallout(self, g, thisx, y0, i, (col, name), c) for s in S: g.add(s) if self.colEndCallout and (i % columnMaximum == lim or i == (n - 1)): if alignment == "left": xt = thisx else: xt = thisx + dx + dxTextSpace yd = thisy + dy * 0.5 + dividerOffsY - ( max(deltay, leadingMove) + yGap) self.colEndCallout(self, g, thisx, xt, yd, jOffs[-1], jOffs[-1] + dx + dxTextSpace) if i % columnMaximum == lim: if variColumn: thisx += jOffs[-1] + xW else: thisx = thisx + deltax thisy = upperlefty else: thisy = thisy - max(deltay, leadingMove) - yGap return g
def _getStr(s): if isSeqType(s): return map(_getStr, s) else: return _objStr(s)
def breakLines(self, width): """ Returns a broken line structure. There are two cases A) For the simple case of a single formatting input fragment the output is A fragment specifier with - kind = 0 - fontName, fontSize, leading, textColor - lines= A list of lines Each line has two items: 1. unused width in points 2. a list of words B) When there is more than one input formatting fragment the out put is A fragment specifier with - kind = 1 - lines = A list of fragments each having fields: - extraspace (needed for justified) - fontSize - words=word list - each word is itself a fragment with - various settings This structure can be used to easily draw paragraphs with the various alignments. You can supply either a single width or a list of widths; the latter will have its last item repeated until necessary. A 2-element list is useful when there is a different first line indent; a longer list could be created to facilitate custom wraps around irregular objects.""" if not isSeqType(width): maxWidths = [width] else: maxWidths = width lines = [] lineno = 0 maxWidth = maxWidths[lineno] style = self.style fFontSize = float(style.fontSize) requiredWidth = 0 #for bullets, work out width and ensure we wrap the right amount onto line one _handleBulletWidth(self.bulletText, style, maxWidths) self.height = 0 autoLeading = getattr(self, 'autoLeading', getattr(style, 'autoLeading', '')) calcBounds = autoLeading not in ('', 'off') frags = self.frags nFrags = len(frags) if nFrags == 1: f = frags[0] if hasattr(f, 'text'): fontSize = f.fontSize fontName = f.fontName ascent, descent = getAscentDescent(fontName, fontSize) kind = 0 L = f.text.split('\n') for l in L: currentWidth = stringWidth(l, fontName, fontSize) requiredWidth = max(currentWidth, requiredWidth) extraSpace = maxWidth - currentWidth lines.append((extraSpace, l.split(' '), currentWidth)) lineno = lineno + 1 maxWidth = lineno < len( maxWidths) and maxWidths[lineno] or maxWidths[-1] blPara = f.clone(kind=kind, lines=lines, ascent=ascent, descent=descent, fontSize=fontSize) else: kind = f.kind lines = f.lines for L in lines: if kind == 0: currentWidth = L[2] else: currentWidth = L.currentWidth requiredWidth = max(currentWidth, requiredWidth) blPara = f.clone(kind=kind, lines=lines) self.width = max(self.width, requiredWidth) return blPara elif nFrags <= 0: return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName, textColor=style.textColor, ascent=style.fontSize, descent=-0.2 * style.fontSize, lines=[]) else: for L in _getFragLines(frags): currentWidth, n, w = _getFragWord(L, maxWidth) f = w[0][0] maxSize = f.fontSize maxAscent, minDescent = getAscentDescent(f.fontName, maxSize) words = [f.clone()] words[-1].text = w[0][1] for i in w[1:]: f = i[0].clone() f.text = i[1] words.append(f) fontSize = f.fontSize fontName = f.fontName if calcBounds: cbDefn = getattr(f, 'cbDefn', None) if getattr(cbDefn, 'width', 0): descent, ascent = imgVRange( imgNormV(cbDefn.height, fontSize), cbDefn.valign, fontSize) else: ascent, descent = getAscentDescent( fontName, fontSize) else: ascent, descent = getAscentDescent(fontName, fontSize) maxSize = max(maxSize, fontSize) maxAscent = max(maxAscent, ascent) minDescent = min(minDescent, descent) lineno += 1 maxWidth = lineno < len( maxWidths) and maxWidths[lineno] or maxWidths[-1] requiredWidth = max(currentWidth, requiredWidth) extraSpace = maxWidth - currentWidth lines.append( ParaLines(extraSpace=extraSpace, wordCount=n, words=words, fontSize=maxSize, ascent=maxAscent, descent=minDescent, currentWidth=currentWidth)) self.width = max(self.width, requiredWidth) return ParaLines(kind=1, lines=lines) return lines