text2svg 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
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