Skip to content

Commit

Permalink
v2.41
Browse files Browse the repository at this point in the history
  • Loading branch information
paddywwoof committed Dec 4, 2020
2 parents 8b1beca + c7f477b commit 5671bdd
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 14 deletions.
4 changes: 4 additions & 0 deletions ChangeLog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Tim Skillman, Patrick Gaunt, Tom Ritchford

Date Amends

v2.41
2020-12-04 Bug fix: PointText now copes with multi-line strings and
can insert new lines at a given width

v2.40
2020-12-02 Bug fix: PointText needs to write over previous characters if the
string reduces in length (set uv to [0.0, 0.0])
Expand Down
2 changes: 1 addition & 1 deletion pi3d/constants/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import time
import logging

__version__ = '2.40'
__version__ = '2.41'
year = time.localtime().tm_year

STARTUP_MESSAGE = """
Expand Down
80 changes: 67 additions & 13 deletions pi3d/util/TextBlock.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ def __init__(self, x, y, z, rot, char_count, data_obj=None, attr=None,
self._buffer_index = 0
self._text_manager = None
self._string_length = 0
self.char_offsets = [0.0] * char_count
self.char_offsets = np.zeros((char_count, 2))
self._string_length = len(self.get_string(self.get_value()))

def set_text_manager(self, manager, buffer_index):
Expand Down Expand Up @@ -192,9 +192,10 @@ def set_position(self, x=None, y=None, z=None, rot=None):
pos = [self.x, self.y, size_pos]

locations = np.zeros((self.char_count, 3), dtype=np.float)
locations[:, 0] = np.multiply(self.char_offsets, math.cos(self.rot))
locations[:, 1] = np.multiply(self.char_offsets, math.sin(self.rot))
locations = np.add(locations, pos)
(c, s) = (np.cos(self.rot), np.sin(self.rot))
matrix = np.array([[c, -s], [s, c]])
locations[:,:2] = matrix.dot(self.char_offsets.T).T
locations += pos
st = self._buffer_index
mid = st + self._string_length
end = st + self.char_count
Expand All @@ -207,7 +208,27 @@ def recolour(self):
self.colouring.recolour()

def set_text(self, text_format=None, size=None, spacing=None, space=None,
char_rot=None, set_pos=True, set_colour=True):
char_rot=None, set_pos=True, set_colour=True, wrap=None, line_space=1.0):
""" Arguments:
*text_format*:
text to display or a format string for displaying value from data_obj
*size*:
size of text 0.0 to 0.9999
*spacing*:
'C', 'M' or 'F'
*space*:
additional space between character
*char_rot*:
character rotation in degrees
*set_pos*:
control whether set_position() is called - default True
*set_colour*:
control whether set_colour() is called - default True
*wrap*:
if set then line breaks insterted to wrap at this number of characters
*line_space*:
multiplier for line spacing if multiline TextBlock
"""
if text_format is not None:
self.text_format = text_format
if size is not None:
Expand All @@ -230,6 +251,8 @@ def set_text(self, text_format=None, size=None, spacing=None, space=None,
LOGGER.error("'%s' needs %s characters but only space for %s",
strval, self._string_length, self.char_count)
return -1
if wrap is not None:
strval = self.split_lines(strval, wrap)
pos = 0.0
spacing = 0.0 #to stop crash if zero length string
index = 0
Expand All @@ -242,29 +265,60 @@ def set_text(self, text_format=None, size=None, spacing=None, space=None,
vari_width = self.size * self.space
if self.spacing == "F":
vari_width = self.size
lines = [[0, 0, 0.0]] # [start slice, end slice, last char offset]
line_n = 0
"""scale is needed if pointsize is different in Points from Font which is
needed to avoid clipping or overlap of corners when rotation some truetype fonts"""
g_scale = float(self._text_manager.point_size) / self._text_manager.font.height
line_ht = None #need to use same line height for whole thing
for glyph in self._text_manager.font.glyph_table.values():
line_ht = glyph[1] * g_scale
break

for char in strval:
if char == '\n': ## new line
lines.append([index, index, 0.0])
pos = 0.0
line_n += 1

if char in self._text_manager.font.glyph_table: # skip chars not in font
glyph = self._text_manager.font.glyph_table[char]
self._text_manager.uv[index+self._buffer_index] = glyph[4:]
"""scale is needed if pointsize is different in Points from Font which is
needed to avoid clipping or overlap of corners when rotation some truetype fonts"""
g_scale = float(self._text_manager.point_size) / self._text_manager.font.height
char_offset = pos
if self.spacing == "F":
#center character to the right
char_offset += float(glyph[0]) * g_scale * self.size * 0.5
self.char_offsets[index] = char_offset
char_offset += glyph[0] * g_scale * self.size * 0.5
self.char_offsets[index] = [char_offset, -line_space * line_n * line_ht]
spacing = (glyph[0] * g_scale * vari_width) + const_width
pos += spacing
index += 1
lines[line_n][1] = index
lines[line_n][2] = pos
pos += spacing
for i in range(index, self.char_count): # if text re-used with shorter string
self._text_manager.uv[i + self._buffer_index] = [0.0, 0.0]

#Justification
self.char_offsets = np.add(self.char_offsets, (pos - spacing) * -self.justify)
for (i, line) in enumerate(lines):
self.char_offsets[line[0]:line[1], 0] += line[2] * -self.justify
if set_pos:
self.set_position()
if set_colour:
self.recolour()
self._text_manager.set_do_reinit()
self._text_manager.set_do_reinit()

def split_lines(self, txt, width):
new_txt = ""
line_len = 0
txt_words = txt.split()
for w in txt_words:
len_w = len(w)
if line_len > 0:
if (line_len + len_w) > width:
new_txt += "\n"
line_len = 0
else:
new_txt += " "
line_len += 1
new_txt += w
line_len += len_w
return new_txt

0 comments on commit 5671bdd

Please sign in to comment.