← All changes
|
includes/Templates/Thermal/Thermal_Text_Layout.php
+114
-14
1.10.2
→
1.10.20
View file →
| @@ -15,15 +15,10 @@ | ||
| 15 | 15 | * FULLWIDTH YEN as one cell while the others measured two, and two copies of the |
| 16 | 16 | * no-mbstring fallback called mb_convert_encoding() — itself an mbstring |
| 17 | 17 | * function — so a host without the extension took a fatal. |
| 18 | 18 | * |
| 19 | - * Deliberately stateless and static rather than a trait. Four private copies that | |
| 20 | - * *looked* locally defined are how the drift happened in the first place; | |
| 21 | - * `display_width()` called on `$this` is indistinguishable from a method the | |
| 22 | - * emitter owns, whereas `Thermal_Text_Layout::display_width()` names its source | |
| 23 | - * at every call. | |
| 24 | - * Being static also keeps `columns` an argument instead of an implicit property | |
| 25 | - * contract, and lets the layout be exercised on its own. | |
| 19 | + * A per-lane instance owns the paper columns and nested applied magnification. | |
| 20 | + * The existing static primitives remain available to raster and other emitters. | |
| 26 | 21 | * |
| 27 | 22 | * Text emission itself stays with each emitter: only the measuring moved. |
| 28 | 23 | * |
| 29 | 24 | * @author Paul Kilmurray <[email protected]> |
| @@ -39,13 +34,109 @@ | ||
| 39 | 34 | */ |
| 40 | 35 | final class Thermal_Text_Layout { |
| 41 | 36 | |
| 42 | 37 | /** |
| 43 | - * Not instantiable: every member is a pure static function. | |
| 38 | + * Paper width in character columns. | |
| 39 | + * | |
| 40 | + * @var int | |
| 44 | 41 | */ |
| 45 | - private function __construct() {} | |
| 42 | + private $columns; | |
| 46 | 43 | |
| 47 | 44 | /** |
| 45 | + * Command-specific magnification ceiling (8 for ESC/POS, 6 for StarPRNT). | |
| 46 | + * | |
| 47 | + * @var int | |
| 48 | + */ | |
| 49 | + private $max_magnification; | |
| 50 | + | |
| 51 | + /** | |
| 52 | + * Applied sizes; the base entry is normal size. | |
| 53 | + * | |
| 54 | + * @var array | |
| 55 | + */ | |
| 56 | + private $sizes = array( | |
| 57 | + array( | |
| 58 | + 'width' => 1, | |
| 59 | + 'height' => 1, | |
| 60 | + ), | |
| 61 | + ); | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * Construct per-lane metrics. | |
| 65 | + * | |
| 66 | + * @param int $columns Paper width in character columns. | |
| 67 | + * @param int $max_magnification Largest multiplier the lane can encode. | |
| 68 | + */ | |
| 69 | + public function __construct( int $columns, int $max_magnification ) { | |
| 70 | + $this->columns = $columns; | |
| 71 | + $this->max_magnification = $max_magnification; | |
| 72 | + } | |
| 73 | + | |
| 74 | + /** | |
| 75 | + * Return the paper width in character columns. | |
| 76 | + * | |
| 77 | + * @return int | |
| 78 | + */ | |
| 79 | + public function columns(): int { | |
| 80 | + return $this->columns; | |
| 81 | + } | |
| 82 | + | |
| 83 | + /** | |
| 84 | + * Enter a size wrapper, replacing (not multiplying) the parent scale. | |
| 85 | + * | |
| 86 | + * @param int $width Requested width multiplier. | |
| 87 | + * @param int $height Requested height multiplier. | |
| 88 | + * @return void | |
| 89 | + */ | |
| 90 | + public function enter_size( int $width, int $height ): void { | |
| 91 | + $this->sizes[] = array( | |
| 92 | + 'width' => max( 1, min( $this->max_magnification, $width ) ), | |
| 93 | + 'height' => max( 1, min( $this->max_magnification, $height ) ), | |
| 94 | + ); | |
| 95 | + } | |
| 96 | + | |
| 97 | + /** | |
| 98 | + * Leave a size wrapper and restore its parent. | |
| 99 | + * | |
| 100 | + * @return void | |
| 101 | + */ | |
| 102 | + public function leave_size(): void { | |
| 103 | + if ( count( $this->sizes ) > 1 ) { | |
| 104 | + array_pop( $this->sizes ); | |
| 105 | + } | |
| 106 | + } | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * Return the magnification actually encoded by the lane. | |
| 110 | + * | |
| 111 | + * @return array{width: int, height: int} | |
| 112 | + */ | |
| 113 | + public function applied_scale(): array { | |
| 114 | + return $this->sizes[ count( $this->sizes ) - 1 ]; | |
| 115 | + } | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * Count leading spaces using printed columns and the applied width scale. | |
| 119 | + * | |
| 120 | + * @param string $align Alignment mode (left|center|right). | |
| 121 | + * @param string $text Normalized plain text. | |
| 122 | + * @return int Number of literal spaces, each occupying the applied width. | |
| 123 | + */ | |
| 124 | + public function measure_padding( string $align, string $text ): int { | |
| 125 | + return self::alignment_padding( $align, self::display_width( $text ), $this->columns, $this->applied_scale()['width'] ); | |
| 126 | + } | |
| 127 | + | |
| 128 | + /** | |
| 129 | + * Resolve row widths using the existing unscaled paper-column contract. | |
| 130 | + * | |
| 131 | + * @param array $cols Column AST nodes. | |
| 132 | + * @return array | |
| 133 | + */ | |
| 134 | + public function measure_row_widths( array $cols ): array { | |
| 135 | + return self::resolve_row_widths( $cols, $this->columns ); | |
| 136 | + } | |
| 137 | + | |
| 138 | + /** | |
| 48 | 139 | * Normalize text by replacing non-ASCII typographic characters. |
| 49 | 140 | * |
| 50 | 141 | * @param string $value The input text. |
| 51 | 142 | * |
| @@ -258,24 +349,33 @@ | ||
| 258 | 349 | |
| 259 | 350 | /** |
| 260 | 351 | * Compute the leading-space padding that aligns a line of the given width. |
| 261 | 352 | * |
| 353 | + * The padding is emitted as literal spaces INSIDE the run it indents, so under a `<size>` | |
| 354 | + * multiplier each one is $scale cells wide -- as is each character of the text. Callers that | |
| 355 | + * emit bytes to a printer must pass the multiplier in force; a count taken at scale 1 lays | |
| 356 | + * down $scale times the margin asked for and wraps the line. Callers that place glyphs at | |
| 357 | + * computed cell positions (the raster emitter) already fold the multiplier into $text_width | |
| 358 | + * and leave $scale at 1. | |
| 359 | + * | |
| 262 | 360 | * @param string $align The alignment mode (left|center|right). |
| 263 | - * @param int $text_width The display width of the line's plain text. | |
| 361 | + * @param int $text_width The display width of the line's plain text, in unscaled cells. | |
| 264 | 362 | * @param int $columns The paper width in character cells. |
| 363 | + * @param int $scale The text width multiplier in force. Default 1. | |
| 265 | 364 | * |
| 266 | 365 | * @return int The number of leading spaces (clamped at 0). |
| 267 | 366 | */ |
| 268 | - public static function alignment_padding( string $align, int $text_width, int $columns ): int { | |
| 269 | - $remaining = $columns - $text_width; | |
| 367 | + public static function alignment_padding( string $align, int $text_width, int $columns, int $scale = 1 ): int { | |
| 368 | + $scale = max( 1, $scale ); | |
| 369 | + $remaining = $columns - ( $text_width * $scale ); | |
| 270 | 370 | if ( $remaining <= 0 ) { |
| 271 | 371 | return 0; |
| 272 | 372 | } |
| 273 | 373 | if ( 'center' === $align ) { |
| 274 | - return (int) floor( $remaining / 2 ); | |
| 374 | + return (int) floor( (int) floor( $remaining / 2 ) / $scale ); | |
| 275 | 375 | } |
| 276 | 376 | if ( 'right' === $align ) { |
| 277 | - return $remaining; | |
| 377 | + return (int) floor( $remaining / $scale ); | |
| 278 | 378 | } |
| 279 | 379 | |
| 280 | 380 | return 0; |
| 281 | 381 | } |