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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c9369612ae9c5bdb3a13197045796bfbbb1d9b1
4
- data.tar.gz: 774fff023b854634b8321a0f3584f7db1d09f841
3
+ metadata.gz: 11492d4c01bc7b5f3666b2dc0b4bd4e5169c802b
4
+ data.tar.gz: 71f7d560f7de8a0780db471d7785da77d03448fb
5
5
  SHA512:
6
- metadata.gz: 7035f7c09512a93ef2672916a73c769c3a54884027425e8146f491264d19b59946056e878752b01a0b4b2e0e578db2f4939f9e1fa6a7a1463d79da929e685994
7
- data.tar.gz: 81f15f3f29af0fe100dfe2958ff4c5f412807215b123d0b3700b61240300c5139d8329816cbcc22d739a9a3b9d93d226f532c09261c57f0fc7ea4ab39a0cf7a3
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
- --option STRING decorate options (default nil)(e.g. fill="red" stroke-width="100")
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
@@ -1,5 +1,4 @@
1
1
  require 'text2svg/option'
2
- require 'text2svg/outline2d'
3
2
  require 'text2svg/typography'
4
3
  require 'text2svg/version'
5
4
 
@@ -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 be set `font\' option'
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.length == 0
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
- [glyph.char_width, true]
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
- before_char = char
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
- width_by_line = lines.map do |line|
89
+
90
+ width_by_line = lines.zip(first_hori_bearing_x).map do |(line, hori_bearing_x)|
90
91
  before_char = nil
91
- if 0 < line.length
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
- output << %(<g #{option.attribute}>\n)
106
- lines.zip(width_by_line).each do |(line, line_width)|
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="translate(0,#{y.to_i})">\n!
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="translate(#{x.to_i},0)" d="#{cs.d}"/>\n!
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, :d) do
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
- [false, true].each do |bold|
26
- opt.bold = bold
27
- [false, true].each do |italic|
28
- opt.italic = italic
29
- begin
30
- c = Text2svg::Typography.build("\u{0041}", opt)
31
- rescue
32
- t.log(opt)
33
- raise
34
- end
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
- unless Text2svg::Content === c
37
- t.error('return value was break')
38
- end
38
+ unless Text2svg::Content === c
39
+ t.error('return value was break')
40
+ end
39
41
 
40
- unless c.data.encoding == Encoding::UTF_8
41
- t.error('encoding was changed')
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
@@ -1,3 +1,3 @@
1
1
  module Text2svg
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.1'
3
3
  end
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.3'
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.2.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-01-19 00:00:00.000000000 Z
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.3
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.3
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.1
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
@@ -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