Skip to content

Commit 6efe749

Browse files
committed
Implement newline logic
avoid smush problems by saving the buffer state before each space When the width of the ascii art is bigger than the specified width, we rewrite the string from the last blank, if no blank we rewrite from the last char
1 parent e23995e commit 6efe749

File tree

2 files changed

+113
-76
lines changed

2 files changed

+113
-76
lines changed

pyfiglet/__init__.py

Lines changed: 108 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -314,17 +314,20 @@ def render(self, text):
314314
builder = FigletBuilder(text,
315315
self.base.Font,
316316
self.base.direction,
317-
self.base.width)
317+
self.base.width,
318+
self.base.justify)
318319

319320
while builder.isNotFinished():
320-
builder.addCharToBuffer()
321+
builder.addCharToProduct()
321322
builder.goToNextChar()
322323

323-
builder.flushLastBuffer()
324-
builder.formatProduct(self.base.justify)
325324
return builder.returnProduct()
326325

327326
class FigletProduct(object):
327+
"""
328+
This class stores the internal build part of
329+
the ascii output string
330+
"""
328331
def __init__(self):
329332
self.queue = list()
330333
self.buffer_string = ""
@@ -340,22 +343,25 @@ class FigletBuilder(object):
340343
"""
341344
Represent the internals of the build process
342345
"""
343-
def __init__(self, text, font, direction, width):
346+
def __init__(self, text, font, direction, width, justify):
344347

345-
self.width = width
346-
self.iterator = 0
348+
self.text = list(map(ord, list(text)))
347349
self.direction = direction
350+
self.width = width
348351
self.font = font
349-
self.text = map(ord, list(text))
352+
self.justify = justify
353+
354+
self.iterator = 0
355+
self.maxSmush = 0
356+
self.newBlankRegistered = False
357+
350358
self.curCharWidth = 0
351359
self.prevCharWidth = 0
352360
self.currentTotalWidth = 0
353-
self.previousTotalWidth = 0
354-
self.maxSmush = 0
355-
self.previousSmush = 0
361+
362+
self.blankMarkers = list()
356363
self.product = FigletProduct()
357364
self.buffer = ['' for i in range(self.font.height)]
358-
self.blank_markers = list()
359365

360366
# constants.. lifted from figlet222
361367
self.SM_EQUAL = 1 # smush equal chars (not hardblanks)
@@ -367,16 +373,75 @@ def __init__(self, text, font, direction, width):
367373
self.SM_KERN = 64
368374
self.SM_SMUSH = 128
369375

370-
def _getCharAt(self, i):
371-
if i < 0 or i >= len(self.text):
376+
# builder interface
377+
378+
def addCharToProduct(self):
379+
curChar = self.getCurChar()
380+
if curChar is None:
381+
return
382+
self.curCharWidth = self.getCurWidth()
383+
self.maxSmush = self.currentSmushAmount(curChar)
384+
385+
self.currentTotalWidth = len(self.buffer[0]) + self.curCharWidth - self.maxSmush
386+
387+
if self.text[self.iterator] == ord(' '):
388+
self.blankMarkers.append(([row for row in self.buffer], self.iterator))
389+
390+
#print(chr(self.text[self.iterator]),":",len(self.buffer[0]),"=>",self.currentTotalWidth,";;", self.blankMarkers)
391+
#for i in self.buffer:
392+
# print(i)
393+
394+
if (self.currentTotalWidth >= self.width):
395+
self.handleNewLine()
396+
else:
397+
for row in range(0, self.font.height):
398+
self.addCurCharRowToBufferRow(curChar, row)
399+
400+
401+
self.prevCharWidth = self.curCharWidth
402+
403+
def goToNextChar(self):
404+
self.iterator += 1
405+
406+
def returnProduct(self):
407+
"""
408+
Returns the output string created by formatProduct
409+
"""
410+
if self.buffer[0] != '':
411+
self.flushLastBuffer()
412+
self.formatProduct()
413+
return self.product.getString()
414+
415+
def isNotFinished(self):
416+
ret = self.iterator < len(self.text)
417+
return ret
418+
419+
# private
420+
421+
def flushLastBuffer(self):
422+
self.product.append(self.buffer)
423+
424+
def formatProduct(self):
425+
"""
426+
This create the output string representation from
427+
the internal representation of the product
428+
"""
429+
string_acc = ''
430+
for buffer in self.product.queue:
431+
buffer = self.justifyString(self.justify, buffer)
432+
string_acc += self.replaceHardblanks(buffer)
433+
self.product.buffer_string = string_acc
434+
435+
def getCharAt(self, i):
436+
if i < 0 or i >= len(list(self.text)):
372437
return None
373438
c = self.text[i]
374439
if c not in self.font.chars:
375440
return None
376441
else:
377442
return self.font.chars[c]
378443

379-
def _getCharWidthAt(self, i):
444+
def getCharWidthAt(self, i):
380445
if i < 0 or i >= len(self.text):
381446
return None
382447
c = self.text[i]
@@ -385,14 +450,11 @@ def _getCharWidthAt(self, i):
385450
else:
386451
return self.font.width[c]
387452

388-
def _getCurChar(self):
389-
return self._getCharAt(self.iterator)
453+
def getCurChar(self):
454+
return self.getCharAt(self.iterator)
390455

