1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Thermal\Profile; |
4
|
|
|
|
5
|
|
|
use Thermal\Printer; |
6
|
|
|
use Thermal\Buffer\Encoding; |
7
|
|
|
use Thermal\Connection\Connection; |
8
|
|
|
use Endroid\QrCode\QrCode; |
9
|
|
|
use Thermal\Graphics\Image; |
10
|
|
|
use Thermal\Graphics\Filter\Threshold; |
11
|
|
|
|
12
|
|
|
abstract class Profile |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* Column count |
16
|
|
|
* |
17
|
|
|
* @var int |
18
|
|
|
*/ |
19
|
|
|
private $columns; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Model capabilities |
23
|
|
|
* |
24
|
|
|
* @var array |
25
|
|
|
*/ |
26
|
|
|
protected $capabilities; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Connection or output buffer |
30
|
|
|
* |
31
|
|
|
* @var \Thermal\Connection\Connection |
32
|
|
|
*/ |
33
|
|
|
private $connection; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Font name A, C or C |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
private $font; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Printer default font name |
44
|
|
|
* |
45
|
|
|
* @var string |
46
|
|
|
*/ |
47
|
|
|
private $default_font; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Encoding |
51
|
|
|
* |
52
|
|
|
* @var \Thermal\Buffer\Encoding |
53
|
|
|
*/ |
54
|
|
|
private $encoding; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Profile constructor |
58
|
|
|
* |
59
|
|
|
* @param array $capabilities |
60
|
|
|
*/ |
61
|
52 |
|
public function __construct($capabilities) |
62
|
|
|
{ |
63
|
52 |
|
$this->capabilities = $capabilities; |
64
|
52 |
|
$this->columns = $this->getDefaultColumns(); |
65
|
52 |
|
$this->default_font = $this->findDefaultFont(); |
66
|
52 |
|
$this->font = $this->getDefaultFont(); |
67
|
52 |
|
$this->connection = null; |
68
|
52 |
|
$this->encoding = new Encoding($this->getDefaultCodePage()); |
69
|
52 |
|
} |
70
|
|
|
|
71
|
13 |
|
public function getName() |
72
|
|
|
{ |
73
|
13 |
|
$name = isset($this->capabilities['name']) ? $this->capabilities['name'] : $this->capabilities['model']; |
74
|
13 |
|
return $this->capabilities['brand'] . ' ' . $name; |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Printer encoding |
79
|
|
|
* |
80
|
|
|
* @return \Thermal\Buffer\Encoding |
81
|
|
|
*/ |
82
|
19 |
|
public function getEncoding() |
83
|
|
|
{ |
84
|
19 |
|
return $this->encoding; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Default column count |
89
|
|
|
* |
90
|
|
|
* @return int |
91
|
|
|
*/ |
92
|
52 |
|
public function getDefaultColumns() |
93
|
|
|
{ |
94
|
52 |
|
return $this->capabilities['columns']; |
95
|
|
|
} |
96
|
|
|
|
97
|
|
|
/** |
98
|
|
|
* Column count for printing |
99
|
|
|
* |
100
|
|
|
* @return int |
101
|
|
|
*/ |
102
|
4 |
|
public function getColumns() |
103
|
|
|
{ |
104
|
4 |
|
return $this->columns; |
105
|
|
|
} |
106
|
|
|
|
107
|
6 |
|
public function setColumns($columns) |
108
|
|
|
{ |
109
|
6 |
|
$font = ['name' => 'Unknow']; |
110
|
|
|
// search for font with more columns |
111
|
|
|
// font list must be sorted by their number of columns |
112
|
6 |
|
foreach ($this->capabilities['fonts'] as $font) { |
113
|
6 |
|
if ($columns <= $font['columns']) { |
114
|
6 |
|
break; |
115
|
|
|
} |
116
|
|
|
} |
117
|
6 |
|
$this->setFont($font); |
118
|
6 |
|
$this->columns = $columns; |
119
|
6 |
|
return $this; |
120
|
|
|
} |
121
|
|
|
|
122
|
52 |
|
public function getDefaultFont() |
123
|
|
|
{ |
124
|
52 |
|
return $this->default_font; |
125
|
|
|
} |
126
|
|
|
|
127
|
52 |
|
private function findDefaultFont() |
128
|
|
|
{ |
129
|
52 |
|
foreach ($this->capabilities['fonts'] as $font) { |
130
|
52 |
|
if ($this->getDefaultColumns() == $font['columns']) { |
131
|
52 |
|
return $font; |
132
|
|
|
} |
133
|
|
|
} |
134
|
1 |
|
throw new \Exception( |
135
|
1 |
|
sprintf( |
136
|
1 |
|
'Default font with %d columns not found for printer "%s"', |
137
|
1 |
|
$this->getDefaultColumns(), |
138
|
1 |
|
$this->getName() |
139
|
|
|
), |
140
|
1 |
|
404 |
141
|
|
|
); |
142
|
|
|
} |
143
|
|
|
|
144
|
3 |
|
public function getCodePages() |
145
|
|
|
{ |
146
|
3 |
|
return array_keys($this->capabilities['codepages']); |
147
|
|
|
} |
148
|
|
|
|
149
|
52 |
|
public function getDefaultCodePage() |
150
|
|
|
{ |
151
|
52 |
|
return $this->capabilities['codepage']; |
152
|
|
|
} |
153
|
|
|
|
154
|
14 |
|
protected function checkCodePage($codepage) |
155
|
|
|
{ |
156
|
14 |
|
if (!isset($this->capabilities['codepages'][$codepage])) { |
157
|
1 |
|
throw new \Exception( |
158
|
1 |
|
sprintf( |
159
|
1 |
|
'Codepage "%s" not supported for printer "%s"', |
160
|
|
|
$codepage, |
161
|
1 |
|
$this->getName() |
162
|
|
|
), |
163
|
1 |
|
401 |
164
|
|
|
); |
165
|
|
|
} |
166
|
14 |
|
return $this; |
167
|
|
|
} |
168
|
|
|
|
169
|
14 |
|
public function setCodePage($codepage) |
170
|
|
|
{ |
171
|
14 |
|
$this->getEncoding()->setCodePage($codepage); |
172
|
14 |
|
$this->checkCodePage($codepage); |
173
|
14 |
|
$this->getConnection()->write($this->capabilities['codepages'][$codepage]); |
174
|
14 |
|
} |
175
|
|
|
|
176
|
6 |
|
public function getFont() |
177
|
|
|
{ |
178
|
6 |
|
return $this->font; |
179
|
|
|
} |
180
|
|
|
|
181
|
8 |
|
public function setFont($font) |
182
|
|
|
{ |
183
|
8 |
|
$found = false; |
184
|
8 |
|
$_font = ['name' => 'Unknow']; |
185
|
8 |
|
foreach ($this->capabilities['fonts'] as $_font) { |
186
|
8 |
|
if ($_font['name'] == $font['name']) { |
187
|
6 |
|
$found = true; |
188
|
6 |
|
break; |
189
|
|
|
} |
190
|
|
|
} |
191
|
8 |
|
if (!$found) { |
192
|
2 |
|
throw new \Exception( |
193
|
2 |
|
sprintf( |
194
|
2 |
|
'Font "%s" not found for printer "%s"', |
195
|
2 |
|
$font['name'], |
196
|
2 |
|
$this->getName() |
197
|
|
|
), |
198
|
2 |
|
404 |
199
|
|
|
); |
200
|
|
|
} |
201
|
6 |
|
if ($this->font['name'] != $_font['name']) { |
202
|
6 |
|
$this->fontChanged($_font, $this->font['name']); |
203
|
6 |
|
$this->refresh(); |
204
|
|
|
} |
205
|
6 |
|
$this->font = $_font; |
206
|
6 |
|
return $this; |
207
|
|
|
} |
208
|
|
|
|
209
|
14 |
|
protected function refresh() |
210
|
|
|
{ |
211
|
|
|
// ensure current codepage |
212
|
14 |
|
$this->setCodePage($this->getEncoding()->getCodePage()); |
213
|
14 |
|
return $this; |
214
|
|
|
} |
215
|
|
|
|
216
|
6 |
|
protected function fontChanged($new_font, $old_font) |
217
|
|
|
{ |
218
|
6 |
|
} |
219
|
|
|
|
220
|
|
|
/** |
221
|
|
|
* Current connection |
222
|
|
|
* |
223
|
|
|
* @return \Thermal\Connection\Connection |
224
|
|
|
*/ |
225
|
39 |
|
public function getConnection() |
226
|
|
|
{ |
227
|
39 |
|
if ($this->connection instanceof Connection) { |
228
|
37 |
|
return $this->connection; |
229
|
|
|
} |
230
|
2 |
|
throw new \Exception('Connection must be set before priting', 500); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** |
234
|
|
|
* Set current connection |
235
|
|
|
* |
236
|
|
|
* @param \Thermal\Connection\Connection $connection |
237
|
|
|
* @return self |
238
|
|
|
*/ |
239
|
47 |
|
public function setConnection($connection) |
240
|
|
|
{ |
241
|
47 |
|
$this->connection = $connection; |
242
|
47 |
|
return $this; |
243
|
|
|
} |
244
|
|
|
|
245
|
12 |
|
public function initialize() |
246
|
|
|
{ |
247
|
12 |
|
if (isset($this->capabilities['initialize'])) { |
248
|
|
|
// ensure defaults |
249
|
12 |
|
$this->getConnection()->write($this->capabilities['initialize']); |
250
|
|
|
} |
251
|
12 |
|
$this->refresh(); |
252
|
12 |
|
} |
253
|
|
|
|
254
|
1 |
|
public function finalize() |
255
|
|
|
{ |
256
|
1 |
|
} |
257
|
|
|
|
258
|
7 |
|
public function write($text, $styles) |
259
|
|
|
{ |
260
|
7 |
|
$this->setMode($styles, true); |
261
|
7 |
|
$this->setStyle(Printer::STYLE_CONDENSED & $styles, true); |
262
|
7 |
|
$this->setStyle(Printer::STYLE_BOLD & $styles, true); |
263
|
7 |
|
$this->setStyle(Printer::STYLE_ITALIC & $styles, true); |
264
|
7 |
|
$this->setStyle(Printer::STYLE_UNDERLINE & $styles, true); |
265
|
7 |
|
$this->getConnection()->write($this->getEncoding()->encode($text, 'UTF-8')); |
266
|
7 |
|
$this->setStyle(Printer::STYLE_UNDERLINE & $styles, false); |
267
|
7 |
|
$this->setStyle(Printer::STYLE_ITALIC & $styles, false); |
268
|
7 |
|
$this->setStyle(Printer::STYLE_BOLD & $styles, false); |
269
|
7 |
|
$this->setStyle(Printer::STYLE_CONDENSED & $styles, false); |
270
|
7 |
|
$this->setMode($styles, false); |
271
|
7 |
|
return $this; |
272
|
|
|
} |
273
|
|
|
|
274
|
3 |
|
public function writeln($text, $styles, $align) |
275
|
|
|
{ |
276
|
3 |
|
if ($align !== null) { |
277
|
3 |
|
$this->setAlignment($align); |
278
|
|
|
} |
279
|
3 |
|
if (strlen($text) > 0) { |
280
|
3 |
|
$this->write($text, $styles); |
281
|
|
|
} |
282
|
3 |
|
$this->feed(1); |
283
|
|
|
// reset align to left |
284
|
3 |
|
if ($align !== null && $align != Printer::ALIGN_LEFT) { |
285
|
2 |
|
$this->setAlignment(Printer::ALIGN_LEFT); |
286
|
|
|
} |
287
|
3 |
|
return $this; |
288
|
|
|
} |
289
|
|
|
|
290
|
3 |
|
protected function getBitmapCmd() |
291
|
|
|
{ |
292
|
3 |
|
return "\e*!"; |
293
|
|
|
} |
294
|
|
|
|
295
|
4 |
|
public function draw($image) |
296
|
|
|
{ |
297
|
4 |
|
$width = $image->getWidth(); |
298
|
4 |
|
$low = $width & 0xFF; |
299
|
4 |
|
$high = ($width >> 8) & 0xFF; |
300
|
4 |
|
$this->getConnection()->write("\e3\x10"); |
301
|
4 |
|
for ($i=0; $i < $image->getLines(); $i++) { |
302
|
4 |
|
$data = $image->getLineData($i); |
303
|
4 |
|
$this->getConnection()->write($this->getBitmapCmd() . chr($low) . chr($high) . $data . "\eJ\x00"); |
304
|
|
|
} |
305
|
4 |
|
$this->getConnection()->write("\e2"); |
306
|
4 |
|
return $this; |
307
|
|
|
} |
308
|
|
|
|
309
|
|
|
/** |
310
|
|
|
* Draw QR Code |
311
|
|
|
* |
312
|
|
|
* @param string $data data to encode |
313
|
|
|
* @param int $size size of QR Code |
314
|
|
|
* @return void |
315
|
|
|
*/ |
316
|
|
|
abstract public function qrcode($data, $size); |
317
|
|
|
|
318
|
|
|
/** |
319
|
|
|
* Draw QR Code generating an image and sending to printer |
320
|
|
|
* |
321
|
|
|
* @param string $data data to encode |
322
|
|
|
* @param int $size size of QR Code |
323
|
|
|
* @return void |
324
|
|
|
*/ |
325
|
2 |
|
protected function drawQrcode($data, $size) |
326
|
|
|
{ |
327
|
2 |
|
$qrCode = new QrCode($data); |
|
|
|
|
328
|
2 |
|
$qrCode->setSize(min(11, max(1, $size ?: 4)) * 50); |
|
|
|
|
329
|
2 |
|
$image = new Image( |
330
|
|
|
[ |
331
|
2 |
|
'data' => $qrCode->writeString(), |
|
|
|
|
332
|
2 |
|
'name' => 'qrcode.png', |
333
|
|
|
], |
334
|
2 |
|
new Threshold() |
335
|
|
|
); |
336
|
2 |
|
$this->draw($image); |
337
|
2 |
|
} |
338
|
|
|
|
339
|
|
|
abstract public function feed($lines); |
340
|
|
|
abstract public function cutter($mode); |
341
|
|
|
abstract public function buzzer(); |
342
|
|
|
|
343
|
|
|
/** |
344
|
|
|
* @param int $number drawer id |
345
|
|
|
* @param int $on_time time in milliseconds that activate the drawer |
346
|
|
|
* @param int $off_time time in milliseconds that deactivate the drawer |
347
|
|
|
*/ |
348
|
|
|
abstract public function drawer($number, $on_time, $off_time); |
349
|
|
|
|
350
|
|
|
abstract public function setAlignment($align); |
351
|
|
|
abstract protected function setMode($mode, $enable); |
352
|
|
|
abstract protected function setStyle($style, $enable); |
353
|
|
|
} |
354
|
|
|
|
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.