skrift-x11 0.2.1 → 0.2.2

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: 92507a6b036b8ab2eb0145017a938019111e2ea17c4e001a693529d2518876f3
4
- data.tar.gz: 2da4b5247c4e4b085a4f4591594d09f69f2f35a93c7fe43210b68f7efbfe3798
3
+ metadata.gz: a75688a1a4f9e322d33c58a9b0a29b2fb26c27536a137e33dd97c340a491dd98
4
+ data.tar.gz: 87a5c7f3f29918f0031e637acbc4d08a6d8d6f122b3112c597515086fa1d0317
5
5
  SHA512:
6
- metadata.gz: 8bac35a07d623a9f27539ec68d2a2cc4eb2cc906e788660a7cbea25323d55ff30ada7ac1474f92c7caa4b8c92a50a509bf6eaf25550c5e04d6e273a13aebe15f
7
- data.tar.gz: c35c1e39c5b5ef7daf70257dc14e0930ac70607e78b6bc8397563964377d8e090b4472162fbbb061c05c584553ae6d0b7e937e7d3ecc156f534b6eed518c41e5
6
+ metadata.gz: 7db2e7d2a63a2afa679ca83652136e13e954b3eee2c11d55c5734c48ed10be641a8fee0eca3d1df779a1d4c19c7a4172027d9aea1659f4bb8f4728f6de3ded3e
7
+ data.tar.gz: 4014ba510524d9921c9eb67986b137151f98aca2cd71427e431fdcefe776c5c869e45b45de09d3a692fe77976f82da4c7df6bdb08ca687736301d43a45f5af12
data/example.rb CHANGED
@@ -52,7 +52,7 @@ f = Font.load("resources/FiraGO-Regular_extended_with_NotoSansEgyptianHieroglyph
52
52
  $skrift = Skrift::X11::Glyphs.new(dpy, f, x_scale: 40, y_scale: 40)
53
53
 
54
54
  def redraw(dpy, wid, gc)
55
- dpy.poly_fill_rectangle(wid, gc, [X11::Form::Rectangle.new(20,45, 400, 400)])
55
+ dpy.poly_fill_rectangle(wid, gc, [20,45, 400, 400])
56
56
  $skrift.render_str($pic, 0xffffff, 50,90, 'Pure Ruby w/Skrift!')
57
57
  $skrift.render_str($pic, 0xffffff, 50,140, "And unicode:")
58
58
  $skrift.render_str($pic, 0xff00ff, 50,200, "Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα.")
@@ -0,0 +1,198 @@
1
+ module Skrift
2
+ module X11
3
+ class Glyphs
4
+
5
+ def empty_box_image
6
+ img = Image.new(stride, boxh)
7
+ img.pixels = Array.new(img.width*img.height,0x00)
8
+ img
9
+ end
10
+
11
+
12
+ def cache_box(ch)
13
+ @boxcache ||= {}
14
+ c = @boxcache[ch] if @boxcache[ch]
15
+
16
+ hx = (boxw+1)/2
17
+ hy = (boxh+1)/2
18
+ yoff = hy*stride
19
+ img = nil
20
+ h = 1 # 1/3 width of "heavy" line
21
+
22
+ lh = light_h = [-255, 0,255, 0, 255]; hh = heavy_h = [-255, -h,255, h, 255]
23
+ lv = light_v = [ 0,-255, 0,255, 255]; hv = heavy_v = [ -h,-255, h,255, 255]
24
+
25
+ ll = light_l = [-255, 0, 0, 0, 255]; hl = heavy_l = [-255, -h, 0, h, 255]
26
+ lu = light_u = [ 0,-255, 0, 0, 255]; hu = heavy_u = [ -h,-255, h, 0, 255]
27
+ lr = light_r = [ 0, 0,255, 0, 255]; hr = heavy_r = [ 0, -h,255, h, 255]
28
+ ld = light_d = [ 0, 0, 0,255, 255]; hd = heavy_d = [ -h, 0, h,255, 255]
29
+
30
+ hc = [ -h, -h, h, h, 255] # Heavy centre
31
+
32
+ d = 2
33
+ dblc = [-d+1, -d+1, d-1, d-1, 0] # Gap in centre of double lines.
34
+ light_vc = [0, -d, 0, d, 255] # Light vertical crossing centre of double line.
35
+
36
+ dh = double_h = [-255,-d,255,-d, 255] + [-255, d,255, d, 255]
37
+ dv = double_v = [-d,-255,-d,255, 255] + [d,-255,d,255, 255]
38
+
39
+ mask_vbar = [-d+1,-255,d-1,255,0]
40
+ mask_hbar = [-255,-d+1,255,d-1,0]
41
+
42
+ mt= masktop = [-255,-255, 255, -1, 0]; maskdtop = [-255,-255, 255,-d-1, 0]
43
+ ml=maskleft = [-255,-255, -1, 255, 0]; maskdleft = [-255,-255,-d-1, 255, 0]
44
+ mb=maskbottom = [-255, 1, 255, 255, 0]; maskdbottom= [-255, d+1, 255, 255, 0]
45
+ mr=maskright = [ 1,-255, 255, 255, 0]; maskdright = [ d+1,-255, 255, 255, 0]
46
+
47
+ mask_lbar = [-255,-d+1,d-1,d-1, 0]; dlbar=double_lbar = [-255,-d,d,d, 255]
48
+ mask_tbar = [-d+1,-255,d-1,d-1, 0]; dtbar=double_tbar = [-d,-255,d,d, 255]
49
+ mask_rbar = [-d+1,-d+1,255,d-1, 0]; drbar=double_rbar = [-d,-d,255,d, 255]
50
+ mask_dbar = [-d+1,-d+1,d-1,255, 0]; ddbar=double_dbar = [-d,-d,d,255, 255]
51
+
52
+ mask_c = [0,0,0,0,0]
53
+
54
+ hdl = heavy_dl = [heavy_d, heavy_l, hc]
55
+ hdr = heavy_dr = [heavy_d, heavy_r, hc]
56
+ hlu = heavy_lu = [heavy_l, heavy_u, hc]
57
+ hru = heavy_ru = [heavy_r, heavy_u, hc]
58
+ ldl = light_dl = [light_d, light_l]
59
+ ldr = light_dr = [light_d, light_r]
60
+ llu = light_lu = [light_l, light_u]
61
+ lru = light_ru = [light_r, light_u]
62
+
63
+ # FIXME Makes stipples wider when tx/ty etc. are big enough
64
+ tx = hx - boxw / 3
65
+ mv2 = mask_v2 = [[-tx, -255, -tx, 255, 0], [tx, -255, tx, 255,0]]
66
+
67
+ ty = hy - boxh / 3
68
+ mh2 = mask_h2 = [[-255,-ty, 255,-ty,0], [-255,ty,255,ty,0]]
69
+
70
+ rects = {
71
+ 0x2500 => lh, 0x2501 => hh, 0x2502 => lv, 0x2503 => hv,
72
+ 0x2504 => lh + mv2, 0x2505 => hh + mv2, 0x2506 => lv + mh2, 0x2507 => hv + mv2,
73
+ 0x2508 => lh, # FIXME: Stippled
74
+ 0x2509 => hh, # FIXME: Stippled
75
+ 0x250A => lv, # FIXME: Stippled
76
+ 0x250B => hv, # FIXME: Stippled
77
+
78
+ 0x250C => ldr, 0x250D => hr + ld, 0x250E => hd + lr, 0x250F => hdr,
79
+ 0x2510 => ldl, 0x2511 => hl + ld, 0x2512 => [hd, ll], 0x2513 => hdl,
80
+ 0x2514 => lru, 0x2515 => lu + hr, 0x2516 => lr + hu, 0x2517 => hru,
81
+ 0x2518 => llu, 0x2519 => [hl, lu], 0x251a => [ll, hu], 0x251b => hlu,
82
+ 0x251c => lv+lr, 0x251d => [lv, hr], 0x251e => ldr + hu, 0x251f => [lru, hd],
83
+
84
+ 0x2520 => hv + lr, 0x2521 => hru + ld, 0x2522 => hdr + lu, 0x2523 => hv + hr,
85
+ 0x2524 => ll + lv, 0x2525 => hl + lv, 0x2526 => hu + ldl, 0x2527 => hd + lu,
86
+ 0x2528 => hv + ll, 0x2529 => hlu + ld, 0x252a => hdl+lu, 0x252b => hl + hv,
87
+ 0x252c => lh + ld, 0x252d => [hl, ldr], 0x252e => [hr, ldr], 0x252f => [hh, ld],
88
+
89
+ 0x2530 => [lh, hd], 0x2531 => [hdl, lr], 0x2532 => [ll, hdr], 0x2533 => [hh, hd],
90
+ 0x2534 => [lh, lu], 0x2535 => [lru, hl], 0x2536 => [llu, hr], 0x2537 => [hh, lu],
91
+ 0x2538 => [lh, hu], 0x2539 => [hlu, lr], 0x253a => [hru, ll], 0x253b => [hh, hu],
92
+ 0x253c => [lv, lh], 0x253d => lv+lr+hl, 0x253e => ll+lv+hr, 0x253f => [lv, hh],
93
+
94
+ 0x2540 => [lh, ld, hu], 0x2541 => [light_h, light_u, heavy_d], 0x2542 => [heavy_v, light_h], 0x2543 => [heavy_l, heavy_u, hc, light_d, light_r],
95
+ 0x2544 => [ll, ld, hru], 0x2545 => [heavy_dl, light_ru], 0x2546 => [light_lu, heavy_dr], 0x2547 => [heavy_h, heavy_u, light_d],
96
+ 0x2548 => [hh, hd, light_u], 0x2549 => [heavy_v, heavy_l, light_r], 0x254a => [heavy_v, light_l, heavy_r], 0x254b => [heavy_v, heavy_h],
97
+ 0x254c => [lh, dblc], 0x254d => [heavy_h, dblc], 0x254e => [light_v, dblc], 0x254f => [heavy_v, dblc],
98
+
99
+ 0x2550 => dh, 0x2551 => dv, 0x2552 => [dh, lv, ml, maskdtop], 0x2553 => [dv, lh, mt, maskdleft],
100
+ 0x2554 => [ddbar, drbar, mask_dbar, mask_rbar], 0x2555 => [dh, mr, lv, maskdtop],
101
+ 0x2556 => [dv, lh,maskdright,mt], 0x2557 => [double_dbar, double_lbar, mask_dbar, mask_lbar],
102
+ 0x2558 => [lv, dh, ml, maskdbottom], 0x2559 => [lh, dv, maskdleft, mb],
103
+ 0x255A => [dtbar, double_rbar, mask_tbar, mask_rbar], 0x255B => [dh, lv, maskdbottom, mr],
104
+ 0x255C => [dv, lh, mb, maskdright], 0x255D => [dtbar, dlbar, mask_tbar, mask_lbar],
105
+ 0x255e => [lv, dh, maskleft], 0x255f => [lh, dv, dblc, maskdleft],
106
+ 0x2560 => [dv, drbar, mask_rbar, mask_vbar], 0x2561 => [lv, dh, maskright],
107
+ 0x2562 => [dv, ll, dblc], 0x2563 => [dlbar, dv, mask_lbar, mask_vbar],
108
+ 0x2564 => [dh, ld, dblc], 0x2565 => [lh, dv, mt],
109
+ 0x2566 => [dh, ddbar,mask_hbar, mask_dbar], 0x2567 => [dh, light_u,dblc],
110
+ 0x2568 => [lh, dv, mb], 0x2569 => [dh, double_tbar, mask_hbar, mask_tbar],
111
+ 0x256A => dh+lv, 0x256b => dv+lh, 0x256c => [dh, dv, mask_hbar, mask_vbar],
112
+
113
+ # 256d, 256e, 256f, 2570 => curves
114
+ # FIXME: Current is just very slightly rounded.
115
+ 0x256d => [ldr, mask_c], 0x256e => [ldl, mask_c], 0x256f => [llu, mask_c], 0x2570 => [lru, mask_c],
116
+
117
+ # 2571, 2572. 2573 => diagonals, handled below.
118
+ 0x2571 => nil, 0x2572 => nil, 0x2573 => nil,
119
+
120
+ 0x2574 => ll, 0x2575 => lu, 0x2576 => lr, 0x2577 => ld,
121
+ 0x2578 => hl, 0x2579 => hu, 0x257a => hr, 0x257b => hd,
122
+ 0x257c => ll + hr, 0x257d => lu + hd, 0x257e => hl + lr, 0x257f => hu + ld
123
+
124
+ }
125
+
126
+ r = rects[ch.ord]
127
+ if r
128
+ img = empty_box_image
129
+ r.flatten.each_slice(5) do |rect|
130
+ p rect
131
+ x1,y1,x2,y2, col = *rect
132
+ x1 = (x1+hx).clamp(0,boxw-1)
133
+ x2 = (x2+hx).clamp(0,boxw-1)
134
+ y1 = (y1+hy).clamp(0,boxh-1)
135
+ y2 = (y2+hy).clamp(0,boxh-1)
136
+ col ||= 255
137
+
138
+ a = Array.new(x2-x1+1,col)
139
+
140
+ (y1..y2).each do |y|
141
+ img.pixels[y*stride + x1 .. y*stride + x2] = a
142
+ end
143
+ end
144
+ return img
145
+ end
146
+
147
+ if ch.ord == 0x2571
148
+ img = empty_box_image
149
+ slope = boxw.to_f / boxh
150
+ x = boxw.to_f-1
151
+ (0...boxh).each do |y|
152
+ err = x - x.to_i
153
+ img.pixels[y*stride+x.ceil] = 255 #(255*(1-err)).floor
154
+ img.pixels[y*stride+x.ceil-1] = (255*err).floor if x > 0
155
+ x-= slope
156
+ end
157
+ return img
158
+ end
159
+
160
+ # FIXME: If size is *at* certain levels level, this, and the next one fails?
161
+
162
+ if ch.ord == 0x2572
163
+ img = empty_box_image
164
+ slope = boxw.to_f / boxh
165
+ x = boxw.to_f-1
166
+ (0...boxh).each do |y|
167
+ err = x - x.to_i
168
+ img.pixels[y*stride+boxw-x.ceil-1] = 255
169
+ img.pixels[y*stride+boxw-x.ceil] = (255*err).floor if x > 0
170
+ x-= slope
171
+ end
172
+ return img
173
+ end
174
+
175
+ if ch.ord == 0x2573
176
+ img = empty_box_image
177
+ slope = boxw.to_f / boxh
178
+ x = boxw.to_f-1
179
+ (0...boxh).each do |y|
180
+ err = x - x.to_i
181
+ img.pixels[y*stride+boxw-x.ceil-1] = 255
182
+ img.pixels[y*stride+boxw-x.ceil] = (255*err).floor if x > 0
183
+ img.pixels[y*stride+x.ceil-1] = (255*err).floor if x > 0
184
+ img.pixels[y*stride+x.ceil] = 255 #(255*(1-err)).floor
185
+ x-= slope
186
+ end
187
+ return img
188
+ end
189
+
190
+ if img
191
+ img = img.dup
192
+ img.pixels = img.pixels.dup
193
+ end
194
+ img || empty_box_image
195
+ end
196
+ end
197
+ end
198
+ end
@@ -1,23 +1,70 @@
1
1
 
2
- require 'skrift'
3
- module Skrift
4
- module X11
5
- # XRender constants currently not defined in pure-x11.
6
- # FIXME.
2
+ require_relative 'boxdrawing'
3
+
4
+ module X11
5
+ # XRender constants currently not defined in pure-x11.
6
+ # FIXME.
7
+ module Form
7
8
  PictOpSrc=1
8
9
  PictOpOver=3
9
10
  CPRepeat = 1
11
+ end
12
+ end
10
13
 
14
+ module Skrift
15
+ module X11
16
+
11
17
  class Glyphs
18
+ attr_reader :fixed_width
19
+ attr_accessor :maxheight
20
+
21
+ def load_font(index)
22
+ return @fonts[index] if @fonts[index]
23
+ f = @fontset[index]
24
+ return nil if !f
25
+ return @fonts[index] = Font.load(f) if File.exist?(f)
26
+
27
+ # FIXME: Do proper resolution of XDG dirs
28
+ fn = File.expand_path("~/.local/share/fonts/#{f}")
29
+ return @fonts[index] = Font.load(fn) if File.exist?(fn)
30
+
31
+ fn = `fc-match --format='%{file}\n' #{fn}`.split("\n").first
32
+ return @fonts[index] = Font.load(fn) if File.exist?(fn)
33
+ return nil
34
+ end
35
+
36
+ def inspect
37
+ "<Glyphs #{object_id}"
38
+ end
39
+
40
+ def initialize dpy, font=nil, fontset: nil, x_scale:, y_scale:, pic: nil, fixed: nil, maxheight: nil, fit: false
41
+ @fontset = fontset
42
+ @fonts = @fontset ? [] : [font]
43
+ @font = font || load_font(0)
44
+ @maxheight = maxheight
12
45
 
13
- def initialize dpy, font, x_scale:, y_scale:, pic: nil, fixed: nil
14
46
  @dpy = dpy
15
- @sft = SFT.new(font)
47
+ @sft = SFT.new(@font)
16
48
  @sft.x_scale = x_scale
17
49
  @sft.y_scale = y_scale
18
50
  @pic = pic
19
51
  @fixed = fixed
52
+ # When set (with a fixed cell), glyphs whose natural size exceeds the
53
+ # cell are scaled down to fit and centred instead of being clamped
54
+ # (and distorted) at the cell edge by the rasteriser.
55
+ @fit = fit
20
56
 
57
+ g = @sft.gmetrics(@sft.lookup("M".ord))
58
+ if !g
59
+ g = @sft.gmetrics(0)
60
+ end
61
+ if g
62
+ @fixed_width = g.advance_width.ceil
63
+ else
64
+ @fixed_width = x_scale
65
+ end
66
+
67
+ @nextgid = 1
21
68
  @glyphcache = {}
22
69
  @colcache = {}
23
70
  @chcache = {}
@@ -30,11 +77,6 @@ module Skrift
30
77
  end
31
78
 
32
79
  attr_accessor :lm
33
- def gm(ch)
34
- gid = @sft.lookup(ch.ord)
35
- @sft.gmetrics(gid)
36
- end
37
-
38
80
 
39
81
  def fill_for_col(col)
40
82
  return @colcache[col] if @colcache[col]
@@ -48,26 +90,74 @@ module Skrift
48
90
  @colcache[col] ||= @dpy.render_create_solid_fill(r,g,b,0xffff)
49
91
  end
50
92
 
51
- def fixed_width
52
- return @fixed_width if @fixed_width
53
- if @fixed
54
- # *Ensure* that the glyphs are equal width.
55
- g = gm("M")
56
- @fixed_width = g.advance_width.ceil
57
- else
58
- nil
59
- end
93
+ private
94
+
95
+ def boxw = @fixed_width
96
+ def stride = (@fixed_width +3)&~3
97
+ def boxh
98
+ @boxh ||= [@maxheight, @lm.ascender.ceil-@lm.descender.ceil].compact.min
60
99
  end
61
-
62
-
63
- def cache_glyph(gid, baseline)
100
+
101
+
102
+ def cache_special(ch)
103
+ # Box drawing
104
+ return nil if !((0x2500 .. 0x257f) === ch.ord)
105
+
106
+
107
+ img = cache_box(ch.ord)
108
+
109
+
110
+ data = img.pixels.pack("C*")
111
+ info = ::X11::Form::GlyphInfo.new(
112
+ img.width, # w
113
+ img.height, # h
114
+ 0, # x
115
+ 0, # y
116
+ fixed_width,
117
+ 0
118
+ )
119
+
120
+ gsgid = @nextgid
121
+ @nextgid += 1
122
+ @dpy.render_add_glyphs(@glyphset, gsgid, info, data)
123
+ @glyphcache[gsgid] = fixed_width
124
+ @chcache[ch] = {gsgid: gsgid}
125
+ end
126
+
127
+ def cache_glyph(gsgid,gid, baseline)
64
128
  return if gid.nil?
65
129
  mtx = @sft.gmetrics(gid)
130
+ scaled = false
131
+ saved = nil
132
+
133
+ # Oversized glyph in a fixed cell: re-render it at a reduced scale so
134
+ # it fits the cell, then position it through the normal
135
+ # baseline-relative path below (no vertical shift). Otherwise the
136
+ # rasteriser clamps the overflow at the cell edge and distorts the
137
+ # shape. Only glyphs clearly wider/taller than the cell are scaled -
138
+ # a marginal overshoot (e.g. a 'W' a pixel past the cell) is left to
139
+ # the clamp, so ordinary text is untouched.
140
+ if @fit && @fixed && mtx
141
+ sx = (mtx.min_width || 0) > boxw * 1.1 ? boxw.to_f / mtx.min_width : 1.0
142
+ sy = (mtx.min_height || 0) > boxh * 1.1 ? boxh.to_f / mtx.min_height : 1.0
143
+ s = [sx, sy].min
144
+ if s < 1.0
145
+ saved = [@sft.x_scale, @sft.y_scale]
146
+ @sft.x_scale = @sft.x_scale * s
147
+ @sft.y_scale = @sft.y_scale * s
148
+ mtx = @sft.gmetrics(gid)
149
+ scaled = true
150
+ end
151
+ end
66
152
 
67
153
  # FIXME: Not sure what to do if mtx.nil? here.
68
154
  # Maybe use x/y scale?
69
- w = fixed_width || mtx.min_width || 0
70
- h = mtx.min_height || 1
155
+ if @fixed
156
+ w = fixed_width
157
+ else
158
+ w = mtx.min_width || 0
159
+ end
160
+ h = [mtx&.min_height || 1, @maxheight].compact.min
71
161
  #p [w,h]
72
162
  img = Image.new((w+3)&~3, h)
73
163
  if !@sft.render(gid, img)
@@ -76,9 +166,9 @@ module Skrift
76
166
  else
77
167
  data = img.pixels.pack("C*")
78
168
  end
79
-
169
+
80
170
  yoff = mtx.y_offset || baseline
81
-
171
+
82
172
  info = ::X11::Form::GlyphInfo.new(
83
173
  img.width, # w
84
174
  img.height, # h
@@ -88,43 +178,72 @@ module Skrift
88
178
  0
89
179
  )
90
180
 
91
- @dpy.render_add_glyphs(@glyphset, gid, info, data)
92
- @glyphcache[gid] = mtx.advance_width#-mtx.left_side_bearing
181
+ @dpy.render_add_glyphs(@glyphset, gsgid, info, data)
182
+ @glyphcache[gsgid] = scaled ? (fixed_width || mtx.advance_width) : mtx.advance_width
183
+ ensure
184
+ @sft.x_scale, @sft.y_scale = saved if saved
93
185
  end
94
186
 
187
+ public
188
+
95
189
  def text_width(str)
96
- gl = map_glyphs(str)
97
190
  # We *presume* that if you call text_width, you intend
98
191
  # to render the string. Maybe we shouldn't?
99
- cache_glyphs(gl)
192
+ gl = cache_glyphs(str)
100
193
  gl.inject(0) {|sum,gl|
101
194
  @glyphcache[gl].to_i + sum
102
195
  }
103
196
  end
104
197
 
105
- def map_glyphs(str)
106
- # FIXME: Should probably cache by character rather than
107
- # glyph
108
- str.to_s.each_char.map do |ch|
109
- @chcache[ch] ||= @sft.lookup(ch.ord).to_i
198
+ private
199
+ def each_font
200
+ Array(@fontset).each_index do |i|
201
+ yield load_font(i)
110
202
  end
111
203
  end
112
204
 
113
- def cache_glyphs(gl)
114
- gl.each do |gid|
115
- data = @glyphcache[gid]
116
- if !data
117
- data = cache_glyph(gid, @lm.ascender)
205
+ def cache_glyphs(str)
206
+ gl = str.to_s.each_char.map do |ch|
207
+
208
+ cache = @chcache[ch]
209
+
210
+ if cache.nil?
211
+ cache = cache_special(ch)
212
+ end
213
+
214
+ if cache.nil?
215
+ each_font do |font|
216
+ # FIXME: This is stupid and must be untangled
217
+ @sft.font = font
218
+ gid = @sft.lookup(ch.ord)
219
+ if gid
220
+ cache = @chcache[ch] = {font: font, gid: gid, gsgid: @nextgid}
221
+ @nextgid += 1
222
+ break
223
+ end
224
+ end
225
+ end
226
+
227
+ if cache
228
+ data = @glyphcache[cache[:gsgid]]
229
+ if !data
230
+ @sft.font = cache[:font]
231
+ data = cache_glyph(cache[:gsgid], cache[:gid], @lm.ascender)
232
+ end
233
+
234
+ cache[:gsgid]
235
+ else
236
+ 0
118
237
  end
119
238
  end
120
239
  end
121
-
240
+
241
+ public
122
242
  def render_str(pic, col, x,y, str)
123
243
  fill = fill_for_col(col)
124
- gl = map_glyphs(str)
125
- cache_glyphs(gl)
244
+ gl = cache_glyphs(str)
126
245
  @dpy.render_composite_glyphs32(
127
- PictOpOver, fill, pic, @gfmt,
246
+ :PictOpOver, fill, pic, @gfmt,
128
247
  @glyphset, 0,0, [x, y, gl]
129
248
  )
130
249
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Skrift
4
4
  module X11
5
- VERSION = "0.2.1"
5
+ VERSION = "0.2.2"
6
6
  end
7
7
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/skrift/x11/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "skrift-x11"
7
+ spec.version = Skrift::X11::VERSION
8
+ spec.authors = ["Vidar Hokstad"]
9
+ spec.email = ["vidar@hokstad.com"]
10
+
11
+ spec.summary = "Helpers to use the pure-Ruvy TrueType engine Skrift with pure Pure-X11 X bindings"
12
+ #spec.description = "TODO: Write a longer description or delete this line."
13
+ #spec.homepage = "TODO: Put your gem's website or public repo URL here."
14
+ spec.license = "MIT"
15
+ spec.required_ruby_version = ">= 2.6.0"
16
+
17
+ #spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
18
+
19
+ #spec.metadata["homepage_uri"] = spec.homepage
20
+ #spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo URL here."
21
+ #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
22
+
23
+ # Specify which files should be added to the gem when it is released.
24
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
25
+ spec.files = Dir.chdir(__dir__) do
26
+ `git ls-files -z`.split("\x0").reject do |f|
27
+ (File.expand_path(f) == __FILE__) ||
28
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
29
+ end
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ # Uncomment to register a new dependency of your gem
36
+ # spec.add_dependency "example-gem", "~> 1.0"
37
+ spec.add_dependency "skrift"
38
+ spec.add_dependency "pure-x11"
39
+
40
+ # For more information and examples about making a new gem, check out our
41
+ # guide at: https://bundler.io/guides/creating_gem.html
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: skrift-x11
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vidar Hokstad
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-11-12 00:00:00.000000000 Z
11
+ date: 2026-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: skrift
@@ -51,10 +51,12 @@ files:
51
51
  - example.png
52
52
  - example.rb
53
53
  - lib/skrift/x11.rb
54
+ - lib/skrift/x11/boxdrawing.rb
54
55
  - lib/skrift/x11/glyphs.rb
55
56
  - lib/skrift/x11/version.rb
56
57
  - resources/FiraGO-Regular_extended_with_NotoSansEgyptianHieroglyphs-Regular.ttf
57
58
  - sig/skrift/x11.rbs
59
+ - skrift-x11.gemspec
58
60
  homepage:
59
61
  licenses:
60
62
  - MIT