classes.c40_text_composer
1from typing import Literal 2import drawBot 3from drawBot import _drawBotDrawingTool as drawBot 4import copy 5 6from lib import content, fonts 7from .c20_box import KBox 8from .c32_pool import KPool 9from datatypes import DFontProps 10 11 12class KTextComposer: 13 """Composes and manages formatted text within a given frame.""" 14 15 def __init__( 16 self, 17 frame: KBox, 18 fontProps: DFontProps, 19 pool: KPool, 20 formattedArgs: dict = None, 21 ): 22 """ 23 Initializes the text composer with a frame, font properties, and a word pool. 24 25 Args: 26 frame: The frame within which the text will be composed. 27 fontProps: The font properties to be applied to the text. 28 pool: The word pool to be used for text composition. 29 formattedArgs: Additional arguments for formatting the text. 30 """ 31 self.frame = frame 32 self.fontProps = fontProps.apply() 33 self.formattedArgs = formattedArgs 34 self.fString = drawBot.FormattedString(**self.fontProps.calc(), **formattedArgs) 35 self.pool = pool 36 37 def setPool(self, pool: KPool): 38 """ 39 Sets the word pool for the composer. 40 """ 41 self.pool = pool 42 return self 43 44 def setOpenTypeFeatures(self, **features: dict[fonts.FontFeature, bool]): 45 """ 46 Sets OpenType features for the formatted string. 47 """ 48 drawBot.openTypeFeatures(**features) 49 self.fString.openTypeFeatures(**features) 50 return self 51 52 def addWord( 53 self, 54 width: float, 55 shape: str = None, 56 tokens: list[content.CharacterToken] = None, 57 ): 58 """ 59 Adds a word from the pool that fits the specified width and optional filters. 60 """ 61 if not self.pool: 62 raise AttributeError("No pool set. Use setPool() to set a pool.") 63 64 linePool = copy.copy(self.pool) # ? Create a pool for this line 65 66 if shape: 67 linePool = linePool.filterWithRegex(shape) 68 69 if tokens: 70 linePool = linePool.filterTokens(["nonword"]) 71 72 word = linePool.getItemByWidth(self.frame.width * width) 73 # Skip removing from the main pool: Commit June 14, 2025 74 self._append(word) 75 return self 76 77 def addString(self, string: str): 78 """ 79 Appends a string to the formatted text. 80 """ 81 self._append(string) 82 return self 83 84 def _append(self, string: str): 85 """ 86 Appends a string to the formatted text. 87 """ 88 # ? Reapply formatted args: spacing needs to be explicit in case it changed 89 self.fString.append(string, **self.fontProps.calc(), **self.formattedArgs) 90 91 def breakLine(self): 92 """ 93 Inserts a line break in the formatted text. 94 """ 95 self.fString.append("\n") 96 return self 97 98 def setTab(self, width: float, alignment: Literal["left", "center", "right"]): 99 """ 100 Sets a tab stop at the given width and alignment, then inserts a tab. 101 """ 102 self.fString.tabs((self.frame.width * width, alignment)) 103 self.fString.append("\t") 104 return self 105 106 def fitForString(self, string: str): 107 """ 108 Adjusts font size to fit the string on a single line within the frame. Updates `fontProps` as a side effect. 109 """ 110 fs, *_ = fonts.fitBinary( 111 string, 112 self.frame.coords, 113 leading=self.fontProps.leading, 114 letterSpacing=self.fontProps.letterSpacing, 115 precision=1, 116 ) 117 self.fontProps = self.fontProps.updateFontSize(fs).apply() 118 return self 119 120 def draw(self): 121 """ 122 Draws the composed text into the frame. 123 """ 124 drawBot.textBox(self.fString, self.frame.coords)
class
KTextComposer:
13class KTextComposer: 14 """Composes and manages formatted text within a given frame.""" 15 16 def __init__( 17 self, 18 frame: KBox, 19 fontProps: DFontProps, 20 pool: KPool, 21 formattedArgs: dict = None, 22 ): 23 """ 24 Initializes the text composer with a frame, font properties, and a word pool. 25 26 Args: 27 frame: The frame within which the text will be composed. 28 fontProps: The font properties to be applied to the text. 29 pool: The word pool to be used for text composition. 30 formattedArgs: Additional arguments for formatting the text. 31 """ 32 self.frame = frame 33 self.fontProps = fontProps.apply() 34 self.formattedArgs = formattedArgs 35 self.fString = drawBot.FormattedString(**self.fontProps.calc(), **formattedArgs) 36 self.pool = pool 37 38 def setPool(self, pool: KPool): 39 """ 40 Sets the word pool for the composer. 41 """ 42 self.pool = pool 43 return self 44 45 def setOpenTypeFeatures(self, **features: dict[fonts.FontFeature, bool]): 46 """ 47 Sets OpenType features for the formatted string. 48 """ 49 drawBot.openTypeFeatures(**features) 50 self.fString.openTypeFeatures(**features) 51 return self 52 53 def addWord( 54 self, 55 width: float, 56 shape: str = None, 57 tokens: list[content.CharacterToken] = None, 58 ): 59 """ 60 Adds a word from the pool that fits the specified width and optional filters. 61 """ 62 if not self.pool: 63 raise AttributeError("No pool set. Use setPool() to set a pool.") 64 65 linePool = copy.copy(self.pool) # ? Create a pool for this line 66 67 if shape: 68 linePool = linePool.filterWithRegex(shape) 69 70 if tokens: 71 linePool = linePool.filterTokens(["nonword"]) 72 73 word = linePool.getItemByWidth(self.frame.width * width) 74 # Skip removing from the main pool: Commit June 14, 2025 75 self._append(word) 76 return self 77 78 def addString(self, string: str): 79 """ 80 Appends a string to the formatted text. 81 """ 82 self._append(string) 83 return self 84 85 def _append(self, string: str): 86 """ 87 Appends a string to the formatted text. 88 """ 89 # ? Reapply formatted args: spacing needs to be explicit in case it changed 90 self.fString.append(string, **self.fontProps.calc(), **self.formattedArgs) 91 92 def breakLine(self): 93 """ 94 Inserts a line break in the formatted text. 95 """ 96 self.fString.append("\n") 97 return self 98 99 def setTab(self, width: float, alignment: Literal["left", "center", "right"]): 100 """ 101 Sets a tab stop at the given width and alignment, then inserts a tab. 102 """ 103 self.fString.tabs((self.frame.width * width, alignment)) 104 self.fString.append("\t") 105 return self 106 107 def fitForString(self, string: str): 108 """ 109 Adjusts font size to fit the string on a single line within the frame. Updates `fontProps` as a side effect. 110 """ 111 fs, *_ = fonts.fitBinary( 112 string, 113 self.frame.coords, 114 leading=self.fontProps.leading, 115 letterSpacing=self.fontProps.letterSpacing, 116 precision=1, 117 ) 118 self.fontProps = self.fontProps.updateFontSize(fs).apply() 119 return self 120 121 def draw(self): 122 """ 123 Draws the composed text into the frame. 124 """ 125 drawBot.textBox(self.fString, self.frame.coords)
Composes and manages formatted text within a given frame.
KTextComposer( frame: classes.c20_box.KBox, fontProps: datatypes.data_fontprops.DFontProps, pool: classes.c32_pool.KPool, formattedArgs: dict = None)
16 def __init__( 17 self, 18 frame: KBox, 19 fontProps: DFontProps, 20 pool: KPool, 21 formattedArgs: dict = None, 22 ): 23 """ 24 Initializes the text composer with a frame, font properties, and a word pool. 25 26 Args: 27 frame: The frame within which the text will be composed. 28 fontProps: The font properties to be applied to the text. 29 pool: The word pool to be used for text composition. 30 formattedArgs: Additional arguments for formatting the text. 31 """ 32 self.frame = frame 33 self.fontProps = fontProps.apply() 34 self.formattedArgs = formattedArgs 35 self.fString = drawBot.FormattedString(**self.fontProps.calc(), **formattedArgs) 36 self.pool = pool
Initializes the text composer with a frame, font properties, and a word pool.
Arguments:
- frame: The frame within which the text will be composed.
- fontProps: The font properties to be applied to the text.
- pool: The word pool to be used for text composition.
- formattedArgs: Additional arguments for formatting the text.
38 def setPool(self, pool: KPool): 39 """ 40 Sets the word pool for the composer. 41 """ 42 self.pool = pool 43 return self
Sets the word pool for the composer.
def
setOpenTypeFeatures( self, **features: dict[typing.Literal['calt', 'case', 'dlig', 'frac', 'liga', 'kern', 'lnum', 'onum', 'ordn', 'pnum', 'ss01', 'ss02', 'ss03', 'ss04', 'ss05', 'ss06', 'ss07', 'ss08', 'ss09', 'ss10', 'subs', 'sups', 'titl', 'tnum'], bool]):
45 def setOpenTypeFeatures(self, **features: dict[fonts.FontFeature, bool]): 46 """ 47 Sets OpenType features for the formatted string. 48 """ 49 drawBot.openTypeFeatures(**features) 50 self.fString.openTypeFeatures(**features) 51 return self
Sets OpenType features for the formatted string.
def
addWord( self, width: float, shape: str = None, tokens: list[typing.Literal['word', 'nonword']] = None):
53 def addWord( 54 self, 55 width: float, 56 shape: str = None, 57 tokens: list[content.CharacterToken] = None, 58 ): 59 """ 60 Adds a word from the pool that fits the specified width and optional filters. 61 """ 62 if not self.pool: 63 raise AttributeError("No pool set. Use setPool() to set a pool.") 64 65 linePool = copy.copy(self.pool) # ? Create a pool for this line 66 67 if shape: 68 linePool = linePool.filterWithRegex(shape) 69 70 if tokens: 71 linePool = linePool.filterTokens(["nonword"]) 72 73 word = linePool.getItemByWidth(self.frame.width * width) 74 # Skip removing from the main pool: Commit June 14, 2025 75 self._append(word) 76 return self
Adds a word from the pool that fits the specified width and optional filters.
def
addString(self, string: str):
78 def addString(self, string: str): 79 """ 80 Appends a string to the formatted text. 81 """ 82 self._append(string) 83 return self
Appends a string to the formatted text.
def
breakLine(self):
92 def breakLine(self): 93 """ 94 Inserts a line break in the formatted text. 95 """ 96 self.fString.append("\n") 97 return self
Inserts a line break in the formatted text.
def
setTab(self, width: float, alignment: Literal['left', 'center', 'right']):
99 def setTab(self, width: float, alignment: Literal["left", "center", "right"]): 100 """ 101 Sets a tab stop at the given width and alignment, then inserts a tab. 102 """ 103 self.fString.tabs((self.frame.width * width, alignment)) 104 self.fString.append("\t") 105 return self
Sets a tab stop at the given width and alignment, then inserts a tab.
def
fitForString(self, string: str):
107 def fitForString(self, string: str): 108 """ 109 Adjusts font size to fit the string on a single line within the frame. Updates `fontProps` as a side effect. 110 """ 111 fs, *_ = fonts.fitBinary( 112 string, 113 self.frame.coords, 114 leading=self.fontProps.leading, 115 letterSpacing=self.fontProps.letterSpacing, 116 precision=1, 117 ) 118 self.fontProps = self.fontProps.updateFontSize(fs).apply() 119 return self
Adjusts font size to fit the string on a single line within the frame. Updates fontProps as a side effect.