예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
    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
예제 #4
0
    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