thermal 0.2.0 β†’ 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b18797f5189d89f1f7326ab9eb8a131c1c0a98f37fc76b10469e4a67bddf5c47
4
- data.tar.gz: 509efa5bfc9b51dd736b30c9f215d36e8f15fc2a578c7039b9bcd60915929554
3
+ metadata.gz: ec2f32edf56df60bcab0eccadcbfdb990423a1e1ea821794b6e28918c000c4df
4
+ data.tar.gz: 45dc3e615b71ad3534f9bca88f3104d01cbc92f95daf668366261e5e9abdeb71
5
5
  SHA512:
6
- metadata.gz: ecef3e5aba6e5d6b296762f53f6b809a2d4950c32232790138cff89ad8beb49439147cd5da89635f1002664c12fb9b9e4595a453a344ce8db148a0c330e2b0d7
7
- data.tar.gz: cfb8b73b14a9bc09ad839066f888e35574c8ec00986787f6e0c666cfddd7d2c9eaa295483867b10297ff389c4c7bfc3b67fa06d6ec8db8c4e5b42e78aa55c254
6
+ metadata.gz: 12d99782797190f588a656f5f0aef5025aae281eaf555381c105ac50d189ac2932dafbfc09123458beaaa262342689bb52840c02dda843c4da1aeb447c86c310
7
+ data.tar.gz: fdfd15fe4144c92065651bc5758af19386d5a134e56392eb0c880dc73458d46769ab8db97a97e1a9c02fb0852a08c04fde97f31a4766afd3140e63e42bd95f74
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Thermal printer support for Ruby. Used to print receipts, chits, tickets, labels, etc.
4
4
 
