def TrimStringToFit(canvas, s, fontname, fontsize, toWidth): sn = s sw = canvas.stringWidth(sn, fontname, fontsize) while sw > toWidth: sn = sn[:-1] sw = canvas.stringWidth(sn, fontname, fontsize) return sn
def wrapText(cls, canvas, text, maxWidth, maxLines=None, append=u'...'): words = text.split(' ') currentWordIndex = 0 lines = [] while currentWordIndex < len(words): currentLine = words[currentWordIndex] currentWordIndex += 1 while currentWordIndex + 1 < len(words) and \ canvas.stringWidth(currentLine + " " + \ words[currentWordIndex + 1]) < maxWidth: currentLine += ' ' + words[currentWordIndex] currentWordIndex += 1 lines.append(currentLine) if maxLines is not None and maxLines < len(lines): lines = lines[:maxLines] while canvas.stringWidth(lines[-1] + append) > maxWidth: # Remove words from the end until there's room for "..." newline = lines[maxLines-1].rsplit(' ', 1)[0] if newline == lines[maxLines-1]: lines.pop() else: lines[-1] = newline lines[-1] += append return lines
def __init__(self, canvas, maxWidth, maxHeight): self.topBorderStr = u'\u00f9\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fb' # we draw the left border character (which includes the rank number), # eight squares, and then the right border character self.widthInChessChars = 1 + 8 + 1 # we draw the top border character, the 8 squares in a file, # and the bottom border character (which includes the file name) self.heightInChessChars = 1 + 8 + 1 self.maxWidth = maxWidth self.maxHeight = maxHeight self.canvas = canvas # increase the font size until we surpass the limits, then decrement back self.fontSymSize = 1 while 1: canvas.setFont('ChessAlpha2', self.fontSymSize) candidateWidth = canvas.stringWidth(self.topBorderStr) if candidateWidth > maxWidth: break if self.fontSymSize * self.heightInChessChars > maxHeight: break self.fontSymSize += 1 self.fontSymSize -= 1 self.fontTextSize = self.fontSymSize - 8 # final calculations canvas.setFont('ChessAlpha2', self.fontSymSize) self.width = self.height = canvas.stringWidth(self.topBorderStr)
def wrapText(cls, canvas, text, maxWidth, maxLines=None, append=u'...'): words = text.split(' ') currentWordIndex = 0 lines = [] while currentWordIndex < len(words): currentLine = words[currentWordIndex] currentWordIndex += 1 while currentWordIndex + 1 < len(words) and \ canvas.stringWidth(currentLine + " " + \ words[currentWordIndex + 1]) < maxWidth: currentLine += ' ' + words[currentWordIndex] currentWordIndex += 1 lines.append(currentLine) if maxLines is not None and maxLines < len(lines): lines = lines[:maxLines] while canvas.stringWidth(lines[-1] + append) > maxWidth: # Remove words from the end until there's room for "..." newline = lines[maxLines - 1].rsplit(' ', 1)[0] if newline == lines[maxLines - 1]: lines.pop() else: lines[-1] = newline lines[-1] += append return lines
def getNameFontSize(canvas, name): #generate strings of names that will be on the name tag. fieldWidth = 252 nameFontSize = 45 nameFont = 'Raleway Bold' threshold = fieldWidth * .90 sw = canvas.stringWidth(name, nameFont, nameFontSize) while sw > threshold: nameFontSize = nameFontSize - 0.1 sw = canvas.stringWidth(name, nameFont, nameFontSize) # if nameFontSize < 30: # nameSplit = name.split() # lastName = nameSplit[-1][0] + '.' # print('last name is replaced to the first letter ' , name ) # nameSplit.pop() # if len(nameSplit) > 1: # firstName = ' '.join(nameSplit) # else: # firstName = nameSplit[0] # name = ' '.join([firstName, lastName]) # nameFontSize = 40 # sw = canvas.stringWidth(name,nameFont,nameFontSize) # while sw > threshold: # nameFontSize = nameFontSize - 0.1 # sw = canvas.stringWidth(name,nameFont,nameFontSize) return nameFontSize
def __init__(self, canvas, maxWidth, maxHeight): self.topBorderStr = u"\u00f9\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fa\u00fb" # we draw the left border character (which includes the rank number), # eight squares, and then the right border character self.widthInChessChars = 1 + 8 + 1 # we draw the top border character, the 8 squares in a file, # and the bottom border character (which includes the file name) self.heightInChessChars = 1 + 8 + 1 self.maxWidth = maxWidth self.maxHeight = maxHeight self.canvas = canvas # increase the font size until we surpass the limits, then decrement back self.fontSymSize = 1 while 1: canvas.setFont("ChessAlpha2", self.fontSymSize) candidateWidth = canvas.stringWidth(self.topBorderStr) if candidateWidth > maxWidth: break if self.fontSymSize * self.heightInChessChars > maxHeight: break self.fontSymSize += 1 self.fontSymSize -= 1 self.fontTextSize = self.fontSymSize - 8 # final calculations canvas.setFont("ChessAlpha2", self.fontSymSize) self.width = self.height = canvas.stringWidth(self.topBorderStr)
def writeText(canvas, style, string, size, vpos, width, **kwargs): """ Wrapper function to conveniently write text and return how much vertical space it took up. """ align = kwargs.get('align', 'centre') if align == 'centre' or align == 'center': hpos = kwargs.get('hpos', width / 2) elif align == 'left': hpos = kwargs.get('hpos', 0) elif align == 'right': hpos = kwargs.get('hpos', width) spacing = kwargs.get('spacing', style.lineSpacing) canvas.setFont(style.font, size) if align == 'centre' or align == 'center': canvas.drawCentredString(hpos, vpos - (0.75 * size * spacing), string) elif align == 'left': canvas.drawString(hpos, vpos - (0.75 * size * spacing), string) elif align == 'right': canvas.drawString(hpos - canvas.stringWidth(string), vpos - (0.75 * size * spacing), string) return size * style.lineSpacing
def word_wrap(text: str, width: int, canvas: 'canvas.Canvas') -> \ Generator[str, None, None]: """Делит text на части, если текст не помещается в width Args: text: текст width: ширина поля canvas: canvas Возвращает подстроки максимальной длины, не превышающей заданную ширину width, разбиение на подстроки по пробелам """ while True: tail = '' tail_words = [] while canvas.stringWidth(text) > width: words = text.split() if len(words) > 1: # перенос по словам text = ' '.join(words[:-1]) tail_words = words[-1:] + tail_words else: # перенос по буквам tail = text[-1:] + tail text = text[:-1] # если даже одна буква не помещается if not text: text = ' '.join([tail[1:], ] + tail_words).strip() yield tail[:1] yield text # выходим, если хвост пустой text = ' '.join([tail, ] + tail_words).strip() if not text: break
def print_line(canvas, y, fontsize, line, force=False): """Prints one line of text on the left-hand side of the label. :param canvas: ReportLab canvas object :param y: vertical coordinate of the lower left corner of the printed text. Note that the origin of the coordinate system is the lower left of the paper. :param fontsize: font size of the text :param line: the text to be printed; it must not contain line breaks :param force: whether `ExcessException` should be raised if the text has to be compressed too much; if ``True``, the text may be compressed as much as necessary :type canvas: canvas.Canvas :type y: float :type fontsize: float :type line: unicode :type force: bool :raises ExcessException: if the line is too long and `force` is ``False`` """ textobject = canvas.beginText() textobject.setFont(institute.reportlab_config.default_fontname, fontsize) width = canvas.stringWidth(line, institute.reportlab_config.default_fontname, fontsize) excess = width / max_width_text if excess > 2 and not force: raise ExcessException elif excess > 1: textobject.setHorizScale(100 / excess) textobject.setTextOrigin(horizontal_margin, y + vertical_margin + vertical_relative_offset * fontsize) textobject.textOut(line) canvas.drawText(textobject)
def el_encogedor_de_fuentes_de_doraemon(canvas, fuente, tamannoini, xini, xfin, y, texto, alineacion = -1): """ Comenzando por el tamaño inicial "tamannoini", encoge el texto hasta que quepa en los límites fijados y después lo escribe. Convierte el texto por si está en una codificación no soportada. Al finalizar, devuelve las propiedades de texto del canvas a su estado original y la fuente a su tamaño inicial. NO AVANZA LÍNEA. Si alineacion == -1: Alineación a la izquierda. Si 0, centrado y si 1, a la derecha. """ # PLAN: No estaría mal pasar un tamaño mínimo de fuente, y si se alcanza o se supera, cortar la línea con # agregarFila y el último tamaño de fuente válido. Claro que entonces habría que devolver también las líneas # avanzadas, etc... canvas.saveState() size = tamannoini texto = escribe(texto) while canvas.stringWidth(texto, fuente, size) > (xfin - xini) and size > 4: size -= 1 canvas.setFont(fuente, size) if alineacion == -1: canvas.drawString(xini, y, texto) elif alineacion == 1: canvas.drawRightString(xfin, y, texto) elif alineacion == 0: canvas.drawCentredString((xfin + xini) / 2.0, y, texto) else: print "geninformes.py::el_encogedor_de_fuentes_de_doraemon -> Error alineación. Uso alineación a la izquierda por defecto." canvas.drawString(xini, y, texto) canvas.restoreState()
def __init__(self, canvas, x, y, width, height=0, font=FONT, fontsize=FONTSIZE, align=ALIGN, lineheight=LINEHEIGHT, move_cursor=False): # Make sure these values aren't strings fontsize = float(fontsize) lineheight = float(lineheight) self.canvas = canvas self.font = font self.fontsize = fontsize self.align = align self.x = x self.y = y self.width = width self.move_cursor = move_cursor # Lineheight self.lineheight = fontsize * lineheight # If height was specified. Start 1 line below. self.first_line = y if height: self.first_line += height - self.lineheight self.text = canvas.beginText() # Set font self.text.setFont(self.font, self.fontsize) self.text.setTextOrigin(x, self.first_line) self.space_width = canvas.stringWidth(' ', font, fontsize)
def __init__(self, canvas, x, y, width, height, font='Helvetica', fontsize=11, align='left', lineheight=1, move_cursor=False): # Make sure these values aren't strings fontsize = float(fontsize) lineheight = float(lineheight) self.canvas = canvas self.font = font self.fontsize = fontsize self.align = align self.x = x self.y = y self.height = height self.width = width self.move_cursor = move_cursor # Regular lineheight self.lineheight = fontsize / 72.0 * units.inch self.first_line = y + height - self.lineheight # Adjusted lineheight self.lineheight *= lineheight self.text = canvas.beginText() self.text.setTextOrigin(x, self.first_line) self.space_width = canvas.stringWidth(' ', font, fontsize)
def contactleftFirstPage(canvas): textobject = canvas.beginText() addrwidth = canvas.stringWidth('510 Victoria Ave, Venice CA 90291','Akkurat',10) urlwidth = canvas.stringWidth('www.leftfieldlabs.com','Akkurat',10) urlx = addrwidth - urlwidth + 18 phonewidth = canvas.stringWidth('424-500-2045','Akkurat',10) phonex = addrwidth - phonewidth + 18 textobject.setTextOrigin(18,75) textobject.setFont('Akkurat',10) textobject.textLine('510 Victoria Ave, Venice CA 90291') yy = textobject.getY() textobject.setTextOrigin(urlx,yy) textobject.textLine('www.leftfieldlabs.com') yyy = textobject.getY() textobject.setTextOrigin(phonex,yyy) textobject.textLine('424-500-2045') canvas.drawText(textobject)
def get_right_align_x_position(self, canvas, text, font, font_size, align_to): if align_to > self._width: align_to = self._width - 10 width = canvas.stringWidth(text, font, font_size) # Alight the text so it ends at the align to point # (hopefully the RHS of the main text) return align_to - width
def TrimStringWithFunction(canvas, s, fontname, fontsize, toWidth, func): try: sw = canvas.stringWidth(s, fontname, fontsize) fontname_ = fontname except: sw = canvas.stringWidth(s, DEF_FONT_NAME, fontsize) fontname_ = DEF_FONT_NAME level = 0 sn = s while sw > toWidth and level < 8: sn = func(sn, level) sw = canvas.stringWidth(sn, fontname_, fontsize) # print("level: %d w=%.0f sw=%.0f s=%s sn=%s" % (level, toWidth, sw, s, sn)) level += 1 while sw > toWidth: sn = sn[:-1] sw = canvas.stringWidth(sn, fontname_, fontsize) return sn
def writeWithWrap(canvas, text, x, y, maxWidth, textHeight): # slice the lines lines = [] end = 0 while text: # travel right until width is exceeded i = 0 while 1: if canvas.stringWidth(text[0:i]) > maxWidth: break i += 1 if i >= len(text): end = 1 break # then travel left until the next space while not end: if text[i] == ' ' and canvas.stringWidth(text[0:i]) <= maxWidth: break i -= 1 if i <= 0: raise Exception("word too long!") # then cut it lines.append(text[0:i]) # next text = text[i + 1:] # now go backwards, printing the lines bottom up y -= textHeight for line in lines: #print "putting line \"%s\" at (%d,%d)" % (line, x, y) canvas.drawString(x, y, line) y -= textHeight
def writeWithWrap(canvas, text, x, y, maxWidth, textHeight): # slice the lines lines = [] end = 0 while text: # travel right until width is exceeded i = 0 while 1: if canvas.stringWidth(text[0:i]) > maxWidth: break i += 1 if i >= len(text): end = 1 break # then travel left until the next space while not end: if text[i] == " " and canvas.stringWidth(text[0:i]) <= maxWidth: break i -= 1 if i <= 0: raise Exception("word too long!") # then cut it lines.append(text[0:i]) # next text = text[i + 1 :] # now go backwards, printing the lines bottom up y -= textHeight for line in lines: # print "putting line \"%s\" at (%d,%d)" % (line, x, y) canvas.drawString(x, y, line) y -= textHeight
def centred_text(canvas, x, y, row, what): x_centre = x + size[0] / 2.0 canvas.saveState() for font_size in range(12, 5, -1): canvas.setFontSize(font_size) if canvas.stringWidth(what) < size[0]: break else: print("Warning: text", what, "too wide") offset = row * size[1] / 4.0 canvas.drawCentredString(x_centre, y + offset, what) canvas.restoreState()
def contactleftLaterPages(canvas): textobject = canvas.beginText() lflwidth = canvas.stringWidth('LEFT FIELD LABS','Gridnik',12) addrwidth = canvas.stringWidth('510 Victoria Ave, Venice CA 90291','Akkurat',10) urlwidth = canvas.stringWidth('www.leftfieldlabs.com','Akkurat',10) phonewidth = canvas.stringWidth('424-500-2045','Akkurat',10) phonex = addrwidth - phonewidth + 18 lflx = addrwidth - lflwidth + 18 urlx = addrwidth - urlwidth + 18 textobject.setTextOrigin(lflx,75) textobject.setFont('Gridnik',12) textobject.textLine('LEFT FIELD LABS') y = textobject.getY() textobject.setTextOrigin(18,y) textobject.setFont('Akkurat',10) textobject.textLine('510 Victoria Ave, Venice CA 90291') yy = textobject.getY() textobject.setTextOrigin(urlx,yy) textobject.textLine('www.leftfieldlabs.com') yyy = textobject.getY() textobject.setTextOrigin(phonex,yyy) textobject.textLine('424-500-2045') canvas.drawText(textobject)
def draw(self): canvas = self.canv if type(self.label) != six.text_type: self.label = self.label.decode("iso-8859-15") # Texte label canvas.setFillColorRGB(0, 0, 0) canvas.setFont("Helvetica-Bold", 11) canvas.drawString(35, 0, self.label) # Ligne noire tailleLigne = LARGEUR_PAGE - (75 * 2) largeurLabel = canvas.stringWidth(self.label, "Helvetica-Bold", 11) canvas.line(0, 3, 30, 3) canvas.line(largeurLabel + 10 + 30, 3, tailleLigne, 3) canvas.rect(30, -3, largeurLabel + 10, 13, fill=0) canvas.line(0, 3.5, 0, -8)
def drawStringExt(canvas, x, y, text, width, sep): segments = [] words = text.split() segment = "" while len(words) > 0: word = words.pop(0) if canvas.stringWidth(segment + word) > width: segments.append(segment) segment = "" segment += word + " " segments.append(segment) off = 0 for segment in segments: canvas.drawString(x, y - off, segment) off += sep return off
def draw(self): canvas = self.canv if type(self.label) != six.text_type : self.label = self.label.decode("iso-8859-15") # Texte label canvas.setFillColorRGB(0, 0, 0) canvas.setFont("Helvetica-Bold", 11) canvas.drawString(35, 0, self.label) # Ligne noire tailleLigne = LARGEUR_PAGE- (75*2) largeurLabel = canvas.stringWidth(self.label, "Helvetica-Bold", 11) canvas.line(0, 3, 30, 3) canvas.line(largeurLabel + 10 + 30, 3, tailleLigne, 3) canvas.rect(30, -3, largeurLabel+10, 13, fill=0) canvas.line(0, 3.5, 0, -8)
def text_wrap(text: str, width: int, canvas: 'canvas.Canvas') -> \ Generator[str, None, None]: """Делит text на части, если текст не помещается в width Args: text: текст width: ширина поля canvas: canvas Возвращает подстроки максимальной длины, не превышающей заданную ширину width, разбиение на подстроки по пробелам """ last_space = 0 text_start = 0 word_len = 0 cur_text_len = 0 for i in range(len(text)): # длина очередного символа нужна заранее symbol_len = canvas.stringWidth(text[i]) # запоминаем позицию пробела или вычисляем длину очередного слова if text[i] == ' ': last_space = i word_len = 0 else: word_len += symbol_len # если длина части текста превысила допустимое значение, то возвращаем текст cur_text_len += symbol_len if cur_text_len > width: cur_text_len = word_len # если слово поместилось, то перенос по пробелу if text_start < last_space: yield text[text_start:last_space] text_start = last_space + 1 # иначе переносим по буквам else: yield text[text_start:i] text_start = i word_len = symbol_len cur_text_len = symbol_len # возвращаем оставшийся кусочек текста yield text[text_start:]
def _draw_back(self, canvas): super()._draw_back(canvas) canvas.setFillColor("white") self.fonts.set_font(canvas, "category") left_of_category_text = self.width + self.border_front[Border.LEFT] width_of_category_text = canvas.stringWidth(self.category) canvas.drawString( left_of_category_text, self.category_bottom, self.category, ) if self.subcategory is not None: self.fonts.set_font(canvas, "subcategory") canvas.drawString( left_of_category_text + width_of_category_text + 1 * mm, self.category_bottom, "({})".format(self.subcategory), )
def SplitStringToFit(canvas, s, fontname, fontsize, toWidth): words = s.split() lines = [] line = [] line_sum = 0 for word in words: sw = canvas.stringWidth(word, fontname, fontsize) if "`" in word: w = word.replace("`", "") line.append(w) lines.append(" ".join(line)) line_sum = 0 line = [] elif line_sum + sw < toWidth: line_sum += sw line.append(word) else: lines.append(" ".join(line)) line_sum = sw line = [word] lines.append(" ".join(line)) return lines
decalage = 0 indiceColonneReponse = 1 ## Affichage des réponses for j in range(len(reponses)): x = textObject.getX() y = textObject.getY() textObject.moveCursor(15, 0) if colonnes == 2: intitule = "\n".join(wrap(reponses[j], 45)) else: intitule = "\n".join(wrap(reponses[j], 90)) if horizQuestion == True: longueurIntitule = canvas.stringWidth(intitule, 'Helvetica', 12) textObject.textOut(liste[j] + " : " + intitule) textObject.moveCursor(longueurIntitule + 30, 0) decalage = decalage + longueurIntitule + 30 else: textObject.textLines(liste[j] + " : " + intitule) nbLignes = nbLignes + len(simpleSplit(intitule, 'Helvetica', 12, 500)) textObject.moveCursor(-15, 0) if decalage != 0: textObject.moveCursor(-(decalage), 0) textObject.textLine("") textObject.textLine("")
def generatePage(words, canvas: canvas.Canvas, page: PageSettings, title): """ :param words: matrix of words (rows * columns) :param canvas: PDF canvas :param meta: other information (e.g page title) :return: """ if page.landscape: (marginR, marginT, marginL, marginB) = page.margins (height, width) = page.pagesize titleX = marginT titleY = width - marginR else: (marginT, marginL, marginB, marginR) = page.margins (width, height) = page.pagesize titleX = marginL titleY = height - marginT # if page.title: # canvas.setFont("HatWordFont", page.titleFontSize) # canvas.drawString(titleX + page.titleIndent, titleY - page.titleHeight / 2, title) if page.landscape: canvas.rotate(90) canvas.translate(0, -height) gwidth = width - marginL - marginR gheight = height - marginT - marginB goriginx = marginL goriginy = marginB # if page.title: # if page.landscape: # gwidth -= page.titleHeight # else: # gheight -= page.titleHeight if page.cutGrid: canvas.setStrokeColor(black) # Large bold rectangle canvas.setLineWidth(0.4 * mm) canvas.rect(goriginx, goriginy, gwidth, gheight) # outer cutting lines: canvas.setLineWidth(0.3 * mm) canvas.line(0, goriginy, width, goriginy) canvas.line(0, goriginy + gheight, width, goriginy + gheight) canvas.line(goriginx, 0, goriginx, height) canvas.line(goriginx + gwidth, 0, goriginx + gwidth, height) # grid cellWidth = gwidth / page.columns cellHeight = gheight / page.rows canvas.setLineWidth(0.2 * mm) canvas.grid([goriginx + i * cellWidth for i in range(page.columns + 1)], [goriginy + j * cellHeight for j in range(page.rows + 1)]) # add words canvas.setFont("HatWordFont", page.fontSize) # As y starts at the end of the page, adjust for it and start from the top # (so that empty cells will placed be at bottom). yoffset = goriginy + cellHeight / 2 + cellHeight * (page.rows - 1) for row in words: xoffset = goriginx + cellWidth / 2 for word in row: # scale down font size for long words numlines = word.count(";") + 1 fontSize = page.fontSize while fontSize > 0 and max( canvas.stringWidth(w, fontSize=fontSize) for w in word.split(";")) >= cellWidth - 2 * page.wordMargin - 0.5: fontSize -= 1 canvas.setFontSize(fontSize) # Somewhat cheap guess on string height : fontsize / 2 yoff = yoffset + fontSize * numlines * 0.65 - fontSize / 2 # print("99999999", word) flag = False for i in word.split(";"): print(i) if (flag): yoff -= fontSize * 1.1 if (i[:5] == "Место"): flag = True else: flag = False if (i == word.split(";")[0]): canvas.setFont("HatWordFontBold", page.titleFontSize) canvas.setFontSize(fontSize) canvas.drawCentredString(xoffset, yoff, i) yoff -= fontSize * 1.1 else: canvas.drawString(xoffset - cellWidth / 2 + 10, yoff, i) if (i == word.split(";")[0]): canvas.setFont("HatWordFont", page.titleFontSize) canvas.setFontSize(fontSize) yoff -= fontSize * 1.1 xoffset += cellWidth yoffset -= cellHeight
def draw(self): canvas = self.canv chartmargin = self.chartMargin for count, gcl in enumerate( self.splitChordList(self.guitarChordList, self.nChords)): v_origin = self.height - count * \ (self.oneHeight + self.stringHeight) self.nStrings = 6 fontsize = 12 stringList = [[c.voicings['guitar'][-(r + 1)] for c in gcl] for r in range(self.nStrings)] stringList.append([c.name for c in gcl]) for i in range(self.nStrings + 1): # i is the string line currently being drawn writeText(canvas, self.style, ['e', 'B', 'G', 'D', 'A', 'E', 'Name'][i], fontsize, v_origin - (i * self.stringHeight), self.width, hpos=chartmargin, align='right') # j is which chord (0 is first chord, 1 is 2nd etc) for j in range(len(stringList[-1])): currentWidth = canvas.stringWidth(stringList[i][j]) if j == 0: x = self.stringHzGap + chartmargin l = self.stringHzSp/2 - self.stringHzGap - \ ((currentWidth/2)) - self.stringHzGap y = v_origin-(self.stringHeight*i) - \ self.stringHeight/2 canvas.line(x, y, x + l, y) else: x = chartmargin + self.stringHzSp * \ (j-0.5)+(lastWidth/2+self.stringHzGap) l = self.stringHzSp - currentWidth / \ 2 - lastWidth/2 - self.stringHzGap*2 y = v_origin-(self.stringHeight*i) - \ self.stringHeight/2 canvas.line(x, y, x + l, y) if j == len(stringList[-1]) - 1: x = chartmargin + self.stringHzSp * \ (j+0.5) + currentWidth/2 + self.stringHzGap l = self.stringHzSp / 2 - currentWidth / 2 - self.stringHzGap y = v_origin-(self.stringHeight*i) - \ self.stringHeight/2 canvas.line(x, y, x + l, y) writeText(canvas, self.style, stringList[i][j], fontsize, v_origin - (i * self.stringHeight), self.width, hpos=chartmargin + self.stringHzSp * (j + 0.5)) lastWidth = currentWidth