391-
def _getCurWidth(self):
392-
return self._getCharWidthAt(self.iterator)
393-
394-
def isNotFinished(self):
395-
return self.iterator < len(self.text)
456+
def getCurWidth(self):
457+
return self.getCharWidthAt(self.iterator)
396458

397459
def getLeftSmushedChar(self, i, addLeft):
398460
idx = len(addLeft) - self.maxSmush + i
@@ -402,6 +464,9 @@ def getLeftSmushedChar(self, i, addLeft):
402464
left = ''
403465
return left, idx
404466

467+
def currentSmushAmount(self, curChar):
468+
return self.smushAmount(self.buffer, curChar)
469+
405470
def updateSmushedCharInLeftBuffer(self, addLeft, idx, smushed):
406471
l = list(addLeft)
407472
if idx < 0 or idx > len(l):
@@ -428,67 +493,43 @@ def addCurCharRowToBufferRow(self, curChar, row):
428493
addLeft, addRight = self.smushRow(curChar, row)
429494
self.buffer[row] = addLeft + addRight[self.maxSmush:]
430495

431-
def cutBufferAtLastBlank(self, last_blank):
432-
cut_buffer = [row[:last_blank] for row in self.buffer]
433-
self.product.append(cut_buffer)
434-
self.buffer = [self.buffer[row][last_blank + self.font.width[ord(' ')] -1:] for row in range(self.font.height)]
496+
def cutBufferCommon(self):
435497
self.currentTotalWidth = len(self.buffer[0])
436-
self.blank_markers = list()
498+
self.buffer = ['' for i in range(self.font.height)]
499+
self.blankMarkers = list()
500+
self.prevCharWidth = 0
501+
curChar = self.getCurChar()
502+
if curChar is None:
503+
return
504+
self.maxSmush = self.currentSmushAmount(curChar)
437505

506+
def cutBufferAtLastBlank(self, saved_buffer, saved_iterator):
507+
self.product.append(saved_buffer)
508+
self.iterator = saved_iterator
509+
self.cutBufferCommon()
438510

439511
def cutBufferAtLastChar(self):
440-
raise NotImplementedError()
441-
512+
self.product.append(self.buffer)
513+
self.iterator -= 1
514+
self.cutBufferCommon()
442515

443516
def blankExist(self, last_blank):
444517
return last_blank != -1
445518

446519
def getLastBlank(self):
447520
try:
448-
last_blank = self.blank_markers.pop()
521+
saved_buffer, saved_iterator = self.blankMarkers.pop()
449522
except IndexError:
450-
return -1
451-
return last_blank
523+
return -1,-1
524+
return (saved_buffer, saved_iterator)
452525

453526
def handleNewLine(self):
454-
last_blank = self.getLastBlank()
455-
if self.blankExist(last_blank):
456-
self.cutBufferAtLastBlank(last_blank)
527+
saved_buffer, saved_iterator = self.getLastBlank()
528+
if self.blankExist(saved_iterator):
529+
self.cutBufferAtLastBlank(saved_buffer, saved_iterator)
457530
else:
458531
self.cutBufferAtLastChar()
459532

460-
def addCharToBuffer(self):
461-
curChar = self._getCurChar()
462-
if curChar is None:
463-
return
464-
self.curCharWidth = self._getCurWidth()
465-
self.previousSmush = self.maxSmush
466-
self.previousWidth = self.currentTotalWidth
467-
self.maxSmush = self.currentSmushAmount(curChar)
468-
self.currentTotalWidth += self.curCharWidth - self.maxSmush
469-
470-
if (self.currentTotalWidth > self.width):
471-
self.handleNewLine()
472-
473-
if self.text[self.iterator] == ord(' '):
474-
self.blank_markers.append(len(self.buffer[0]))
475-
476-
477-
for row in range(0, self.font.height):
478-
self.addCurCharRowToBufferRow(curChar, row)
479-
480-
self.prevCharWidth = self.curCharWidth
481-
482-
def flushLastBuffer(self):
483-
self.product.append(self.buffer)
484-
485-
def formatProduct(self, justify):
486-
string_acc = ''
487-
for buffer in self.product.queue:
488-
buffer = self.justifyString(justify, buffer)
489-
string_acc += self.replaceHardblanks(buffer)
490-
self.product.buffer_string = string_acc
491-
492533
def justifyString(self, justify, buffer):
493534
if justify == 'right':
494535
for row in range(0, self.font.height):
@@ -507,15 +548,6 @@ def replaceHardblanks(self, buffer):
507548
string = string.replace(self.font.hardBlank, ' ')
508549
return string
509550

510-
def returnProduct(self):
511-
return self.product.getString()
512-
513-
def goToNextChar(self):
514-
self.iterator += 1
515-
516-
def currentSmushAmount(self, curChar):
517-
return self.smushAmount(self.buffer, curChar)
518-
519551
def smushAmount(self, buffer=[], curChar=[]):
520552
"""
521553
Calculate the amount of smushing we can do between this char and the

test_font.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash
2+
set -eux
3+
pyfiglet -f $2 "$1" > /tmp/pyfiglet
4+
figlet -d pyfiglet/fonts -f $2 "$1"> /tmp/figlet
5+
vimdiff /tmp/figlet /tmp/pyfiglet

0 commit comments

Comments
 (0)