rays 0.1.47 → 0.1.49
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.doc/ext/rays/bitmap.cpp +287 -46
- data/.doc/ext/rays/camera.cpp +2 -2
- data/.doc/ext/rays/color.cpp +11 -0
- data/.doc/ext/rays/defs.cpp +32 -8
- data/.doc/ext/rays/font.cpp +50 -2
- data/.doc/ext/rays/image.cpp +3 -3
- data/.doc/ext/rays/matrix.cpp +65 -7
- data/.doc/ext/rays/native.cpp +2 -4
- data/.doc/ext/rays/painter.cpp +117 -9
- data/.doc/ext/rays/point.cpp +1 -11
- data/.doc/ext/rays/polygon.cpp +133 -97
- data/.doc/ext/rays/polyline.cpp +89 -10
- data/.doc/ext/rays/rays.cpp +80 -0
- data/.doc/ext/rays/{noise.cpp → util.cpp} +2 -2
- data/ChangeLog.md +46 -0
- data/VERSION +1 -1
- data/ext/rays/bitmap.cpp +288 -46
- data/ext/rays/camera.cpp +2 -2
- data/ext/rays/color.cpp +13 -1
- data/ext/rays/defs.cpp +32 -8
- data/ext/rays/defs.h +56 -3
- data/ext/rays/font.cpp +56 -4
- data/ext/rays/image.cpp +3 -3
- data/ext/rays/matrix.cpp +69 -7
- data/ext/rays/native.cpp +2 -4
- data/ext/rays/painter.cpp +132 -13
- data/ext/rays/point.cpp +1 -12
- data/ext/rays/polygon.cpp +136 -99
- data/ext/rays/polyline.cpp +95 -9
- data/ext/rays/rays.cpp +80 -0
- data/ext/rays/{noise.cpp → util.cpp} +2 -2
- data/include/rays/color.h +3 -1
- data/include/rays/defs.h +24 -26
- data/include/rays/font.h +17 -3
- data/include/rays/image.h +1 -1
- data/include/rays/matrix.h +24 -0
- data/include/rays/painter.h +24 -0
- data/include/rays/polygon.h +68 -43
- data/include/rays/polyline.h +17 -2
- data/include/rays/ruby/polygon.h +0 -11
- data/include/rays/ruby/rays.h +4 -0
- data/include/rays/{noise.h → util.h} +2 -2
- data/lib/rays/color.rb +7 -1
- data/lib/rays/font.rb +1 -1
- data/lib/rays/image.rb +11 -1
- data/lib/rays/matrix.rb +16 -0
- data/lib/rays/painter.rb +18 -7
- data/lib/rays/point.rb +5 -1
- data/lib/rays/polygon.rb +44 -35
- data/lib/rays/polyline.rb +54 -8
- data/lib/rays.rb +0 -1
- data/rays.gemspec +2 -2
- data/src/color.cpp +11 -2
- data/src/font.cpp +37 -18
- data/src/font.h +6 -5
- data/src/image.cpp +58 -14
- data/src/ios/font.mm +89 -32
- data/src/ios/helper.h +2 -2
- data/src/ios/helper.mm +2 -2
- data/src/matrix.cpp +45 -0
- data/src/osx/font.mm +93 -33
- data/src/osx/helper.h +2 -2
- data/src/osx/helper.mm +2 -2
- data/src/painter.cpp +246 -114
- data/src/painter.h +11 -3
- data/src/polygon.cpp +431 -332
- data/src/polyline.cpp +138 -27
- data/src/polyline.h +3 -5
- data/src/shader.cpp +36 -4
- data/src/shader.h +1 -1
- data/src/texture.cpp +23 -4
- data/src/texture.h +2 -0
- data/src/{noise.cpp → util.cpp} +1 -1
- data/src/win32/font.cpp +1 -1
- data/test/test_bitmap.rb +12 -5
- data/test/test_color.rb +25 -4
- data/test/test_font.rb +23 -2
- data/test/test_image.rb +44 -18
- data/test/test_matrix.rb +22 -0
- data/test/test_painter.rb +27 -0
- data/test/test_point.rb +1 -1
- data/test/test_polygon.rb +52 -45
- data/test/test_polyline.rb +191 -72
- metadata +12 -18
- data/.doc/ext/rays/polygon_line.cpp +0 -97
- data/ext/rays/polygon_line.cpp +0 -100
- data/lib/rays/polygon_line.rb +0 -33
- data/test/test_polygon_line.rb +0 -164
data/lib/rays/polygon.rb
CHANGED
@@ -8,74 +8,83 @@ module Rays
|
|
8
8
|
class Polygon
|
9
9
|
|
10
10
|
include Enumerable
|
11
|
+
include Comparable
|
11
12
|
|
12
|
-
def initialize(*args, loop: true)
|
13
|
-
setup args, loop
|
13
|
+
def initialize(*args, loop: true, colors: nil, texcoords: nil)
|
14
|
+
setup args, loop, colors, texcoords
|
14
15
|
end
|
15
16
|
|
16
|
-
def transform(
|
17
|
-
|
18
|
-
|
19
|
-
lines = block.call lines if block
|
20
|
-
self.class.new(*lines)
|
17
|
+
def transform(&block)
|
18
|
+
polylines = block.call to_a
|
19
|
+
self.class.new(*polylines)
|
21
20
|
end
|
22
21
|
|
23
22
|
def intersects(obj)
|
24
23
|
!(self & obj).empty?
|
25
24
|
end
|
26
25
|
|
27
|
-
def
|
28
|
-
|
26
|
+
def <=>(o)
|
27
|
+
(size <=> o.size).then {|cmp| return cmp if cmp != 0}
|
28
|
+
to_a.zip(o.to_a).each {|a, b| cmp = a <=> b; return cmp if cmp != 0}
|
29
|
+
0
|
29
30
|
end
|
30
31
|
|
31
|
-
def
|
32
|
-
|
32
|
+
def inspect()
|
33
|
+
"#<Rays::Polygon [#{map {|polyline| polyline.inspect}.join ', '}]>"
|
33
34
|
end
|
34
35
|
|
35
|
-
def self.
|
36
|
-
|
36
|
+
def self.points(*points)
|
37
|
+
points! points
|
37
38
|
end
|
38
39
|
|
39
|
-
def self.
|
40
|
-
|
41
|
-
|
40
|
+
def self.line(*points, loop: false)
|
41
|
+
line! points, loop
|
42
|
+
end
|
42
43
|
|
43
|
-
|
44
|
+
def self.lines(*points)
|
45
|
+
lines! points
|
44
46
|
end
|
45
47
|
|
46
|
-
def self.
|
47
|
-
|
48
|
-
|
48
|
+
def self.triangles(*points, loop: true, colors: nil, texcoords: nil)
|
49
|
+
triangles! points, loop, colors, texcoords
|
50
|
+
end
|
49
51
|
|
50
|
-
|
52
|
+
def self.triangle_strip(*points, colors: nil, texcoords: nil)
|
53
|
+
triangle_strip! points, colors, texcoords
|
51
54
|
end
|
52
55
|
|
53
|
-
def self.
|
54
|
-
|
56
|
+
def self.triangle_fan(*points, colors: nil, texcoords: nil)
|
57
|
+
triangle_fan! points, colors, texcoords
|
55
58
|
end
|
56
59
|
|
57
|
-
def self.
|
58
|
-
|
60
|
+
def self.rect(
|
61
|
+
*args, round: nil, lt: nil, rt: nil, lb: nil, rb: nil,
|
62
|
+
nsegment: nil)
|
63
|
+
|
64
|
+
rect! args, round, lt, rt, lb, rb, nsegment
|
59
65
|
end
|
60
66
|
|
61
|
-
def self.
|
62
|
-
|
67
|
+
def self.quads(*points, loop: true, colors: nil, texcoords: nil)
|
68
|
+
quads! points, loop, colors, texcoords
|
63
69
|
end
|
64
70
|
|
65
|
-
def self.
|
66
|
-
|
71
|
+
def self.quad_strip(*points, colors: nil, texcoords: nil)
|
72
|
+
quad_strip! points, colors, texcoords
|
67
73
|
end
|
68
74
|
|
69
|
-
def self.
|
70
|
-
|
75
|
+
def self.ellipse(
|
76
|
+
*args, center: nil, radius: nil, hole: nil, from: nil, to: nil,
|
77
|
+
nsegment: nil)
|
78
|
+
|
79
|
+
ellipse! args, center, radius, hole, from, to, nsegment
|
71
80
|
end
|
72
81
|
|
73
|
-
def self.curve(*
|
74
|
-
curve!
|
82
|
+
def self.curve(*points, loop: false, nsegment: nil)
|
83
|
+
curve! points, loop, nsegment
|
75
84
|
end
|
76
85
|
|
77
|
-
def self.bezier(*
|
78
|
-
bezier!
|
86
|
+
def self.bezier(*points, loop: false, nsegment: nil)
|
87
|
+
bezier! points, loop, nsegment
|
79
88
|
end
|
80
89
|
|
81
90
|
end# Polygon
|
data/lib/rays/polyline.rb
CHANGED
@@ -7,20 +7,66 @@ module Rays
|
|
7
7
|
class Polyline
|
8
8
|
|
9
9
|
include Enumerable
|
10
|
+
include Comparable
|
10
11
|
|
11
|
-
def initialize(
|
12
|
-
|
12
|
+
def initialize(
|
13
|
+
*points, loop: false, fill: nil, colors: nil, texcoords: nil, hole: false)
|
14
|
+
|
15
|
+
setup points, loop, (fill != nil ? fill : loop), colors, texcoords, hole
|
16
|
+
end
|
17
|
+
|
18
|
+
def with(**kwargs)
|
19
|
+
points_, loop_, fill_, colors_, texcoords_, hole_ =
|
20
|
+
kwargs.values_at :points, :loop, :fill, :colors, :texcoords, :hole
|
21
|
+
self.class.new(
|
22
|
+
*(points_ || (points? ? points : [])),
|
23
|
+
loop: loop_ != nil ? loop_ : loop?,
|
24
|
+
fill: fill_ != nil ? fill_ : fill?,
|
25
|
+
colors: colors_ || (colors? ? colors : nil),
|
26
|
+
texcoords: texcoords_ || (texcoords? ? texcoords : nil),
|
27
|
+
hole: hole_ != nil ? hole_ : hole?)
|
28
|
+
end
|
29
|
+
|
30
|
+
def points()
|
31
|
+
each_point.to_a
|
32
|
+
end
|
33
|
+
|
34
|
+
def colors()
|
35
|
+
each_color.to_a
|
36
|
+
end
|
37
|
+
|
38
|
+
def texcoords()
|
39
|
+
each_texcoord.to_a
|
40
|
+
end
|
41
|
+
|
42
|
+
def each_point(&block)
|
43
|
+
block ? each_point!(&block) : enum_for(:each_point!)
|
44
|
+
end
|
45
|
+
|
46
|
+
def each_color(&block)
|
47
|
+
block ? each_color!(&block) : enum_for(:each_color!)
|
48
|
+
end
|
49
|
+
|
50
|
+
def each_texcoord(&block)
|
51
|
+
block ? each_texcoord!(&block) : enum_for(:each_texcoord!)
|
13
52
|
end
|
14
53
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
54
|
+
alias each each_point
|
55
|
+
|
56
|
+
def <=>(o)
|
57
|
+
(size <=> o.size) .then {|cmp| return cmp if cmp != 0}
|
58
|
+
(loop? <=> o.loop?).then {|cmp| return cmp if cmp != 0}
|
59
|
+
(fill? <=> o.fill?).then {|cmp| return cmp if cmp != 0}
|
60
|
+
points .zip(o.points) .each {|a, b| cmp = a <=> b; return cmp if cmp != 0}
|
61
|
+
colors .zip(o.colors) .each {|a, b| cmp = a <=> b; return cmp if cmp != 0}
|
62
|
+
texcoords.zip(o.texcoords).each {|a, b| cmp = a <=> b; return cmp if cmp != 0}
|
63
|
+
0
|
20
64
|
end
|
21
65
|
|
22
66
|
def inspect()
|
23
|
-
|
67
|
+
p = points.map {|o| o.to_a.join ','}.join ', '
|
68
|
+
c, t = colors.size, texcoords.size
|
69
|
+
"#<Rays::Polyline [#{p}] loop:#{loop?} fill:#{fill?} hole:#{hole?} colors:#{c} texcoords:#{t}>"
|
24
70
|
end
|
25
71
|
|
26
72
|
end# Polyline
|
data/lib/rays.rb
CHANGED
data/rays.gemspec
CHANGED
@@ -25,8 +25,8 @@ Gem::Specification.new do |s|
|
|
25
25
|
s.platform = Gem::Platform::RUBY
|
26
26
|
s.required_ruby_version = '>= 3.0.0'
|
27
27
|
|
28
|
-
s.add_runtime_dependency 'xot', '~> 0.1.
|
29
|
-
s.add_runtime_dependency 'rucy', '~> 0.1.
|
28
|
+
s.add_runtime_dependency 'xot', '~> 0.1.42'
|
29
|
+
s.add_runtime_dependency 'rucy', '~> 0.1.44'
|
30
30
|
|
31
31
|
s.files = `git ls-files`.split $/
|
32
32
|
s.executables = s.files.grep(%r{^bin/}) {|f| File.basename f}
|
data/src/color.cpp
CHANGED
@@ -47,8 +47,17 @@ namespace Rays
|
|
47
47
|
hue = fmod(hue, 1.f);
|
48
48
|
if (hue < 0) hue += 1.f;
|
49
49
|
|
50
|
-
auto
|
51
|
-
return Color(
|
50
|
+
auto rgb = glm::rgbColor(Vec3(hue * 360.f, saturation, value));
|
51
|
+
return Color(rgb[0], rgb[1], rgb[2], alpha);
|
52
|
+
}
|
53
|
+
|
54
|
+
void
|
55
|
+
get_hsv (float* hue, float* saturation, float* value, const Color& color)
|
56
|
+
{
|
57
|
+
auto hsv = glm::hsvColor(Vec3(color.r, color.g, color.b));
|
58
|
+
if (hue) *hue = hsv[0] / 360.f;
|
59
|
+
if (saturation) *saturation = hsv[1];
|
60
|
+
if (value) *value = hsv[2];
|
52
61
|
}
|
53
62
|
|
54
63
|
|
data/src/font.cpp
CHANGED
@@ -27,7 +27,7 @@ namespace Rays
|
|
27
27
|
if (pixel_density != for_pixel_density)
|
28
28
|
{
|
29
29
|
rawfont_for_pixel_density =
|
30
|
-
RawFont(rawfont
|
30
|
+
RawFont(rawfont, rawfont.size() * pixel_density);
|
31
31
|
for_pixel_density = pixel_density;
|
32
32
|
}
|
33
33
|
|
@@ -37,8 +37,16 @@ namespace Rays
|
|
37
37
|
};// Font::Data
|
38
38
|
|
39
39
|
|
40
|
+
Font
|
41
|
+
load_font (const char* path, coord size)
|
42
|
+
{
|
43
|
+
Font font;
|
44
|
+
font.self->rawfont = RawFont_load(path, size);
|
45
|
+
return font;
|
46
|
+
}
|
47
|
+
|
40
48
|
const Font&
|
41
|
-
|
49
|
+
get_default_font ()
|
42
50
|
{
|
43
51
|
static const Font FONT(NULL);
|
44
52
|
return FONT;
|
@@ -50,21 +58,6 @@ namespace Rays
|
|
50
58
|
return font.self->get_raw(pixel_density);
|
51
59
|
}
|
52
60
|
|
53
|
-
coord
|
54
|
-
Font_get_width (const Font& font, float pixel_density, const char* str)
|
55
|
-
{
|
56
|
-
return Font_get_raw(font, pixel_density).get_width(str);
|
57
|
-
}
|
58
|
-
|
59
|
-
coord
|
60
|
-
Font_get_height (
|
61
|
-
const Font& font, float pixel_density,
|
62
|
-
coord* ascent, coord* descent, coord* leading)
|
63
|
-
{
|
64
|
-
return Font_get_raw(font, pixel_density)
|
65
|
-
.get_height(ascent, descent, leading);
|
66
|
-
}
|
67
|
-
|
68
61
|
|
69
62
|
Font::Font ()
|
70
63
|
{
|
@@ -79,12 +72,26 @@ namespace Rays
|
|
79
72
|
{
|
80
73
|
}
|
81
74
|
|
75
|
+
Font
|
76
|
+
Font::dup () const
|
77
|
+
{
|
78
|
+
Font f;
|
79
|
+
f.self->rawfont = RawFont(self->rawfont, self->rawfont.size());
|
80
|
+
return f;
|
81
|
+
}
|
82
|
+
|
82
83
|
String
|
83
84
|
Font::name () const
|
84
85
|
{
|
85
86
|
return self->rawfont.name();
|
86
87
|
}
|
87
88
|
|
89
|
+
void
|
90
|
+
Font::set_size (coord size)
|
91
|
+
{
|
92
|
+
self->rawfont = RawFont(self->rawfont, size);
|
93
|
+
}
|
94
|
+
|
88
95
|
coord
|
89
96
|
Font::size () const
|
90
97
|
{
|
@@ -94,7 +101,19 @@ namespace Rays
|
|
94
101
|
coord
|
95
102
|
Font::get_width (const char* str) const
|
96
103
|
{
|
97
|
-
|
104
|
+
if (!strchr(str, '\n'))
|
105
|
+
return self->rawfont.get_width(str);
|
106
|
+
|
107
|
+
Xot::StringList lines;
|
108
|
+
split(&lines, str);
|
109
|
+
|
110
|
+
coord width = 0;
|
111
|
+
for (const auto& line : lines)
|
112
|
+
{
|
113
|
+
coord w = self->rawfont.get_width(line.c_str());
|
114
|
+
if (w > width) width = w;
|
115
|
+
}
|
116
|
+
return width;
|
98
117
|
}
|
99
118
|
|
100
119
|
coord
|
data/src/font.h
CHANGED
@@ -15,11 +15,15 @@ namespace Rays
|
|
15
15
|
class RawFont
|
16
16
|
{
|
17
17
|
|
18
|
+
typedef RawFont This;
|
19
|
+
|
18
20
|
public:
|
19
21
|
|
20
22
|
RawFont ();
|
21
23
|
|
22
|
-
RawFont (const char* name, coord size
|
24
|
+
RawFont (const char* name, coord size);
|
25
|
+
|
26
|
+
RawFont (const This& obj, coord size);
|
23
27
|
|
24
28
|
~RawFont ();
|
25
29
|
|
@@ -51,11 +55,8 @@ namespace Rays
|
|
51
55
|
|
52
56
|
const RawFont& Font_get_raw (const Font& font, float pixel_density);
|
53
57
|
|
54
|
-
coord Font_get_width (const Font& font, float pixel_density, const char* str);
|
55
58
|
|
56
|
-
|
57
|
-
const Font& font, float pixel_density,
|
58
|
-
coord* ascent = NULL, coord* descent = NULL, coord* leading = NULL);
|
59
|
+
RawFont RawFont_load (const char* path, coord size);
|
59
60
|
|
60
61
|
|
61
62
|
}// Rays
|
data/src/image.cpp
CHANGED
@@ -10,6 +10,13 @@
|
|
10
10
|
#include "texture.h"
|
11
11
|
|
12
12
|
|
13
|
+
#if 0
|
14
|
+
#define PRINT_MODIFIED_FLAGS(message) self->print_modified_flags(message)
|
15
|
+
#else
|
16
|
+
#define PRINT_MODIFIED_FLAGS(message)
|
17
|
+
#endif
|
18
|
+
|
19
|
+
|
13
20
|
namespace Rays
|
14
21
|
{
|
15
22
|
|
@@ -27,6 +34,16 @@ namespace Rays
|
|
27
34
|
|
28
35
|
mutable Texture texture;
|
29
36
|
|
37
|
+
void print_modified_flags (const char* message)
|
38
|
+
{
|
39
|
+
printf("%s: %d %d %d %d \n",
|
40
|
+
message,
|
41
|
+
bitmap ? 1 : 0,
|
42
|
+
Bitmap_get_modified(bitmap) ? 1 : 0,
|
43
|
+
texture ? 1 : 0,
|
44
|
+
texture.modified() ? 1 : 0);
|
45
|
+
}
|
46
|
+
|
30
47
|
};// Image::Data
|
31
48
|
|
32
49
|
|
@@ -82,18 +99,30 @@ namespace Rays
|
|
82
99
|
if (!self->bitmap)
|
83
100
|
{
|
84
101
|
if (self->texture)
|
102
|
+
{
|
103
|
+
PRINT_MODIFIED_FLAGS("new bitmap from texture");
|
85
104
|
self->bitmap = Bitmap_from(self->texture);
|
105
|
+
}
|
86
106
|
else
|
107
|
+
{
|
108
|
+
PRINT_MODIFIED_FLAGS("new bitmap");
|
87
109
|
self->bitmap = Bitmap(self->width, self->height, self->color_space);
|
110
|
+
}
|
88
111
|
clear_modified_flags(image);
|
89
112
|
}
|
90
|
-
else if (
|
91
|
-
self->texture &&
|
92
|
-
self->texture.modified() &&
|
93
|
-
!Bitmap_get_modified(self->bitmap))
|
113
|
+
else if (self->texture && self->texture.modified())
|
94
114
|
{
|
95
|
-
|
96
|
-
|
115
|
+
if (Bitmap_get_modified(self->bitmap))
|
116
|
+
{
|
117
|
+
invalid_state_error(
|
118
|
+
__FILE__, __LINE__, "bitmap and texture modifications conflicted");
|
119
|
+
}
|
120
|
+
else
|
121
|
+
{
|
122
|
+
PRINT_MODIFIED_FLAGS("bitmap from texture");
|
123
|
+
self->bitmap = Bitmap_from(self->texture);
|
124
|
+
clear_modified_flags(image);
|
125
|
+
}
|
97
126
|
}
|
98
127
|
|
99
128
|
return self->bitmap;
|
@@ -115,9 +144,13 @@ namespace Rays
|
|
115
144
|
if (!self->texture)
|
116
145
|
{
|
117
146
|
if (self->bitmap)
|
147
|
+
{
|
148
|
+
PRINT_MODIFIED_FLAGS("new texture from bitmap");
|
118
149
|
self->texture = Texture(self->bitmap);
|
150
|
+
}
|
119
151
|
else
|
120
152
|
{
|
153
|
+
PRINT_MODIFIED_FLAGS("new texture");
|
121
154
|
self->texture = Texture(self->width, self->height, self->color_space);
|
122
155
|
|
123
156
|
Painter p = image.painter();
|
@@ -127,13 +160,19 @@ namespace Rays
|
|
127
160
|
}
|
128
161
|
clear_modified_flags(&image);
|
129
162
|
}
|
130
|
-
else if (
|
131
|
-
self->bitmap &&
|
132
|
-
Bitmap_get_modified(self->bitmap) &&
|
133
|
-
!self->texture.modified())
|
163
|
+
else if (self->bitmap && Bitmap_get_modified(self->bitmap))
|
134
164
|
{
|
135
|
-
self->texture
|
136
|
-
|
165
|
+
if (self->texture.modified())
|
166
|
+
{
|
167
|
+
invalid_state_error(
|
168
|
+
__FILE__, __LINE__, "texture and bitmap modifications conflicted");
|
169
|
+
}
|
170
|
+
else
|
171
|
+
{
|
172
|
+
PRINT_MODIFIED_FLAGS("texture from bitmap");
|
173
|
+
self->texture = self->bitmap;
|
174
|
+
clear_modified_flags(&image);
|
175
|
+
}
|
137
176
|
}
|
138
177
|
|
139
178
|
return self->texture;
|
@@ -232,15 +271,20 @@ namespace Rays
|
|
232
271
|
}
|
233
272
|
|
234
273
|
Bitmap&
|
235
|
-
Image::bitmap ()
|
274
|
+
Image::bitmap (bool modify)
|
236
275
|
{
|
276
|
+
if (modify)
|
277
|
+
{
|
278
|
+
if (!self->bitmap) get_bitmap(this);
|
279
|
+
Bitmap_set_modified(&self->bitmap);
|
280
|
+
}
|
237
281
|
return get_bitmap(this);
|
238
282
|
}
|
239
283
|
|
240
284
|
const Bitmap&
|
241
285
|
Image::bitmap () const
|
242
286
|
{
|
243
|
-
return
|
287
|
+
return const_cast<Image*>(this)->bitmap();
|
244
288
|
}
|
245
289
|
|
246
290
|
Image::operator bool () const
|
data/src/ios/font.mm
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
#include "../font.h"
|
3
3
|
|
4
4
|
|
5
|
+
#include <memory>
|
5
6
|
#import <CoreGraphics/CGContext.h>
|
6
7
|
#import <CoreText/CoreText.h>
|
7
8
|
#include "rays/exception.h"
|
@@ -12,15 +13,23 @@ namespace Rays
|
|
12
13
|
{
|
13
14
|
|
14
15
|
|
16
|
+
typedef std::shared_ptr<const __CFDictionary> CFDictionaryPtr;
|
17
|
+
|
18
|
+
typedef std::shared_ptr<const __CFAttributedString> CFAttributedStringPtr;
|
19
|
+
|
20
|
+
typedef std::shared_ptr<CGDataProvider> CGDataProviderPtr;
|
21
|
+
|
22
|
+
typedef std::shared_ptr<CGFont> CGFontPtr;
|
23
|
+
|
24
|
+
typedef std::shared_ptr<const __CTLine> CTLinePtr;
|
25
|
+
|
26
|
+
|
15
27
|
struct RawFont::Data
|
16
28
|
{
|
17
29
|
|
18
|
-
CTFontRef font;
|
30
|
+
CTFontRef font = NULL;
|
19
31
|
|
20
|
-
|
21
|
-
: font(NULL)
|
22
|
-
{
|
23
|
-
}
|
32
|
+
String path;
|
24
33
|
|
25
34
|
~Data ()
|
26
35
|
{
|
@@ -34,7 +43,7 @@ namespace Rays
|
|
34
43
|
};// RawFont::Data
|
35
44
|
|
36
45
|
|
37
|
-
static
|
46
|
+
static CTLinePtr
|
38
47
|
make_line (CTFontRef font, const char* str)
|
39
48
|
{
|
40
49
|
if (!font || !str || *str == '\0')
|
@@ -50,18 +59,65 @@ namespace Rays
|
|
50
59
|
};
|
51
60
|
size_t nkeys = sizeof(keys) / sizeof(keys[0]);
|
52
61
|
|
53
|
-
|
54
|
-
|
55
|
-
|
62
|
+
CFDictionaryPtr attr(
|
63
|
+
CFDictionaryCreate(
|
64
|
+
NULL, (const void**) &keys, (const void**) &values, nkeys,
|
65
|
+
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks),
|
66
|
+
CFRelease);
|
56
67
|
|
57
|
-
|
58
|
-
NULL, cfstring(str).get(), attr)
|
59
|
-
|
68
|
+
CFAttributedStringPtr attrstr(
|
69
|
+
CFAttributedStringCreate(NULL, cfstring(str).get(), attr.get()),
|
70
|
+
CFRelease);
|
60
71
|
|
61
|
-
|
62
|
-
|
72
|
+
return CTLinePtr(
|
73
|
+
CTLineCreateWithAttributedString(attrstr.get()),
|
74
|
+
CFRelease);
|
75
|
+
}
|
63
76
|
|
64
|
-
|
77
|
+
const FontFamilyMap&
|
78
|
+
get_font_families ()
|
79
|
+
{
|
80
|
+
static const FontFamilyMap MAP = []() {
|
81
|
+
FontFamilyMap map;
|
82
|
+
for (NSString* family in UIFont.familyNames)
|
83
|
+
{
|
84
|
+
FontFamilyMap::mapped_type array;
|
85
|
+
for (NSString* name in [UIFont fontNamesForFamilyName: family])
|
86
|
+
array.emplace_back(name.UTF8String);
|
87
|
+
map[family.UTF8String] = array;
|
88
|
+
}
|
89
|
+
return map;
|
90
|
+
}();
|
91
|
+
return MAP;
|
92
|
+
}
|
93
|
+
|
94
|
+
RawFont
|
95
|
+
RawFont_load (const char* path, coord size)
|
96
|
+
{
|
97
|
+
if (!path)
|
98
|
+
argument_error(__FILE__, __LINE__);
|
99
|
+
|
100
|
+
CGDataProviderPtr data_provider(
|
101
|
+
CGDataProviderCreateWithFilename(path),
|
102
|
+
CGDataProviderRelease);
|
103
|
+
if (!data_provider)
|
104
|
+
rays_error(__FILE__, __LINE__, "failed to create CGDataProvider");
|
105
|
+
|
106
|
+
CGFontPtr cgfont(
|
107
|
+
CGFontCreateWithDataProvider(data_provider.get()),
|
108
|
+
CGFontRelease);
|
109
|
+
if (!cgfont)
|
110
|
+
rays_error(__FILE__, __LINE__, "failed to create CGFont");
|
111
|
+
|
112
|
+
CTFontRef ctfont = CTFontCreateWithGraphicsFont(
|
113
|
+
cgfont.get(), size, NULL, NULL);
|
114
|
+
if (!ctfont)
|
115
|
+
rays_error(__FILE__, __LINE__, "failed to create CTFont");
|
116
|
+
|
117
|
+
RawFont rawfont;
|
118
|
+
rawfont.self->font = ctfont;
|
119
|
+
rawfont.self->path = path;
|
120
|
+
return rawfont;
|
65
121
|
}
|
66
122
|
|
67
123
|
|
@@ -76,6 +132,15 @@ namespace Rays
|
|
76
132
|
: CTFontCreateUIFontForLanguage(kCTFontSystemFontType, size, NULL);
|
77
133
|
}
|
78
134
|
|
135
|
+
RawFont::RawFont (const This& obj, coord size)
|
136
|
+
{
|
137
|
+
const char* path = obj.self->path.empty() ? NULL : obj.self->path.c_str();
|
138
|
+
if (path)
|
139
|
+
*this = RawFont_load(path, size);
|
140
|
+
else
|
141
|
+
self->font = CTFontCreateWithName(cfstring(obj.name()).get(), size, NULL);
|
142
|
+
}
|
143
|
+
|
79
144
|
RawFont::~RawFont ()
|
80
145
|
{
|
81
146
|
}
|
@@ -92,15 +157,13 @@ namespace Rays
|
|
92
157
|
|
93
158
|
if (*str == '\0') return;
|
94
159
|
|
95
|
-
|
160
|
+
CTLinePtr line = make_line(self->font, str);
|
96
161
|
if (!line)
|
97
162
|
rays_error(__FILE__, __LINE__, "creating CTLineRef failed.");
|
98
163
|
|
99
|
-
coord width
|
100
|
-
width = get_width(str);
|
101
|
-
height = get_height(&ascent);
|
102
|
-
|
103
|
-
height = ceil(height);
|
164
|
+
coord width, height, ascent = 0;
|
165
|
+
width = ceil(get_width(str));
|
166
|
+
height = ceil(get_height(&ascent));
|
104
167
|
ascent = floor(ascent);
|
105
168
|
|
106
169
|
CGRect rect = CGRectMake(x, context_height - height - y, width, height);
|
@@ -112,10 +175,8 @@ namespace Rays
|
|
112
175
|
CGContextSaveGState(context);
|
113
176
|
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
|
114
177
|
CGContextSetTextPosition(context, x, context_height - ascent - y);
|
115
|
-
CTLineDraw(line, context);
|
178
|
+
CTLineDraw(line.get(), context);
|
116
179
|
CGContextRestoreGState(context);
|
117
|
-
|
118
|
-
CFRelease(line);
|
119
180
|
}
|
120
181
|
|
121
182
|
String
|
@@ -123,14 +184,13 @@ namespace Rays
|
|
123
184
|
{
|
124
185
|
if (!*this) return "";
|
125
186
|
|
126
|
-
|
187
|
+
CFStringPtr str(CTFontCopyFullName(self->font), CFRelease);
|
127
188
|
|
128
189
|
enum {BUFSIZE = 2048};
|
129
190
|
char buf[BUFSIZE + 1];
|
130
|
-
if (!CFStringGetCString(str, buf, BUFSIZE, kCFStringEncodingUTF8))
|
191
|
+
if (!CFStringGetCString(str.get(), buf, BUFSIZE, kCFStringEncodingUTF8))
|
131
192
|
buf[0] = '\0';
|
132
193
|
|
133
|
-
CFRelease(str);
|
134
194
|
return buf;
|
135
195
|
}
|
136
196
|
|
@@ -152,14 +212,11 @@ namespace Rays
|
|
152
212
|
|
153
213
|
if (*str == '\0') return 0;
|
154
214
|
|
155
|
-
|
215
|
+
CTLinePtr line = make_line(self->font, str);
|
156
216
|
if (!line)
|
157
217
|
rays_error(__FILE__, __LINE__, "creating CTLineRef failed.");
|
158
218
|
|
159
|
-
|
160
|
-
CFRelease(line);
|
161
|
-
|
162
|
-
return w;
|
219
|
+
return CTLineGetTypographicBounds(line.get(), NULL, NULL, NULL);
|
163
220
|
}
|
164
221
|
|
165
222
|
coord
|