tui-td 0.2.7 → 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/lib/tui_td/cairo_renderer.rb +109 -0
- data/lib/tui_td/screenshot.rb +26 -4
- 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
|
|
@@ -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/screenshot.rb
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
require "chunky_png"
|
|
4
4
|
require_relative "ansi_utils"
|
|
5
|
+
require_relative "cairo_renderer"
|
|
6
|
+
require_relative "unifont_glyphs"
|
|
5
7
|
|
|
6
8
|
module TUITD
|
|
7
9
|
class Screenshot
|
|
@@ -356,12 +358,32 @@ module TUITD
|
|
|
356
358
|
return
|
|
357
359
|
end
|
|
358
360
|
|
|
359
|
-
return if char == " " || char_ord < 32
|
|
361
|
+
return if char == " " || char_ord < 32
|
|
360
362
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
+
# ASCII printable (33-126): use Spleen bitmap font (pixel-perfect)
|
|
364
|
+
if char_ord <= 126
|
|
365
|
+
rows_data = glyph_rows(char)
|
|
366
|
+
if rows_data
|
|
367
|
+
draw_glyph(image, px, py, rows_data, fg_rgb, bold: bold, italic: italic)
|
|
368
|
+
draw_underline(image, px, py, CELL_W, fg_rgb) if underline
|
|
369
|
+
return
|
|
370
|
+
end
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Unicode (127+): try Unifont bitmap first (pixel-perfect like Spleen)
|
|
374
|
+
if char_ord > 126
|
|
375
|
+
unifont_rows = UnifontGlyphs.rows(char_ord)
|
|
376
|
+
if unifont_rows
|
|
377
|
+
draw_glyph(image, px, py, unifont_rows, fg_rgb, bold: bold, italic: italic)
|
|
378
|
+
draw_underline(image, px, py, CELL_W, fg_rgb) if underline
|
|
379
|
+
return
|
|
380
|
+
end
|
|
381
|
+
end
|
|
363
382
|
|
|
364
|
-
|
|
383
|
+
# Fallback: render via Cairo for characters not in Unifont
|
|
384
|
+
if CairoRenderer.available?
|
|
385
|
+
CairoRenderer.render_glyph_onto(image, px, py, char, fg_rgb, bold: bold, italic: italic)
|
|
386
|
+
end
|
|
365
387
|
|
|
366
388
|
draw_underline(image, px, py, CELL_W, fg_rgb) if underline
|
|
367
389
|
end
|