5
5
  [![Gem Version](https://badge.fury.io/rb/thermal.svg)](https://badge.fury.io/rb/thermal)
6
- [![CI](https://github.com/tablecheck/thermal/actions/workflows/ci.yml/badge.svg)](https://github.com/tablecheck/thermal/actions/workflows/ci.yml)
6
+ [![Test](https://github.com/tablecheck/thermal/actions/workflows/test.yml/badge.svg)](https://github.com/tablecheck/thermal/actions/workflows/test.yml)
7
7
  [![Ruby Style Guide](https://img.shields.io/badge/code_style-rubocop-brightgreen.svg)](https://github.com/rubocop/rubocop)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
9
9
 
@@ -167,14 +167,11 @@ To add support for additional Thermal printers.
167
167
  - Add new code in `lib/thermal/printer/escpos.rb`
168
168
  - Add new code in `lib/thermal/printer/starprnt.rb`
169
169
 
170
- # πŸ’– Acknowledgements
170
+ # πŸ“˜ Third-Party Documentation
171
171
 
172
- ### πŸ‘¨β€πŸ’» Maintainers
172
+ See the [tablecheck/thermal-docs](https://github.com/tablecheck/thermal-docs) repo.
173
173
 
174
- Thermal is maintained and battle-tested by the team at [TableCheck](https://www.tablecheck.com/en/join/)
175
- based in Tokyo, Japan. πŸ—Ό We use Thermal to help our restaurant users print chits, receipts, and
176
- QR codes to serve their guests' reservations. If you are seeking your next career adventure,
177
- [we're hiring](https://careers.tablecheck.com/)!
174
+ # πŸ’– Acknowledgements
178
175
 
179
176
  ### πŸ“š Data Sources
180
177
 
@@ -184,17 +181,18 @@ to provide a comprehensive list of thermal printers.
184
181
 
185
182
  ### 🌟 Special Thanks
186
183
 
187
- This gem draws inspiration from the following libraries.
188
- Thank you to the authors for their hard work.
184
+ This gem draws inspiration from the following libraries. Thank you to the authors for their hard work.
189
185
  - [escpos-php](https://github.com/escpos/escpos-php)
190
186
  - [escpos-printer-db](https://github.com/receipt-print-hq/escpos-printer-db)
191
187
  - [EscPosEncoder JS](https://github.com/NielsLeenheer/EscPosEncoder/blob/master/src/esc-pos-encoder.js)
192
188
 
193
- ### ©️ Copyright Attribution
189
+ ### πŸ‘¨β€πŸ’» Maintainers
194
190
 
195
- The vendor manuals in the `doc/vendor` directory are the property of their respective owners.
196
- They are included here for references purposes only under the fair use doctrine.
191
+ Thermal is maintained and battle-tested by the team at [TableCheck](https://www.tablecheck.com)
192
+ based in Tokyo, Japan. πŸ—Ό We use Thermal to help our restaurant users print chits, receipts, and
193
+ QR codes to serve their guests' reservations. If you are seeking your next career adventure,
194
+ [we're hiring](https://careers.tablecheck.com/)!
197
195
 
198
- ### πŸ“œ License
196
+ # πŸ“œ License
199
197
 
200
- This gem is released under the MIT License. Please see the [LICENSE](LICENSE) file for details.
198
+ This gem is released under the MIT License. Please see the [LICENSE](LICENSE) file for details.
@@ -1,79 +1,80 @@
1
- # frozen_string_literal: true
2
-
3
- module Thermal
4
- module Db
5
- class Device
6
- DEFAULT_COL_WIDTH = 42
7
-
8
- attr_reader :key
9
-
10
- def initialize(key, data)
11
- @key = key
12
- @data = data
13
-
14
- # eager load cache
15
- codepage_index
16
- charset_index
17
- end
18
-
19
- def name
20
- @data['name']&.to_s
21
- end
22
-
23
- def format
24
- @data['format']&.to_s
25
- end
26
-
27
- def supports?(feature)
28
- !!@data.dig('features', feature)
29
- end
30
-
31
- # TODO: this needs to be dynamic in the printer
32
- def col_width
33
- @col_width ||= @data.dig('fonts', 0, 'columns') || DEFAULT_COL_WIDTH
34
- end
35
-
36
- def find_encoding(u_codepoint)
37
- if (codepage = codepage_index[u_codepoint])
38
- [:codepage, codepage].freeze
39
- elsif (charset = charset_index[u_codepoint]) && charset > 0
40
- [:charset, charset].freeze
41
- end
42
- end
43
-
44
- # def find_codepage(encoding)
45
- # encoding = encoding&.to_s
46
- # device.codepages&.invert&.[](encoding) || 0
47
- # end
48
-
49
- def codepages
50
- @codepages ||= begin
51
- codepages = @data['codepages'] || ::Thermal::Db::DEFAULT_CODEPAGES
52
- codepages.each_with_object({}) do |(k, v), h|
53
- encoding = ::Thermal::Db.encoding(v)
54
- h[k] = encoding if encoding
55
- end.freeze
56
- end
57
- end
58
-
59
- def charsets
60
- @charsets ||= begin
61
- charsets = @data['charsets'] || ::Thermal::Db::DEFAULT_CHARSETS
62
- ::Thermal::Util.index_with(charsets) { |i| ::Thermal::Db.charset(i) }.freeze
63
- end
64
- end
65
-
66
- private
67
-
68
- def codepage_index
69
- @codepage_index ||= codepages.map { |k, v| ::Thermal::Util.index_with(v.u_codepoints, k) }
70
- .reverse.inject(&:merge).freeze
71
- end
72
-
73
- def charset_index
74
- @charset_index ||= charsets.values.map! { |c| ::Thermal::Util.index_with(c.u_codepoints, c.key) }
75
- .reverse.inject(&:merge).freeze
76
- end
77
- end
78
- end
79
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Thermal
4
+ module Db
5
+ class Device
6
+ DEFAULT_COL_WIDTH = 42
7
+
8
+ attr_reader :key
9
+
10
+ def initialize(key, data)
11
+ @key = key
12
+ @data = data
13
+
14
+ # eager load cache
15
+ codepage_index
16
+ charset_index
17
+ end
18
+
19
+ def name
20
+ @data['name']&.to_s
21
+ end
22
+
23
+ def format
24
+ @data['format']&.to_s
25
+ end
26
+
27
+ def supports?(feature)
28
+ !!@data.dig('features', feature)
29
+ end
30
+
31
+ # TODO: this needs to be dynamic in the printer
32
+ def col_width
33
+ @col_width ||= @data.dig('fonts', 0, 'columns') || DEFAULT_COL_WIDTH
34
+ end
35
+
36
+ def find_encoding(u_codepoint)
37
+ if (codepage = codepage_index[u_codepoint])
38
+ [:codepage, codepage].freeze
39
+ elsif (charset = charset_index[u_codepoint]) && charset > 0
40
+ [:charset, charset].freeze
41
+ end
42
+ end
43
+
44
+ # def find_codepage(encoding)
45
+ # encoding = encoding&.to_s
46
+ # device.codepages&.invert&.[](encoding) || 0
47
+ # end
48
+
49
+ def codepages
50
+ @codepages ||= begin
51
+ codepages = @data['codepages'] || ::Thermal::Db::DEFAULT_CODEPAGES
52
+ codepages.each_with_object({}) do |(k, v), h|
53
+ encoding = ::Thermal::Db.encoding(v)
54
+ h[k] = encoding if encoding
55
+ end.freeze
56
+ end
57
+ end
58
+
59
+ def charsets
60
+ @charsets ||= begin
61
+ charsets = @data['charsets'] || ::Thermal::Db::DEFAULT_CHARSETS
62
+ ::Thermal::Util.index_with(charsets) { |i| ::Thermal::Db.charset(i) }.freeze
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def codepage_index
69
+ @codepage_index ||= codepages.map { |k, v| ::Thermal::Util.index_with(v.u_codepoints, k) }
70
+ .reverse.inject(&:merge).freeze
71
+ end
72
+
73
+ def charset_index
74
+ @charset_index ||= charsets.values
75
+ .map! { |c| ::Thermal::Util.index_with(c.u_codepoints, c.key) }
76
+ .reverse.inject(&:merge).freeze
77
+ end
78
+ end
79
+ end
80
+ end
@@ -1,167 +1,167 @@
1
- # frozen_string_literal: true
2
-
3
- module Thermal
4
- module Escpos
5
- # Inspired by mike42/escpos-php
6
- # https://github.com/mike42/escpos-php/blob/development/src/Mike42/Escpos/PrintBuffers/EscposPrintBuffer.php
7
- class Buffer < ::Thermal::ByteBuffer
8
- extend Forwardable
9
-
10
- def initialize(profile)
11
- super()
12
- @profile = profile
13
- @codepage = 0
14
- @charset = 0
15
- @cjk = false
16
- init_buffer!
17
- end
18
-
19
- def_delegators :@profile,
20
- :find_encoding,
21
- :cjk_encoding,
22
- :codepages,
23
- :charsets,
24
- :codepoint_cjk_skip?,
25
- :codepoint_cjk_force?
26
-
27
- def current_encoding
28
- @cjk ? cjk_encoding : codepages[@codepage]
29
- end
30
-
31
- def current_charset
32
- charsets[@charset]
33
- end
34
-
35
- def write_text(text, replace: nil, no_cjk: false)
36
- text = ::Thermal::Util.normalize_utf8(text, replace: replace)
37
- text&.each_codepoint do |u_codepoint|
38
- write_u_codepoint(u_codepoint, replace: replace, no_cjk: no_cjk)
39
- end
40
- end
41
-
42
- private
43
-
44
- def write_u_codepoint(u_codepoint, replace: nil, no_cjk: false, fallback: false)
45
- replace ||= ::Thermal.replace_char
46
-
47
- if ascii?(u_codepoint)
48
- reset_charset!(u_codepoint)
49
- write(u_codepoint)
50
- elsif current_encoding &&
51
- (!@cjk || (!no_cjk && !codepoint_cjk_skip?(u_codepoint))) &&
52
- (@cjk || !codepoint_cjk_force?(u_codepoint)) &&
53
- (codepoint = current_encoding.codepoint(u_codepoint))
54
- write(codepoint)
55
- else
56
- location, value = find_encoding(u_codepoint, no_cjk: no_cjk)
57
- case location
58
- when :codepage
59
- set_codepage(value)
60
- codepoint = current_encoding.codepoint(u_codepoint)
61
- # TODO: move this to encoding class
62
- raise_missing_codepoint!(u_codepoint, current_encoding) unless codepoint
63
- write(codepoint)
64
- when :charset
65
- set_charset(value)
66
- codepoint = current_charset.codepoint(u_codepoint)
67
- # TODO: move this to encoding class
68
- raise_missing_codepoint!(u_codepoint, current_encoding) unless codepoint
69
- write(codepoint)
70
- when :cjk
71
- set_cjk(true)
72
- char = current_encoding.codepoint(u_codepoint)
73
- # TODO: move this to encoding class
74
- raise_missing_codepoint!(u_codepoint, current_encoding) unless char
75
- write(char)
76
- else
77
- write_u_codepoint(replace.ord, replace: ' ', fallback: true) unless fallback || replace.empty?
78
- end
79
- end
80
- end
81
-
82
- def init_buffer!
83
- sequence(::Escpos::HW_INIT)
84
-
85
- # CJK is on after HW_INIT for Chinese models.
86
- # To ensure consistency, we explicitly set it off.
87
- # https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=175
88
- sequence(Cmd::SET_CJK_OFF) if cjk_supported?
89
- end
90
-
91
- def ascii?(codepoint, extended: false)
92
- (codepoint == 10) ||
93
- (codepoint >= 32 && codepoint <= 126) ||
94
- (extended && codepoint >= 128 && codepoint <= 255)
95
- end
96
-
97
- def set_charset(charset) # rubocop:disable Naming/AccessorMethodName
98
- return if @charset == charset
99
-
100
- sequence([0x1b, 0x52] + [charset])
101
- @charset = charset
102
- end
103
-
104
- def reset_charset!(u_codepoint)
105
- return unless ::Thermal::Db::Charset::CODEPOINTS.include?(u_codepoint)
106
-
107
- set_charset(0)
108
- end
109
-
110
- def set_codepage(codepage) # rubocop:disable Naming/AccessorMethodName
111
- set_cjk(false)
112
- return if @codepage == codepage
113
-
114
- sequence(::Escpos::CP_SET + [codepage])
115
- @codepage = codepage
116
- end
117
-
118
- def set_cjk(enabled) # rubocop:disable Naming/AccessorMethodName
119
- enabled ? set_cjk_on : set_cjk_off
120
- end
121
-
122
- def set_cjk_on
123
- return if !cjk_supported? || @cjk
124
-
125
- sequence(cjk_on_command)
126
- @cjk = true
127
- end
128
-
129
- def set_cjk_off
130
- return if !cjk_supported? || !@cjk
131
-
132
- sequence(cjk_off_command)
133
- @cjk = false
134
- end
135
-
136
- def cjk_supported?
137
- !!cjk_encoding
138
- end
139
-
140
- def shift_jis?
141
- cjk_encoding&.ruby == 'Shift_JIS'
142
- end
143
-
144
- def cjk_on_command
145
- if shift_jis?
146
- Cmd::SET_JIS_MODE + [1]
147
- else
148
- Cmd::SET_CJK_ON
149
- end
150
- end
151
-
152
- def cjk_off_command
153
- if shift_jis?
154
- Cmd::SET_JIS_MODE + [0]
155
- else
156
- Cmd::SET_CJK_OFF
157
- end
158
- end
159
-
160
- # TODO: move this to encoding
161
- def raise_missing_codepoint!(u_codepoint, encoding)
162
- klass = encoding.class.name.split('::').last
163
- raise "Codepoint U#{u_codepoint.to_s(16)} not found in #{klass} #{encoding.name}"
164
- end
165
- end
166
- end
167
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Thermal
4
+ module Escpos
5
+ # Inspired by mike42/escpos-php
6
+ # https://github.com/mike42/escpos-php/blob/development/src/Mike42/Escpos/PrintBuffers/EscposPrintBuffer.php
7
+ class Buffer < ::Thermal::ByteBuffer
8
+ extend Forwardable
9
+
10
+ def initialize(profile)
11
+ super()
12
+ @profile = profile
13
+ @codepage = 0
14
+ @charset = 0
15
+ @cjk = false
16
+ init_buffer!
17
+ end
18
+
19
+ def_delegators :@profile,
20
+ :find_encoding,
21
+ :cjk_encoding,
22
+ :codepages,
23
+ :charsets,
24
+ :codepoint_cjk_skip?,
25
+ :codepoint_cjk_force?
26
+
27
+ def current_encoding
28
+ @cjk ? cjk_encoding : codepages[@codepage]
29
+ end
30
+
31
+ def current_charset
32
+ charsets[@charset]
33
+ end
34
+
35
+ def write_text(text, replace: nil, no_cjk: false)
36
+ text = ::Thermal::Util.normalize_utf8(text, replace: replace)
37
+ text&.each_codepoint do |u_codepoint|
38
+ write_u_codepoint(u_codepoint, replace: replace, no_cjk: no_cjk)
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def write_u_codepoint(u_codepoint, replace: nil, no_cjk: false, fallback: false)
45
+ replace ||= ::Thermal.replace_char
46
+
47
+ if ascii?(u_codepoint)
48
+ reset_charset!(u_codepoint)
49
+ write(u_codepoint)
50
+ elsif current_encoding &&
51
+ (!@cjk || (!no_cjk && !codepoint_cjk_skip?(u_codepoint))) &&
52
+ (@cjk || !codepoint_cjk_force?(u_codepoint)) &&
53
+ (codepoint = current_encoding.codepoint(u_codepoint))
54
+ write(codepoint)
55
+ else
56
+ location, value = find_encoding(u_codepoint, no_cjk: no_cjk)
57
+ case location
58
+ when :codepage
59
+ set_codepage(value)
60
+ codepoint = current_encoding.codepoint(u_codepoint)
61
+ # TODO: move this to encoding class
62
+ raise_missing_codepoint!(u_codepoint, current_encoding) unless codepoint
63
+ write(codepoint)
64
+ when :charset
65
+ set_charset(value)
66
+ codepoint = current_charset.codepoint(u_codepoint)
67
+ # TODO: move this to encoding class
68
+ raise_missing_codepoint!(u_codepoint, current_encoding) unless codepoint
69
+ write(codepoint)
70
+ when :cjk
71
+ set_cjk(true)
72
+ char = current_encoding.codepoint(u_codepoint)
73
+ # TODO: move this to encoding class
74
+ raise_missing_codepoint!(u_codepoint, current_encoding) unless char
75
+ write(char)
76
+ else
77
+ write_u_codepoint(replace.ord, replace: ' ', fallback: true) unless fallback || replace.empty?
78
+ end
79
+ end
80
+ end
81
+
82
+ def init_buffer!
83
+ sequence(::Escpos::HW_INIT)
84
+
85
+ # CJK is on after HW_INIT for Chinese models.
86
+ # To ensure consistency, we explicitly set it off.
87
+ # https://reference.epson-biz.com/modules/ref_escpos/index.php?content_id=175
88
+ sequence(Cmd::SET_CJK_OFF) if cjk_supported?
89
+ end
90
+
91
+ def ascii?(codepoint, extended: false)
92
+ (codepoint == 10) ||
93
+ codepoint.between?(32, 126) ||
94
+ (extended && codepoint.between?(128, 255))
95
+ end
96
+
97
+ def set_charset(charset) # rubocop:disable Naming/AccessorMethodName
98
+ return if @charset == charset
99
+
100
+ sequence([0x1b, 0x52] + [charset])
101
+ @charset = charset
102
+ end
103
+
104
+ def reset_charset!(u_codepoint)
105
+ return unless ::Thermal::Db::Charset::CODEPOINTS.include?(u_codepoint)
106
+
107
+ set_charset(0)
108
+ end
109
+
110
+ def set_codepage(codepage) # rubocop:disable Naming/AccessorMethodName
111
+ set_cjk(false)
112
+ return if @codepage == codepage
113
+
114
+ sequence(::Escpos::CP_SET + [codepage])
115
+ @codepage = codepage
116
+ end
117
+
118
+ def set_cjk(enabled) # rubocop:disable Naming/AccessorMethodName
119
+ enabled ? set_cjk_on : set_cjk_off
120
+ end
121
+
122
+ def set_cjk_on
123
+ return if !cjk_supported? || @cjk
124
+
125
+ sequence(cjk_on_command)
126
+ @cjk = true
127
+ end
128
+
129
+ def set_cjk_off
130
+ return if !cjk_supported? || !@cjk
131
+
132
+ sequence(cjk_off_command)
133
+ @cjk = false
134
+ end
135
+
136
+ def cjk_supported?
137
+ !!cjk_encoding
138
+ end
139
+
140
+ def shift_jis?
141
+ cjk_encoding&.ruby == 'Shift_JIS'
142
+ end
143
+
144
+ def cjk_on_command
145
+ if shift_jis?
146
+ Cmd::SET_JIS_MODE + [1]
147
+ else
148
+ Cmd::SET_CJK_ON
149
+ end
150
+ end
151
+
152
+ def cjk_off_command
153
+ if shift_jis?
154
+ Cmd::SET_JIS_MODE + [0]
155
+ else
156
+ Cmd::SET_CJK_OFF
157
+ end
158
+ end
159
+
160
+ # TODO: move this to encoding
161
+ def raise_missing_codepoint!(u_codepoint, encoding)
162
+ klass = encoding.class.name.split('::').last
163
+ raise "Codepoint U#{u_codepoint.to_s(16)} not found in #{klass} #{encoding.name}"
164
+ end
165
+ end
166
+ end
167
+ end
@@ -1,71 +1,71 @@
1
- # frozen_string_literal: true
2
-
3
- module Thermal
4
- class Profile
5
- extend Forwardable
6
-
7
- # TODO: some of these methods can be moved to an Escpos::Encoder class.
8
-
9
- # These characters should always use codepage, even if present
10
- # in CJK. HR chars have issues with double-printing in CJK encodings
11
- # on Epson printers. This has been observed on Japanese (Shift-JIS)
12
- # with \u2500 and Simplified Chinese (GB18030) with \u2584.
13
- CODEPOINTS_CJK_SKIP = [
14
- "\u2500".."\u259F", # box drawing + block elements
15
- "\u2660".."\u2667" # card suits
16
- ].map(&:to_a).flatten.join.each_codepoint.to_a.freeze
17
-
18
- # These characters exist in the Katakana codepage,
19
- # but should use CJK encoding if available.
20
- CODEPOINTS_CJK_FORCE = 'ε††εΉ΄ζœˆζ—₯ζ™‚εˆ†η§’γ€’εΈ‚εŒΊη”Ίζ‘δΊΊ'.each_codepoint.to_a.freeze
21
-
22
- # Wraps a Device object with CJK encoding support.
23
- def initialize(device, **opts)
24
- @device_key = device.to_s
25
- @cjk = ::Thermal::Db.find_cjk_encoding(opts[:cjk_encoding]) || opts[:cjk_encoding]
26
- end
27
-
28
- def device_name
29
- device.name
30
- end
31
-
32
- def cjk_encoding
33
- return @cjk_encoding if defined?(@cjk_encoding)
34
-
35
- @cjk_encoding = ::Thermal::Db.cjk_encoding(@cjk)
36
- end
37
-
38
- def_delegators :device,
39
- :format,
40
- :codepages,
41
- :charsets,
42
- :supports?,
43
- :col_width
44
-
45
- def find_encoding(u_codepoint, no_cjk: false)
46
- device_encoding = device.find_encoding(u_codepoint)
47
- if device_encoding && !codepoint_cjk_force?(u_codepoint)
48
- device_encoding
49
- elsif !no_cjk && cjk_encoding&.codepoint?(u_codepoint)
50
- [:cjk, true].freeze
51
- else # rubocop:disable Lint/DuplicateBranch
52
- # codepoint_cjk_force failed
53
- device_encoding
54
- end
55
- end
56
-
57
- def codepoint_cjk_skip?(u_codepoint)
58
- CODEPOINTS_CJK_SKIP.include?(u_codepoint)
59
- end
60
-
61
- def codepoint_cjk_force?(u_codepoint)
62
- CODEPOINTS_CJK_FORCE.include?(u_codepoint)
63
- end
64
-
65
- private
66
-
67
- def device
68
- @device ||= ::Thermal::Db.device(@device_key)
69
- end
70
- end
71
- end
1
+ # frozen_string_literal: true
2
+
3
+ module Thermal
4
+ class Profile
5
+ extend Forwardable
6
+
7
+ # TODO: some of these methods can be moved to an Escpos::Encoder class.
8
+
9
+ # These characters should always use codepage, even if present
10
+ # in CJK. HR chars have issues with double-printing in CJK encodings
11
+ # on Epson printers. This has been observed on Japanese (Shift-JIS)
12
+ # with \u2500 and Simplified Chinese (GB18030) with \u2584.
13
+ CODEPOINTS_CJK_SKIP = [
14
+ "\u2500".."\u259F", # box drawing + block elements
15
+ "\u2660".."\u2667" # card suits
16
+ ].map(&:to_a).join.each_codepoint.to_a.freeze
17
+
18
+ # These characters exist in the Katakana codepage,
19
+ # but should use CJK encoding if available.
20
+ CODEPOINTS_CJK_FORCE = 'ε††εΉ΄ζœˆζ—₯ζ™‚εˆ†η§’γ€’εΈ‚εŒΊη”Ίζ‘δΊΊ'.each_codepoint.to_a.freeze
21
+
22
+ # Wraps a Device object with CJK encoding support.
23
+ def initialize(device, **opts)
24
+ @device_key = device.to_s
25
+ @cjk = ::Thermal::Db.find_cjk_encoding(opts[:cjk_encoding]) || opts[:cjk_encoding]
26
+ end
27
+
28
+ def device_name
29
+ device.name
30
+ end
31
+
32
+ def cjk_encoding
33
+ return @cjk_encoding if defined?(@cjk_encoding)
34
+
35
+ @cjk_encoding = ::Thermal::Db.cjk_encoding(@cjk)
36
+ end
37
+
38
+ def_delegators :device,
39
+ :format,
40
+ :codepages,
41
+ :charsets,
42
+ :supports?,
43
+ :col_width
44
+
45
+ def find_encoding(u_codepoint, no_cjk: false)
46
+ device_encoding = device.find_encoding(u_codepoint)
47
+ if device_encoding && !codepoint_cjk_force?(u_codepoint)
48
+ device_encoding
49
+ elsif !no_cjk && cjk_encoding&.codepoint?(u_codepoint)
50
+ [:cjk, true].freeze
51
+ else # rubocop:disable Lint/DuplicateBranch
52
+ # codepoint_cjk_force failed
53
+ device_encoding
54
+ end
55
+ end
56
+
57
+ def codepoint_cjk_skip?(u_codepoint)
58
+ CODEPOINTS_CJK_SKIP.include?(u_codepoint)
59
+ end
60
+
61
+ def codepoint_cjk_force?(u_codepoint)
62
+ CODEPOINTS_CJK_FORCE.include?(u_codepoint)
63
+ end
64
+
65
+ private
66
+
67
+ def device
68
+ @device ||= ::Thermal::Db.device(@device_key)
69
+ end
70
+ end
71
+ end
@@ -216,8 +216,11 @@ module Stargraphic
216
216
  def text_image(markup, width: @width, align: :left, font: 'Sans', delete: true)
217
217
  tmp_path = ::Thermal.tmp_path("#{SecureRandom.uuid}.png")
218
218
 
219
+ # TODO: Fix font loading
220
+ # font ||= self.class.font
221
+
219
222
  begin
220
- ::MiniMagick::Tool::Convert.new do |i|
223
+ configure = proc do |i|
221
224
  i << '+antialias'
222
225
  i << '+dither'
223
226
  i.size width
@@ -232,6 +235,12 @@ module Stargraphic
232
235
  i.negate
233
236
  i << tmp_path
234
237
  end
238
+
239
+ if ::MiniMagick.respond_to?(:convert) # MiniMagick 5+
240
+ ::MiniMagick.convert(&configure)
241
+ else
242
+ ::MiniMagick::Tool::Convert.new(&configure)
243
+ end
235
244
  rescue StandardError => e
236
245
  Bugsnag.notify(e) do |r|
237
246
  r.add_metadata('data',
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Thermal
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thermal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Johnny Shields
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2025-03-12 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: base64
@@ -93,7 +92,6 @@ homepage: https://github.com/tablecheck/thermal
93
92
  licenses: []
94
93
  metadata:
95
94
  rubygems_mfa_required: 'true'
96
- post_install_message:
97
95
  rdoc_options: []
98
96
  require_paths:
99
97
  - lib
@@ -108,8 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
106
  - !ruby/object:Gem::Version
109
107
  version: '0'
110
108
  requirements: []
111
- rubygems_version: 3.5.11
112
- signing_key:
109
+ rubygems_version: 4.0.4
113
110
  specification_version: 4
114
111
  summary: Thermal printer support for Ruby
115
112
  test_files: []