tui-td 0.2.6 → 0.2.8
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 +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +8 -4
- data/lib/tui_td/cairo_renderer.rb +109 -0
- data/lib/tui_td/driver.rb +2 -0
- data/lib/tui_td/screenshot.rb +495 -6
- data/lib/tui_td/unifont_glyphs.rb +2789 -0
- data/lib/tui_td/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ebeda13c1510dfd65ec0dd5e45a330ed9100c3dd5a0919dfcedb13340e01a280
|
|
4
|
+
data.tar.gz: fe33d4368ae7b516f18b7cc30974124408214dbd116f6e300986b05a967e4835
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f1c7051f157319f46d96f371654d276ada570e2aea06d4871659cf989734f5c3d65c0da163a23d56ebb844d3c3cb3b5087b6fcc60f8dcebfdbec0d35ab317720
|
|
7
|
+
data.tar.gz: 2f74615955a3434efe4d06427099ae18eca2c43bdefe93b6c8b2465ebb2eb28f84024ecbcfcbda39cedec4e5ac0373141d6f6ec0ac31aff6a64f7cf8b9ebb781
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
+
## 0.2.7
|
|
4
|
+
|
|
5
|
+
- Screenshot rendering for 23 special characters: blocks (▀ ▄ █), triangles (▲ ▼), arrows (↑ ↓ → ←), half blocks (▌ ▐)
|
|
6
|
+
- Screenshot rendering for symbols: checkmarks (✓ ✗ ✖), checkboxes (☐ ☑ ☒), gear (⚙), warning (⚠), info (ℹ)
|
|
7
|
+
- Screenshot rendering for punctuation: ellipsis (…), em dash (—)
|
|
8
|
+
- Cursor drawing support in screenshot renderer
|
|
9
|
+
- Braille character rendering in screenshot
|
|
10
|
+
- Rounded corner box-drawing characters (╭ ╮ ╯ ╰) in screenshot
|
|
11
|
+
- `page_up` / `page_down` key support in test runner and driver
|
|
12
|
+
- Fixed junction pixels in rounded corner box-drawing characters
|
|
13
|
+
|
|
3
14
|
## 0.2.6
|
|
4
15
|
|
|
5
16
|
- ISO-2022 charset switching support (G0/G1 designators, Shift Out/In) with DEC Special Character & Line Drawing mapping
|
data/README.md
CHANGED
|
@@ -417,10 +417,14 @@ Top-level structure returned by `state_data` / `--json`:
|
|
|
417
417
|
|
|
418
418
|
```json
|
|
419
419
|
{
|
|
420
|
-
"size":
|
|
421
|
-
"cursor":
|
|
422
|
-
"
|
|
423
|
-
"
|
|
420
|
+
"size": {"rows": 40, "cols": 120},
|
|
421
|
+
"cursor": {"row": 5, "col": 12},
|
|
422
|
+
"cursor_visible": true,
|
|
423
|
+
"cursor_style": "block",
|
|
424
|
+
"mouse_mode": null,
|
|
425
|
+
"mouse_format": null,
|
|
426
|
+
"rows": [[{"char": "A", "fg": "cyan", ...}]],
|
|
427
|
+
"raw": "\e[31mred\e[0m\n..."
|
|
424
428
|
}
|
|
425
429
|
```
|
|
426
430
|
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TUITD
|
|
4
|
+
module CairoRenderer
|
|
5
|
+
CELL_W = 8
|
|
6
|
+
CELL_H = 16
|
|
7
|
+
DEFAULT_FONT = "Arial Unicode MS"
|
|
8
|
+
FONT_SIZE = 12.0
|
|
9
|
+
RENDER_SCALE = 3
|
|
10
|
+
|
|
11
|
+
@available = false
|
|
12
|
+
@cache = {}
|
|
13
|
+
|
|
14
|
+
begin
|
|
15
|
+
require "cairo"
|
|
16
|
+
@available = true
|
|
17
|
+
rescue LoadError
|
|
18
|
+
# Cairo not available; render_glyph_onto is a no-op
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class << self
|
|
22
|
+
def available?
|
|
23
|
+
@available
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def render_glyph_onto(cpn_image, px, py, char, fg_rgb, bold:, italic:)
|
|
27
|
+
return unless available?
|
|
28
|
+
|
|
29
|
+
alpha = glyph_alpha(char, bold: bold, italic: italic)
|
|
30
|
+
composite(alpha, cpn_image, px, py, fg_rgb)
|
|
31
|
+
rescue StandardError => e
|
|
32
|
+
warn "CairoRenderer: #{e.message}" if $DEBUG
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
def glyph_alpha(char, bold:, italic:)
|
|
38
|
+
key = [char.ord, bold, italic]
|
|
39
|
+
@cache[key] ||= render_surface(char, bold, italic)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def render_surface(char, bold, italic)
|
|
43
|
+
# Render at higher resolution then box-filter downsample for smoother edges
|
|
44
|
+
scale = RENDER_SCALE
|
|
45
|
+
big_w = CELL_W * scale
|
|
46
|
+
big_h = CELL_H * scale
|
|
47
|
+
surface = Cairo::ImageSurface.new(Cairo::Format::ARGB32, big_w, big_h)
|
|
48
|
+
context = Cairo::Context.new(surface)
|
|
49
|
+
|
|
50
|
+
context.antialias = Cairo::ANTIALIAS_NONE
|
|
51
|
+
|
|
52
|
+
fo = Cairo::FontOptions.new
|
|
53
|
+
fo.hint_style = Cairo::HINT_STYLE_FULL
|
|
54
|
+
fo.hint_metrics = Cairo::HINT_METRICS_ON
|
|
55
|
+
context.font_options = fo
|
|
56
|
+
|
|
57
|
+
slant = italic ? Cairo::FONT_SLANT_ITALIC : Cairo::FONT_SLANT_NORMAL
|
|
58
|
+
weight = bold ? Cairo::FONT_WEIGHT_BOLD : Cairo::FONT_WEIGHT_NORMAL
|
|
59
|
+
context.select_font_face(DEFAULT_FONT, slant, weight)
|
|
60
|
+
context.set_font_size(FONT_SIZE * scale)
|
|
61
|
+
|
|
62
|
+
extents = context.text_extents(char)
|
|
63
|
+
x_off = ((big_w - extents.width) / 2.0) - extents.x_bearing
|
|
64
|
+
y_off = ((big_h - extents.height) / 2.0) - extents.y_bearing
|
|
65
|
+
|
|
66
|
+
context.set_source_rgba(1.0, 1.0, 1.0, 1.0)
|
|
67
|
+
context.move_to(x_off, y_off)
|
|
68
|
+
context.show_text(char)
|
|
69
|
+
|
|
70
|
+
data = surface.data
|
|
71
|
+
stride = surface.stride
|
|
72
|
+
scale_sq = scale * scale
|
|
73
|
+
|
|
74
|
+
alpha_grid = Array.new(CELL_H) { Array.new(CELL_W, 0) }
|
|
75
|
+
CELL_H.times do |dy|
|
|
76
|
+
CELL_W.times do |dx|
|
|
77
|
+
sum = 0
|
|
78
|
+
scale.times do |sy|
|
|
79
|
+
row_off = (dy * scale + sy) * stride
|
|
80
|
+
scale.times do |sx|
|
|
81
|
+
sum += data.getbyte(row_off + (dx * scale + sx) * 4 + 3)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
alpha_grid[dy][dx] = sum / scale_sq
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
alpha_grid
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def composite(alpha_grid, cpn_image, px, py, fg_rgb)
|
|
92
|
+
fr, fg, fb = fg_rgb
|
|
93
|
+
|
|
94
|
+
CELL_H.times do |dy|
|
|
95
|
+
CELL_W.times do |dx|
|
|
96
|
+
a = alpha_grid[dy][dx]
|
|
97
|
+
next if a < 24
|
|
98
|
+
|
|
99
|
+
factor = [a, 255].min / 255.0
|
|
100
|
+
r = (fr * factor).to_i
|
|
101
|
+
g = (fg * factor).to_i
|
|
102
|
+
b = (fb * factor).to_i
|
|
103
|
+
cpn_image[px + dx, py + dy] = ChunkyPNG::Color.rgb(r, g, b)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
data/lib/tui_td/driver.rb
CHANGED