skrift-x11 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a086ab34c955c628b9b32640d98e26415a2e6766e9a784797893b6c8ef7473b0
4
+ data.tar.gz: 89a0ea4e3ee0cf221037e6c951d746c63f00140dd775f1b332cb0d7afdc52c67
5
+ SHA512:
6
+ metadata.gz: 8cf85e533b7d29eb13e993842a83a09bd3eaf7322fe41d93d5290637788d5bd944a90dd96f3f21f618edf2d03998f9667f7c403621470622fd552d72f6d039be
7
+ data.tar.gz: e07c349839802875a8d73f13a0dd2daa3beb76c12f52677f34a7a5f5bdd76aab8acdb38dc5c5c59e5612aad1ae2716ba7ffe223a86b4ca63eebae5fde1eae21d
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Vidar Hokstad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Skrift::X11
2
+
3
+ Skrift::X11 is a binding for the pure-Ruby pure-x11 gem for the pure-
4
+ Ruby [Skrift TrueType engine](https://github.com/vidarh/skrift)
5
+
6
+ It can produce output like this (see `example.rb`):
7
+
8
+ ![Example image](https://raw.githubusercontent.com/vidarh/skrift-x11/master/example.png)
9
+
10
+
11
+ ## Installation
12
+
13
+ Install the gem and add to the application's Gemfile by executing:
14
+
15
+ $ bundle add skrift-x11
16
+
17
+ If bundler is not being used to manage dependencies, install the gem by executing:
18
+
19
+ $ gem install skrift-x11
20
+
21
+ ## Usage
22
+
23
+ See `example.rb`
24
+
25
+
26
+ ## Contributing
27
+
28
+ Bug reports and pull requests are welcome on GitHub at https://github.com/vidarh/skrift-x11.
29
+
30
+ ## License
31
+
32
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
data/example.png ADDED
Binary file
data/example.rb ADDED
@@ -0,0 +1,85 @@
1
+ #require 'rubygems'
2
+ require 'skrift'
3
+ require 'X11'
4
+ require 'bundler'
5
+ require 'chunky_png'
6
+ require 'pp'
7
+
8
+ Bundler.setup(:default, :development)
9
+
10
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
11
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
12
+
13
+ require 'skrift/x11'
14
+
15
+ $dpy = dpy = display = X11::Display.new
16
+ screen = dpy.screens.first
17
+
18
+ # Transparency: Check
19
+ # https://stackoverflow.com/questions/13395179/empty-or-transparent-window-with-xlib-showing-border-lines-only/13397150#13397150
20
+
21
+ # FIXME: Hack; see XFindVisualMatch
22
+ visual = 123
23
+
24
+ cmap = $dpy.create_colormap(0, screen.root, visual)
25
+
26
+ wid = display.new_id
27
+ $dpy.create_window(
28
+ 32,
29
+ wid, screen.root,
30
+ 0, 0, # x,y
31
+ 1000, 600, # w,h
32
+ 0,
33
+ X11::Form::InputOutput,
34
+ visual, #X11::Form::CopyFromParent -- Must be provided if e.g. depth is different than root.
35
+ X11::Form::CWBackPixel | X11::Form::CWBorderPixel |
36
+ X11::Form::CWEventMask | X11::Form::CWColorMap,
37
+ [0x00000000, # ARGB background
38
+ 0x0, # Border pixel; Necessary when depth != screen.root_depth
39
+ X11::Form::SubstructureNotifyMask |
40
+ X11::Form::StructureNotifyMask | ## Move
41
+ X11::Form::ExposureMask |
42
+ X11::Form::KeyPressMask |
43
+ X11::Form::ButtonPressMask,
44
+ cmap # Colormap. Necessary when depth != screen.root_depth
45
+ ]
46
+ )
47
+
48
+ dpy.map_window(wid) # Window won't be visible until this
49
+
50
+ # A "picture" object for us to draw in the window with.
51
+ fmt = dpy.render_find_visual_format(visual)
52
+ $pic = dpy.render_create_picture(wid, fmt)
53
+
54
+ # The easy way
55
+ #$fgpic = dpy.render_create_solid_fill(0xffff,0xffff,0,0)
56
+
57
+
58
+ $gc = dpy.create_gc(wid, foreground: 0xffff0000)
59
+
60
+ puts "Main loop"
61
+
62
+ $f = Font.load("resources/FiraGO-Regular_extended_with_NotoSansEgyptianHieroglyphs-Regular.ttf")
63
+
64
+ $skrift = Skrift::X11::Glyphs.new($dpy, $f, x_scale: 40, y_scale: 40)
65
+
66
+ def redraw(dpy, wid, gc)
67
+ dpy.poly_fill_rectangle(wid, gc, [X11::Form::Rectangle.new(20,45, 400, 400)])
68
+ $skrift.render_str($pic, 0xffffff, 50,90, 'Pure Ruby w/Skrift!')
69
+ $skrift.render_str($pic, 0xffffff, 50,140, "And unicode:")
70
+ $skrift.render_str($pic, 0xff00ff, 50,200, "Μπορώ να φάω σπασμένα γυαλιά χωρίς να πάθω τίποτα.")
71
+ $skrift.render_str($pic, 0x00ffff, 50,250, "Я можу їсти шкло, й воно мені не пошкодить.")
72
+ end
73
+
74
+ loop do
75
+ pkt = display.next_packet
76
+ if pkt
77
+ #puts pkt.inspect[0..200]
78
+ #raise "Error" if pkt.is_a?(X11::Form::Error)
79
+ redraw(display, wid, $gc) if pkt.is_a?(X11::Form::Expose)
80
+
81
+ if pkt.is_a?(X11::Form::KeyPress)
82
+ # lookup_keysym(dpy,pkt)
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,129 @@
1
+
2
+ require 'skrift'
3
+ module Skrift
4
+ module X11
5
+ # XRender constants currently not defined in pure-x11.
6
+ # FIXME.
7
+ PictOpSrc=1
8
+ PictOpOver=3
9
+ CPRepeat = 1
10
+
11
+ class Glyphs
12
+
13
+ def initialize dpy, font, x_scale:, y_scale:, pic: nil, fixed: nil
14
+ @dpy = dpy
15
+ @sft = SFT.new(font)
16
+ @sft.x_scale = x_scale
17
+ @sft.y_scale = y_scale
18
+ @pic = pic
19
+ @fixed = fixed
20
+
21
+ @glyphcache = {}
22
+ @colcache = {}
23
+
24
+ @lm = @sft.lmetrics
25
+
26
+ # The glyph set
27
+ @gfmt = @dpy.render_find_standard_format(:a8).id
28
+ @glyphset = @dpy.render_create_glyph_set(@gfmt)
29
+ end
30
+
31
+ attr_accessor :lm
32
+ def gm(ch)
33
+ gid = @sft.lookup(ch.ord)
34
+ @sft.gmetrics(gid)
35
+ end
36
+
37
+
38
+ def fill_for_col(col)
39
+ return @colcache[col] if @colcache[col]
40
+ r = col >> 16
41
+ r |= r << 8
42
+ g = (col >> 8) & 0xff
43
+ g |= g << 8
44
+ b = col & 0xff
45
+ b |= b << 8
46
+
47
+ @colcache[col] ||= @dpy.render_create_solid_fill(r,g,b,0xffff)
48
+ end
49
+
50
+ def fixed_width
51
+ return @fixed_width if @fixed_width
52
+ if @fixed
53
+ # *Ensure* that the glyphs are equal width.
54
+ g = gm("M")
55
+ @fixed_width = g.advance_width.ceil
56
+ else
57
+ nil
58
+ end
59
+ end
60
+
61
+
62
+ def cache_glyph(gid, baseline)
63
+ mtx = @sft.gmetrics(gid)
64
+
65
+ # FIXME: Not sure what to do if mtx.nil? here.
66
+ # Maybe use x/y scale?
67
+ w = fixed_width || mtx.min_width || 0
68
+ h = mtx.min_height || 1
69
+ #p [w,h]
70
+ img = Image.new((w+3)&~3, h)
71
+ if !@sft.render(gid, img)
72
+ #STDERR.puts "Unable to render #{gid}\n"
73
+ data = "\0"*(w*h)
74
+ else
75
+ data = img.pixels.pack("C*")
76
+ end
77
+
78
+ yoff = mtx.y_offset || baseline
79
+
80
+ info = ::X11::Form::GlyphInfo.new(
81
+ img.width, # w
82
+ img.height, # h
83
+ -mtx.left_side_bearing, # x
84
+ yoff-baseline, # y
85
+ fixed_width || mtx.advance_width, # || mtx.advance_width, # x_off
86
+ 0
87
+ )
88
+
89
+ @dpy.render_add_glyphs(@glyphset, gid, info, data)
90
+ @glyphcache[gid] = mtx.advance_width#-mtx.left_side_bearing
91
+ end
92
+
93
+ def text_width(str)
94
+ gl = map_glyphs(str)
95
+ # We *presume* that if you call text_width, you intend
96
+ # to render the string. Maybe we shouldn't?
97
+ cache_glyphs(gl)
98
+ gl.inject(0) {|sum,gl|
99
+ @glyphcache[gl].to_i + sum
100
+ }
101
+ end
102
+
103
+ def map_glyphs(str)
104
+ # FIXME: Should probably cache by character rather than
105
+ # glyph
106
+ str.to_s.each_char.map { |ch| @sft.lookup(ch.ord) }
107
+ end
108
+
109
+ def cache_glyphs(gl)
110
+ gl.each do |gid|
111
+ data = @glyphcache[gid]
112
+ if !data
113
+ data = cache_glyph(gid, @lm.ascender)
114
+ end
115
+ end
116
+ end
117
+
118
+ def render_str(pic, col, x,y, str)
119
+ fill = fill_for_col(col)
120
+ gl = map_glyphs(str)
121
+ cache_glyphs(gl)
122
+ @dpy.render_composite_glyphs32(
123
+ PictOpOver, fill, pic, @gfmt,
124
+ @glyphset, 0,0, [x, y, gl]
125
+ )
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Skrift
4
+ module X11
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
data/lib/skrift/x11.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "x11/version"
4
+ require_relative "x11/glyphs"
5
+
6
+ module Skrift
7
+ module X11
8
+ class Error < StandardError; end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module Skrift
2
+ module X11
3
+ VERSION: String
4
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: skrift-x11
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Vidar Hokstad
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-09-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: skrift
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: pure-x11
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description:
42
+ email:
43
+ - vidar@hokstad.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE.txt
49
+ - README.md
50
+ - Rakefile
51
+ - example.png
52
+ - example.rb
53
+ - lib/skrift/x11.rb
54
+ - lib/skrift/x11/glyphs.rb
55
+ - lib/skrift/x11/version.rb
56
+ - resources/FiraGO-Regular_extended_with_NotoSansEgyptianHieroglyphs-Regular.ttf
57
+ - sig/skrift/x11.rbs
58
+ homepage:
59
+ licenses:
60
+ - MIT
61
+ metadata: {}
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 2.6.0
71
+ required_rubygems_version: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ requirements: []
77
+ rubygems_version: 3.4.10
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Helpers to use the pure-Ruvy TrueType engine Skrift with pure Pure-X11 X
81
+ bindings
82
+ test_files: []