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.""" self._width_max = 0 if not isSeq(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) if currentWidth > self._width_max: self._width_max = currentWidth 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 if currentWidth > self._width_max: self._width_max = currentWidth lines.append( ParaLines(extraSpace=extraSpace, wordCount=n, words=words, fontSize=maxSize, ascent=maxAscent, descent=minDescent, currentWidth=currentWidth, preformatted=True)) self.width = max(self.width, requiredWidth) return ParaLines(kind=1, lines=lines) return lines
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 isSeq(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 breakLines(self, width): if not isinstance(width, ListType): maxWidths = [width] else: maxWidths = width lines = [] lineno = 0 style = self.style fFontSize = float(style.fontSize) #for bullets, work out width and ensure we wrap the right amount onto line one _handleBulletWidth(self.bulletText,style,maxWidths) maxWidth = maxWidths[0] self.height = 0 frags = self.frags nFrags= len(frags) if nFrags==1 and not hasattr(frags[0],'cbDefn'): f = frags[0] fontSize = f.fontSize fontName = f.fontName words = hasattr(f,'text') and split(f.text, ' ') or f.words spaceWidth = stringWidth(' ', fontName, fontSize, self.encoding) cLine = [] currentWidth = - spaceWidth # hack to get around extra space for word 1 newwords = [] for word in words: #this underscores my feeling that Unicode throughout would be easier! wordWidth = stringWidth(word, fontName, fontSize, self.encoding) #Hyphenate long words in the paragraph to fit an area of width self.blockwidth charwidth = int(ceil(wordWidth / len(word))) charinline = int(floor(self.blockwidth / charwidth)) # print word # print 'wordWidth', wordWidth # print 'self.blockwidth', self.blockwidth # print 'len(word)', len(word) # print 'charwidth', charwidth # print 'charinline', charinline # print range(0, int(ceil(wordWidth / self.blockwidth))) newtext = '' diff = 0 for i in range(0, 1 + int(ceil(wordWidth / self.blockwidth))): # print 'i = ', i # print i * charinline # print (i + 1) * charinline # print self.text[i * charinline:(i + 1) * charinline] # newtext = '%s%s ' % (newtext, word[i * charinline:(i + 1) * charinline]) max = (i + 1) * charinline min = (i * charinline) - diff for s in self.splitter: p = word.find(s, max - 10, max) if p < max and p > 0: diff = max - p - 1 max = p + 1 else: diff = 0 newwords.append(word[min:max]) # print stringWidth(word[i * charinline:(i + 1) * charinline], # fontName, fontSize, self.encoding) # print len(word[i * charinline:(i + 1) * charinline]) # print newwords for word in newwords: newWidth = currentWidth + spaceWidth + wordWidth if newWidth <= maxWidth or not len(cLine): # fit one more on this line cLine.append(word) currentWidth = newWidth else: if currentWidth > self.width: self.width = currentWidth #end of line lines.append((maxWidth - currentWidth, cLine)) cLine = [word] currentWidth = wordWidth lineno += 1 try: maxWidth = maxWidths[lineno] except IndexError: maxWidth = maxWidths[-1] # use the last one #deal with any leftovers on the final line if cLine!=[]: if currentWidth>self.width: self.width = currentWidth lines.append((maxWidth - currentWidth, cLine)) return f.clone(kind=0, lines=lines) elif nFrags<=0: return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName, textColor=style.textColor, lines=[]) else: if hasattr(self,'blPara') and getattr(self,'_splitpara',0): #NB this is an utter hack that awaits the proper information #preserving splitting algorithm return self.blPara n = 0 words = [] for w in _getFragWords(frags): spaceWidth = stringWidth(' ',w[-1][0].fontName, w[-1][0].fontSize) print('133', w) if n==0: currentWidth = -spaceWidth # hack to get around extra space for word 1 maxSize = 0 wordWidth = w[0] f = w[1][0] if wordWidth>0: newWidth = currentWidth + spaceWidth + wordWidth else: newWidth = currentWidth #test to see if this frag is a line break. If it is we will only act on it #if the current width is non-negative or the previous thing was a deliberate lineBreak lineBreak = hasattr(f,'lineBreak') endLine = (newWidth>maxWidth and n>0) or lineBreak if not endLine: if lineBreak: continue #throw it away nText = w[1][1] if nText: n += 1 maxSize = max(maxSize,f.fontSize) if words==[]: g = f.clone() words = [g] g.text = nText elif not _sameFrag(g,f): if currentWidth>0 and ((nText!='' and nText[0]!=' ') or hasattr(f,'cbDefn')): if hasattr(g,'cbDefn'): i = len(words)-1 while hasattr(words[i],'cbDefn'): i -= 1 words[i].text += ' ' else: g.text += ' ' g = f.clone() words.append(g) g.text = nText else: if nText!='' and nText[0]!=' ': g.text += ' ' + nText for i in w[2:]: g = i[0].clone() g.text=i[1] words.append(g) maxSize = max(maxSize,g.fontSize) currentWidth = newWidth else: #either it won't fit, or it's a lineBreak tag if lineBreak: g = f.clone() #del g.lineBreak words.append(g) if currentWidth>self.width: self.width = currentWidth #end of line lines.append(FragLine(extraSpace=(maxWidth - currentWidth),wordCount=n, words=words, fontSize=maxSize)) #start new line lineno += 1 try: maxWidth = maxWidths[lineno] except IndexError: maxWidth = maxWidths[-1] # use the last one if lineBreak: n = 0 words = [] continue currentWidth = wordWidth n = 1 maxSize = f.fontSize g = f.clone() words = [g] g.text = w[1][1] for i in w[2:]: g = i[0].clone() g.text=i[1] words.append(g) maxSize = max(maxSize,g.fontSize) #deal with any leftovers on the final line if words!=[]: if currentWidth>self.width: self.width = currentWidth lines.append(ParaLines(extraSpace=(maxWidth - currentWidth),wordCount=n, words=words, fontSize=maxSize)) return ParaLines(kind=1, lines=lines) return lines
def breakLines(self, width): if not isinstance(width, ListType): maxWidths = [width] else: maxWidths = width lines = [] lineno = 0 style = self.style fFontSize = float(style.fontSize) #for bullets, work out width and ensure we wrap the right amount onto line one _handleBulletWidth(self.bulletText, style, maxWidths) maxWidth = maxWidths[0] self.height = 0 frags = self.frags nFrags = len(frags) if nFrags == 1 and not hasattr(frags[0], 'cbDefn'): f = frags[0] fontSize = f.fontSize fontName = f.fontName words = hasattr(f, 'text') and split(f.text, ' ') or f.words spaceWidth = stringWidth(' ', fontName, fontSize, self.encoding) cLine = [] currentWidth = -spaceWidth # hack to get around extra space for word 1 newwords = [] for word in words: #this underscores my feeling that Unicode throughout would be easier! wordWidth = stringWidth(word, fontName, fontSize, self.encoding) #Hyphenate long words in the paragraph to fit an area of width self.blockwidth charwidth = int(ceil(wordWidth / len(word))) charinline = int(floor(self.blockwidth / charwidth)) # print word # print 'wordWidth', wordWidth # print 'self.blockwidth', self.blockwidth # print 'len(word)', len(word) # print 'charwidth', charwidth # print 'charinline', charinline # print range(0, int(ceil(wordWidth / self.blockwidth))) newtext = '' diff = 0 for i in range(0, 1 + int(ceil(wordWidth / self.blockwidth))): # print 'i = ', i # print i * charinline # print (i + 1) * charinline # print self.text[i * charinline:(i + 1) * charinline] # newtext = '%s%s ' % (newtext, word[i * charinline:(i + 1) * charinline]) max = (i + 1) * charinline min = (i * charinline) - diff for s in self.splitter: p = word.find(s, max - 10, max) if p < max and p > 0: diff = max - p - 1 max = p + 1 else: diff = 0 newwords.append(word[min:max]) # print stringWidth(word[i * charinline:(i + 1) * charinline], # fontName, fontSize, self.encoding) # print len(word[i * charinline:(i + 1) * charinline]) # print newwords for word in newwords: newWidth = currentWidth + spaceWidth + wordWidth if newWidth <= maxWidth or not len(cLine): # fit one more on this line cLine.append(word) currentWidth = newWidth else: if currentWidth > self.width: self.width = currentWidth #end of line lines.append((maxWidth - currentWidth, cLine)) cLine = [word] currentWidth = wordWidth lineno += 1 try: maxWidth = maxWidths[lineno] except IndexError: maxWidth = maxWidths[-1] # use the last one #deal with any leftovers on the final line if cLine != []: if currentWidth > self.width: self.width = currentWidth lines.append((maxWidth - currentWidth, cLine)) return f.clone(kind=0, lines=lines) elif nFrags <= 0: return ParaLines(kind=0, fontSize=style.fontSize, fontName=style.fontName, textColor=style.textColor, lines=[]) else: if hasattr(self, 'blPara') and getattr(self, '_splitpara', 0): #NB this is an utter hack that awaits the proper information #preserving splitting algorithm return self.blPara n = 0 words = [] for w in _getFragWords(frags): spaceWidth = stringWidth(' ', w[-1][0].fontName, w[-1][0].fontSize) print('133', w) if n == 0: currentWidth = -spaceWidth # hack to get around extra space for word 1 maxSize = 0 wordWidth = w[0] f = w[1][0] if wordWidth > 0: newWidth = currentWidth + spaceWidth + wordWidth else: newWidth = currentWidth #test to see if this frag is a line break. If it is we will only act on it #if the current width is non-negative or the previous thing was a deliberate lineBreak lineBreak = hasattr(f, 'lineBreak') endLine = (newWidth > maxWidth and n > 0) or lineBreak if not endLine: if lineBreak: continue #throw it away nText = w[1][1] if nText: n += 1 maxSize = max(maxSize, f.fontSize) if words == []: g = f.clone() words = [g] g.text = nText elif not _sameFrag(g, f): if currentWidth > 0 and ( (nText != '' and nText[0] != ' ') or hasattr(f, 'cbDefn')): if hasattr(g, 'cbDefn'): i = len(words) - 1 while hasattr(words[i], 'cbDefn'): i -= 1 words[i].text += ' ' else: g.text += ' ' g = f.clone() words.append(g) g.text = nText else: if nText != '' and nText[0] != ' ': g.text += ' ' + nText for i in w[2:]: g = i[0].clone() g.text = i[1] words.append(g) maxSize = max(maxSize, g.fontSize) currentWidth = newWidth else: #either it won't fit, or it's a lineBreak tag if lineBreak: g = f.clone() #del g.lineBreak words.append(g) if currentWidth > self.width: self.width = currentWidth #end of line lines.append( FragLine(extraSpace=(maxWidth - currentWidth), wordCount=n, words=words, fontSize=maxSize)) #start new line lineno += 1 try: maxWidth = maxWidths[lineno] except IndexError: maxWidth = maxWidths[-1] # use the last one if lineBreak: n = 0 words = [] continue currentWidth = wordWidth n = 1 maxSize = f.fontSize g = f.clone() words = [g] g.text = w[1][1] for i in w[2:]: g = i[0].clone() g.text = i[1] words.append(g) maxSize = max(maxSize, g.fontSize) #deal with any leftovers on the final line if words != []: if currentWidth > self.width: self.width = currentWidth lines.append( ParaLines(extraSpace=(maxWidth - currentWidth), wordCount=n, words=words, fontSize=maxSize)) return ParaLines(kind=1, lines=lines) return lines