text2svg 0.2.0 → 0.3.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 +4 -4
- data/README.md +1 -1
- data/lib/text2svg.rb +0 -1
- data/lib/text2svg/typography.rb +29 -20
- data/lib/text2svg/typography_test.rb +29 -15
- data/lib/text2svg/version.rb +1 -1
- data/text2svg.gemspec +1 -1
- metadata +5 -6
- data/lib/text2svg/outline2d.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11492d4c01bc7b5f3666b2dc0b4bd4e5169c802b
|
4
|
+
data.tar.gz: 71f7d560f7de8a0780db471d7785da77d03448fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8bd0e32fe33cb34c98e07140cf124afbcd8acb9bce119d55a3c75593298daea83a7314e3cd8981ebaa1435558f9ae8a82f7470c6d7147021c9b964f7de2d761
|
7
|
+
data.tar.gz: 46de4a1e9ab9d27dc20b3e0561a07f9eb50793377b916af7b0fe80750af6f6331495ddd032f0a57196f852cf4e132459f74bd1fed5dc702408a22c38fbd27d45
|
data/README.md
CHANGED
@@ -20,7 +20,7 @@ Usage: text2svg [options]
|
|
20
20
|
--encoding ENCODING input text encoding (default utf-8)
|
21
21
|
--bold embolden outline (default false)
|
22
22
|
--italic oblique outline (default false)
|
23
|
-
--
|
23
|
+
--attribute STRING decorate options (default nil)(e.g. fill="red" stroke-width="100")
|
24
24
|
```
|
25
25
|
|
26
26
|
## Ruby API
|
data/lib/text2svg.rb
CHANGED
data/lib/text2svg/typography.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'freetype'
|
2
|
-
require 'text2svg/outline2d'
|
3
2
|
require 'text2svg/option'
|
4
3
|
|
5
4
|
module Text2svg
|
@@ -39,7 +38,7 @@ module Text2svg
|
|
39
38
|
|
40
39
|
notdef_indexes = []
|
41
40
|
unless option.font
|
42
|
-
raise OptionError, 'should
|
41
|
+
raise OptionError, 'should set `font\' option'
|
43
42
|
end
|
44
43
|
FreeType::API::Font.open(File.expand_path(option.font)) do |f|
|
45
44
|
f.set_char_size(0, 0, 3000, 3000)
|
@@ -47,14 +46,13 @@ module Text2svg
|
|
47
46
|
lines = []
|
48
47
|
line = []
|
49
48
|
lines << line
|
49
|
+
first_hori_bearing_x = []
|
50
50
|
|
51
|
-
before_char = nil
|
52
51
|
space_width = f.glyph(' '.freeze).char_width
|
53
52
|
text.each_char.with_index do |char, index|
|
54
53
|
if NEW_LINE.match char
|
55
54
|
line = []
|
56
55
|
lines << line
|
57
|
-
before_char = nil
|
58
56
|
next
|
59
57
|
end
|
60
58
|
|
@@ -66,7 +64,7 @@ module Text2svg
|
|
66
64
|
f.glyph(char)
|
67
65
|
end
|
68
66
|
|
69
|
-
if glyph.outline.tags.
|
67
|
+
if glyph.outline.tags.empty?
|
70
68
|
notdef_indexes << index
|
71
69
|
glyph = f.notdef
|
72
70
|
end
|
@@ -74,25 +72,33 @@ module Text2svg
|
|
74
72
|
glyph.bold if option.bold
|
75
73
|
glyph.italic if option.italic
|
76
74
|
|
77
|
-
width, is_draw = if IDEOGRAPHIC_SPACE.match char
|
78
|
-
[space_width * 2r, false]
|
75
|
+
hori_advance, width, is_draw = if IDEOGRAPHIC_SPACE.match char
|
76
|
+
[space_width * 2r, space_width * 2r, false]
|
79
77
|
elsif WHITESPACE.match char
|
80
|
-
[space_width, false]
|
78
|
+
[space_width, space_width, false]
|
81
79
|
else
|
82
|
-
|
80
|
+
if line.empty?
|
81
|
+
first_hori_bearing_x << glyph.metrics[:horiBearingX]
|
82
|
+
end
|
83
|
+
[glyph.metrics[:horiAdvance], glyph.metrics[:width], true]
|
83
84
|
end
|
84
|
-
|
85
|
-
line << CharSet.new(char, width, is_draw, Outline2d.new(glyph.outline).to_d)
|
85
|
+
line << CharSet.new(char, hori_advance, width, is_draw, glyph.outline.svg_path_data)
|
86
86
|
end
|
87
87
|
|
88
88
|
inter_char_space = space_width / INTER_CHAR_SPACE_DIV
|
89
|
-
|
89
|
+
|
90
|
+
width_by_line = lines.zip(first_hori_bearing_x).map do |(line, hori_bearing_x)|
|
90
91
|
before_char = nil
|
91
|
-
if
|
92
|
+
if line.empty?.!
|
92
93
|
line.map { |cs|
|
94
|
+
cs.width = if cs == line.last
|
95
|
+
[cs.width, cs.hori_advance].max
|
96
|
+
else
|
97
|
+
cs.hori_advance
|
98
|
+
end
|
93
99
|
w = cs.width + f.kerning_unfitted(before_char, cs.char).x
|
94
100
|
w.tap { before_char = cs.char }
|
95
|
-
}.inject(:+) + (line.length - 1) * inter_char_space
|
101
|
+
}.inject(:+) + (line.length - 1) * inter_char_space - [0, hori_bearing_x].min
|
96
102
|
else
|
97
103
|
0
|
98
104
|
end
|
@@ -102,8 +108,10 @@ module Text2svg
|
|
102
108
|
y = 0r
|
103
109
|
output = ''
|
104
110
|
line_height = f.line_height
|
105
|
-
|
106
|
-
|
111
|
+
|
112
|
+
output << %(<g #{option.attribute}>\n) if option.attribute
|
113
|
+
|
114
|
+
lines.zip(width_by_line, first_hori_bearing_x).each do |(line, line_width, hori_bearing_x)|
|
107
115
|
x = 0r
|
108
116
|
y += line_height
|
109
117
|
before_char = nil
|
@@ -119,12 +127,13 @@ module Text2svg
|
|
119
127
|
warn 'text_align must be left,right or center'
|
120
128
|
end
|
121
129
|
|
122
|
-
output << %!<g transform="
|
130
|
+
output << %!<g transform="matrix(1,0,0,1,0,#{y.to_i})">\n!
|
123
131
|
|
132
|
+
x -= hori_bearing_x
|
124
133
|
line.each do |cs|
|
125
134
|
x += f.kerning_unfitted(before_char, cs.char).x.to_i
|
126
135
|
if cs.draw?
|
127
|
-
output << %! <path transform="
|
136
|
+
output << %! <path transform="matrix(1,0,0,1,#{x.to_i},0)" d="#{cs.outline2d.join(' '.freeze)}"/>\n!
|
128
137
|
end
|
129
138
|
x += cs.width
|
130
139
|
x += inter_char_space if cs != line.last
|
@@ -132,7 +141,7 @@ module Text2svg
|
|
132
141
|
end
|
133
142
|
output << "</g>\n".freeze
|
134
143
|
end
|
135
|
-
output << "</g>\n".freeze
|
144
|
+
output << "</g>\n".freeze if option.attribute
|
136
145
|
|
137
146
|
option_width = 0
|
138
147
|
option_width += space_width / 1.5 if option.italic
|
@@ -142,7 +151,7 @@ module Text2svg
|
|
142
151
|
end
|
143
152
|
end
|
144
153
|
|
145
|
-
CharSet = Struct.new(:char, :width, :is_draw, :
|
154
|
+
CharSet = Struct.new(:char, :hori_advance, :width, :is_draw, :outline2d) do
|
146
155
|
def draw?
|
147
156
|
is_draw
|
148
157
|
end
|
@@ -22,23 +22,26 @@ module Text2svgTypographyTest
|
|
22
22
|
opt.text_align = text_align
|
23
23
|
[Encoding::UTF_8, Encoding::ASCII_8BIT].each do |encoding|
|
24
24
|
opt.encoding = encoding
|
25
|
-
[
|
26
|
-
opt.
|
27
|
-
[false, true].each do |
|
28
|
-
opt.
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
25
|
+
[nil, 'fill="red"'].each do |attribute|
|
26
|
+
opt.attribute = attribute
|
27
|
+
[false, true].each do |bold|
|
28
|
+
opt.bold = bold
|
29
|
+
[false, true].each do |italic|
|
30
|
+
opt.italic = italic
|
31
|
+
begin
|
32
|
+
c = Text2svg::Typography.build('A', opt)
|
33
|
+
rescue
|
34
|
+
t.log(opt)
|
35
|
+
raise
|
36
|
+
end
|
35
37
|
|
36
|
-
|
37
|
-
|
38
|
-
|
38
|
+
unless Text2svg::Content === c
|
39
|
+
t.error('return value was break')
|
40
|
+
end
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
+
unless c.data.encoding == Encoding::UTF_8
|
43
|
+
t.error('encoding was changed')
|
44
|
+
end
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
@@ -52,4 +55,15 @@ module Text2svgTypographyTest
|
|
52
55
|
t.error('return value was break')
|
53
56
|
end
|
54
57
|
end
|
58
|
+
|
59
|
+
def benchmark_build(b)
|
60
|
+
str = [*'!'..'z'].join
|
61
|
+
opt = Text2svg::Option.new('/Library/Fonts/Times New Roman.ttf')
|
62
|
+
b.reset_timer
|
63
|
+
i = 0
|
64
|
+
while i < b.n
|
65
|
+
Text2svg::Typography.build(str, opt)
|
66
|
+
i += 1
|
67
|
+
end
|
68
|
+
end
|
55
69
|
end
|
data/lib/text2svg/version.rb
CHANGED
data/text2svg.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
-
spec.add_runtime_dependency 'freetype', '>= 0.0.
|
22
|
+
spec.add_runtime_dependency 'freetype', '>= 0.0.6'
|
23
23
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
24
24
|
spec.add_development_dependency 'rake', '~> 10.0'
|
25
25
|
spec.add_development_dependency 'rgot'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: text2svg
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ksss
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-02-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: freetype
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.
|
19
|
+
version: 0.0.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.0.
|
26
|
+
version: 0.0.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,7 +88,6 @@ files:
|
|
88
88
|
- lib/text2svg/cli.rb
|
89
89
|
- lib/text2svg/cli_test.rb
|
90
90
|
- lib/text2svg/option.rb
|
91
|
-
- lib/text2svg/outline2d.rb
|
92
91
|
- lib/text2svg/typography.rb
|
93
92
|
- lib/text2svg/typography_test.rb
|
94
93
|
- lib/text2svg/version.rb
|
@@ -113,7 +112,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
112
|
version: '0'
|
114
113
|
requirements: []
|
115
114
|
rubyforge_project:
|
116
|
-
rubygems_version: 2.5.
|
115
|
+
rubygems_version: 2.5.2
|
117
116
|
signing_key:
|
118
117
|
specification_version: 4
|
119
118
|
summary: Build svg path data from font file
|
data/lib/text2svg/outline2d.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require 'freetype'
|
2
|
-
|
3
|
-
module Text2svg
|
4
|
-
class Outline2d
|
5
|
-
def initialize(outline)
|
6
|
-
@outline = outline
|
7
|
-
end
|
8
|
-
|
9
|
-
def to_d
|
10
|
-
end_ptd_of_counts = @outline.contours
|
11
|
-
contours = []
|
12
|
-
contour = []
|
13
|
-
@outline.points.each.with_index do |point, index|
|
14
|
-
contour << point
|
15
|
-
if index == end_ptd_of_counts.first
|
16
|
-
end_ptd_of_counts.shift
|
17
|
-
contours << contour
|
18
|
-
contour = []
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
path = []
|
23
|
-
contours.each do |contour|
|
24
|
-
first_pt = contour.first
|
25
|
-
last_pt = contour.last
|
26
|
-
curve_pt = nil
|
27
|
-
start = 0
|
28
|
-
if first_pt.on_curve?
|
29
|
-
curve_pt = nil
|
30
|
-
start = 1
|
31
|
-
else
|
32
|
-
if last_pt.on_curve?
|
33
|
-
first_pt = last_pt
|
34
|
-
else
|
35
|
-
first_pt = FreeType::API::Point.new(0, (first_pt.x + last_pt.x) / 2, (first_pt.y + last_pt.y) / 2)
|
36
|
-
end
|
37
|
-
curve_pt = first_pt
|
38
|
-
end
|
39
|
-
path << ['M', first_pt.x, -first_pt.y]
|
40
|
-
|
41
|
-
prev_pt = nil
|
42
|
-
(start...contour.length).each do |j|
|
43
|
-
pt = contour[j]
|
44
|
-
prev_pt = if j == 0
|
45
|
-
first_pt
|
46
|
-
else
|
47
|
-
contour[j - 1]
|
48
|
-
end
|
49
|
-
|
50
|
-
if prev_pt.on_curve? && pt.on_curve?
|
51
|
-
path << ['L', pt.x, -pt.y]
|
52
|
-
elsif prev_pt.on_curve? && !pt.on_curve?
|
53
|
-
curve_pt = pt
|
54
|
-
elsif !prev_pt.on_curve? && !pt.on_curve?
|
55
|
-
path << ['Q', prev_pt.x, -prev_pt.y, (prev_pt.x + pt.x) / 2, -((prev_pt.y + pt.y) / 2)]
|
56
|
-
curve_pt = pt
|
57
|
-
elsif !prev_pt.on_curve? && pt.on_curve?
|
58
|
-
path << ['Q', curve_pt.x, -curve_pt.y, pt.x, -pt.y]
|
59
|
-
curve_pt = nil
|
60
|
-
else
|
61
|
-
raise
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
next unless first_pt != last_pt
|
66
|
-
if curve_pt
|
67
|
-
path << ['Q', curve_pt.x, -curve_pt.y, first_pt.x, -first_pt.y]
|
68
|
-
else
|
69
|
-
path << ['L', first_pt.x, -first_pt.y]
|
70
|
-
end
|
71
|
-
end
|
72
|
-
path << ['z'] if 0 < path.length
|
73
|
-
|
74
|
-
path.map { |(command, *args)|
|
75
|
-
"#{command}#{args.join(' ')}"
|
76
|
-
}.join('')
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|