fontconfig 0.0.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.
- data/.gitignore +18 -0
- data/Gemfile +7 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +21 -0
- data/ext/fontconfig/extconf.rb +6 -0
- data/ext/fontconfig/fc_config.c +357 -0
- data/ext/fontconfig/fc_fontset.c +111 -0
- data/ext/fontconfig/fc_objectset.c +87 -0
- data/ext/fontconfig/fc_pattern.c +202 -0
- data/ext/fontconfig/fontconfig.c +24 -0
- data/ext/fontconfig/rb_fontconfig.h +19 -0
- data/fontconfig.gemspec +24 -0
- data/lib/fontconfig/version.rb +3 -0
- data/lib/fontconfig.rb +32 -0
- data/spec/base_spec.rb +16 -0
- data/spec/config_spec.rb +39 -0
- data/spec/object_set_spec.rb +26 -0
- data/spec/pattern_spec.rb +51 -0
- data/spec/test_helper.rb +5 -0
- metadata +141 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Vasily Fedoseyev
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Fontconfig
|
2
|
+
|
3
|
+
Ruby bindings for fontconfig (http://fontconfig.org)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'fontconfig'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install fontconfig
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
|
4
|
+
require 'rake/extensiontask'
|
5
|
+
Rake::ExtensionTask.new('fontconfig')
|
6
|
+
|
7
|
+
require 'rake/testtask'
|
8
|
+
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.pattern = 'spec/**/*_spec.rb'
|
11
|
+
t.libs.push 'spec'
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
task :bundler do
|
16
|
+
require 'bundler/setup'
|
17
|
+
end
|
18
|
+
|
19
|
+
task :test => [:compile, :bundler]
|
20
|
+
|
21
|
+
task :default => :test
|
@@ -0,0 +1,357 @@
|
|
1
|
+
#include "rb_fontconfig.h"
|
2
|
+
|
3
|
+
VALUE rb_cFcConfig;
|
4
|
+
|
5
|
+
static size_t fc_config_memsize(const void *p) { return 0; }
|
6
|
+
static void fc_config_free(void* p){
|
7
|
+
if(p){
|
8
|
+
// FcConfigDestroy -- Destroy a configuration
|
9
|
+
FcConfigDestroy((FcConfig*)p);
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
static const rb_data_type_t Fc_Config_data_type = {
|
14
|
+
"FcConfig", 0, fc_config_free, fc_config_memsize,
|
15
|
+
};
|
16
|
+
|
17
|
+
static VALUE config_wrap(FcConfig* p){
|
18
|
+
return TypedData_Wrap_Struct(rb_cFcConfig, &Fc_Config_data_type, p);
|
19
|
+
}
|
20
|
+
|
21
|
+
int is_fc_config(VALUE val){
|
22
|
+
return rb_typeddata_is_kind_of(val, &Fc_Config_data_type);
|
23
|
+
}
|
24
|
+
|
25
|
+
#define CONFIG_UNWRAP(c) ((FcConfig*)RTYPEDDATA_DATA(c))
|
26
|
+
|
27
|
+
// FcConfigParseAndLoad -- load a configuration file
|
28
|
+
static VALUE rb_config_parse_and_load(int argc, VALUE *argv, VALUE self){
|
29
|
+
VALUE path, complain = Qnil;
|
30
|
+
rb_scan_args(argc, argv, "11", &path, &complain);
|
31
|
+
if(TYPE(path)!=T_STRING)
|
32
|
+
path = rb_any_to_s(path);
|
33
|
+
|
34
|
+
int res = FcConfigParseAndLoad(CONFIG_UNWRAP(self), RSTRING_PTR(path), RTEST(complain));
|
35
|
+
return BOOL2VAL(res);
|
36
|
+
}
|
37
|
+
|
38
|
+
// FcConfigCreate -- Create a configuration
|
39
|
+
static VALUE rb_config_new(int argc, VALUE *argv, VALUE klass){
|
40
|
+
FcConfig * conf = FcConfigCreate();
|
41
|
+
VALUE file;
|
42
|
+
rb_scan_args(argc, argv, "01", &file);
|
43
|
+
|
44
|
+
if(!conf){
|
45
|
+
rb_raise(rb_eRuntimeError, "Cannot create FcConfig");
|
46
|
+
}
|
47
|
+
VALUE self = config_wrap(conf);
|
48
|
+
if(RTEST(file)){
|
49
|
+
if(!rb_config_parse_and_load(1, &file, self) == Qfalse){
|
50
|
+
FcConfigDestroy(conf);
|
51
|
+
RTYPEDDATA_DATA(self) = 0;
|
52
|
+
rb_raise(rb_eRuntimeError, "Cannot load FcConfig");
|
53
|
+
}
|
54
|
+
}
|
55
|
+
return self;
|
56
|
+
}
|
57
|
+
|
58
|
+
// FcConfigFilename -- Find a config file
|
59
|
+
static VALUE rb_config_filename(VALUE klass, VALUE filename){
|
60
|
+
// in FONTCONFIG_PATH
|
61
|
+
char* fname = 0;
|
62
|
+
if(RTEST(filename)){
|
63
|
+
if(TYPE(filename) != T_STRING)
|
64
|
+
filename = rb_any_to_s(filename);
|
65
|
+
fname = RSTRING_PTR(filename);
|
66
|
+
}
|
67
|
+
char* res = FcConfigFilename(fname);
|
68
|
+
if(!res){
|
69
|
+
rb_raise(rb_eRuntimeError, "cannot get config filename");
|
70
|
+
}
|
71
|
+
VALUE rb_res = rb_str_new2(res);
|
72
|
+
FcStrFree(res); //?
|
73
|
+
return rb_res;
|
74
|
+
}
|
75
|
+
|
76
|
+
// FcConfigGetCurrent -- Return current configuration
|
77
|
+
//// FcConfigReference -- Increment config reference count
|
78
|
+
static VALUE rb_config_get_current(VALUE klass){
|
79
|
+
FcConfig* conf = FcConfigGetCurrent();
|
80
|
+
if(!conf)
|
81
|
+
rb_raise(rb_eRuntimeError, "no current in FcConfigGetCurrent");
|
82
|
+
FcConfigReference(conf);
|
83
|
+
return config_wrap(conf);
|
84
|
+
}
|
85
|
+
|
86
|
+
// FcConfigSetCurrent -- Set configuration as default
|
87
|
+
static VALUE rb_config_set_current(VALUE self){
|
88
|
+
return BOOL2VAL(FcConfigSetCurrent(CONFIG_UNWRAP(self)));
|
89
|
+
}
|
90
|
+
|
91
|
+
// FcConfigUptoDate -- Check timestamps on config files
|
92
|
+
static VALUE rb_config_up_to_date_p(VALUE self){
|
93
|
+
return BOOL2VAL(FcConfigUptoDate(CONFIG_UNWRAP(self)));
|
94
|
+
}
|
95
|
+
|
96
|
+
// FcConfigHome -- return the current home directory.
|
97
|
+
static VALUE rb_config_home(VALUE klass){
|
98
|
+
char* home = FcConfigHome();
|
99
|
+
if(!home)
|
100
|
+
return Qnil;
|
101
|
+
return rb_str_new2(home);
|
102
|
+
}
|
103
|
+
|
104
|
+
// FcConfigEnableHome -- controls use of the home directory.
|
105
|
+
static VALUE rb_config_enable_home(int argc, VALUE *argv, VALUE klass){
|
106
|
+
VALUE enable;
|
107
|
+
if(rb_scan_args(argc, argv, "01", &enable) == 0){
|
108
|
+
enable = Qtrue;
|
109
|
+
}
|
110
|
+
return BOOL2VAL(FcConfigEnableHome(RTEST(enable)));
|
111
|
+
}
|
112
|
+
|
113
|
+
// FcConfigBuildFonts -- Build font database
|
114
|
+
static VALUE rb_config_build_fonts(VALUE self){
|
115
|
+
//TODO: set some flag?
|
116
|
+
//changes after this have undetermined effects
|
117
|
+
return BOOL2VAL(FcConfigBuildFonts(CONFIG_UNWRAP(self)));
|
118
|
+
}
|
119
|
+
|
120
|
+
VALUE FcStrList2Array(FcStrList* list){
|
121
|
+
VALUE res = rb_ary_new();
|
122
|
+
char* str;
|
123
|
+
while(str = FcStrListNext(list)){
|
124
|
+
rb_ary_push(res, rb_str_new2(str));
|
125
|
+
}
|
126
|
+
FcStrListDone(list);
|
127
|
+
return res;
|
128
|
+
}
|
129
|
+
|
130
|
+
// FcConfigGetConfigDirs -- Get config directories
|
131
|
+
static VALUE rb_config_get_config_dirs(VALUE self){
|
132
|
+
FcStrList * list = FcConfigGetConfigDirs(CONFIG_UNWRAP(self));
|
133
|
+
return FcStrList2Array(list);
|
134
|
+
}
|
135
|
+
|
136
|
+
// FcConfigGetFontDirs -- Get font directories
|
137
|
+
static VALUE rb_config_get_font_dirs(VALUE self){
|
138
|
+
FcStrList * list = FcConfigGetFontDirs(CONFIG_UNWRAP(self));
|
139
|
+
return FcStrList2Array(list);
|
140
|
+
}
|
141
|
+
|
142
|
+
// FcConfigGetConfigFiles -- Get config files
|
143
|
+
static VALUE rb_config_get_config_files(VALUE self){
|
144
|
+
FcStrList * list = FcConfigGetConfigFiles(CONFIG_UNWRAP(self));
|
145
|
+
return FcStrList2Array(list);
|
146
|
+
}
|
147
|
+
|
148
|
+
// FcConfigGetCacheDirs -- return the list of directories searched for cache files
|
149
|
+
static VALUE rb_config_get_cache_dirs(VALUE self){
|
150
|
+
FcStrList * list = FcConfigGetCacheDirs(CONFIG_UNWRAP(self));
|
151
|
+
return FcStrList2Array(list);
|
152
|
+
}
|
153
|
+
|
154
|
+
// FcConfigGetRescanInterval -- Get config rescan interval
|
155
|
+
static VALUE rb_config_get_rescan_interval(VALUE self){
|
156
|
+
return INT2FIX(FcConfigGetRescanInterval(CONFIG_UNWRAP(self)));
|
157
|
+
}
|
158
|
+
|
159
|
+
// FcConfigSetRescanInterval -- Set config rescan interval
|
160
|
+
static VALUE rb_config_set_rescan_interval(VALUE self, VALUE interval){
|
161
|
+
interval = rb_to_int(interval);
|
162
|
+
return INT2FIX(FcConfigSetRescanInterval(CONFIG_UNWRAP(self), NUM2INT(interval)));
|
163
|
+
}
|
164
|
+
|
165
|
+
// FcConfigGetSysRoot -- Obtain the system root directory
|
166
|
+
static VALUE rb_config_get_sys_root(VALUE self){
|
167
|
+
const char* res = FcConfigGetSysRoot(CONFIG_UNWRAP(self));
|
168
|
+
if(!res)
|
169
|
+
return Qnil;
|
170
|
+
return rb_str_new2(res);
|
171
|
+
}
|
172
|
+
|
173
|
+
// FcConfigSetSysRoot -- Set the system root directory
|
174
|
+
static VALUE rb_config_set_sys_root(VALUE self, VALUE root){
|
175
|
+
FcConfigSetSysRoot(CONFIG_UNWRAP(self), StringValuePtr(root));
|
176
|
+
return self;
|
177
|
+
}
|
178
|
+
|
179
|
+
// FcFontRenderPrepare -- Prepare pattern for loading font file
|
180
|
+
static VALUE rb_config_font_render_prepare(VALUE self, VALUE pat, VALUE font){
|
181
|
+
if(!is_fc_pattern(pat) || !is_fc_pattern(font)){
|
182
|
+
rb_raise(rb_eArgError, "arguments must be Fontconfig::Pattern");
|
183
|
+
}
|
184
|
+
FcPattern * res = FcFontRenderPrepare(CONFIG_UNWRAP(self), (FcPattern*)RTYPEDDATA_DATA(pat), (FcPattern*)RTYPEDDATA_DATA(font));
|
185
|
+
if(!res){
|
186
|
+
rb_raise(rb_eRuntimeError, "FcFontRenderPrepare returned NULL");
|
187
|
+
}
|
188
|
+
return pattern_wrap(res);
|
189
|
+
}
|
190
|
+
|
191
|
+
// FcConfigAppFontClear -- Remove all app fonts from font database
|
192
|
+
static VALUE rb_config_app_font_clear(VALUE self){
|
193
|
+
FcConfigAppFontClear(CONFIG_UNWRAP(self));
|
194
|
+
return self;
|
195
|
+
}
|
196
|
+
|
197
|
+
// FcConfigAppFontAddFile -- Add font file to font database
|
198
|
+
static VALUE rb_config_app_font_add_file(VALUE self, VALUE path){
|
199
|
+
return BOOL2VAL(FcConfigAppFontAddFile(CONFIG_UNWRAP(self), StringValuePtr(path)));
|
200
|
+
}
|
201
|
+
|
202
|
+
// FcConfigAppFontAddDir -- Add fonts from directory to font database
|
203
|
+
static VALUE rb_config_app_font_add_dir(VALUE self, VALUE path){
|
204
|
+
return BOOL2VAL(FcConfigAppFontAddDir(CONFIG_UNWRAP(self), StringValuePtr(path)));
|
205
|
+
}
|
206
|
+
|
207
|
+
|
208
|
+
// FcFontMatch -- Return best font
|
209
|
+
// This function should be called only after FcConfigSubstitute and FcDefaultSubstitute called on pattern
|
210
|
+
// TODO: check for this?
|
211
|
+
static VALUE rb_config_font_match(VALUE self, VALUE pattern){
|
212
|
+
if(!is_fc_pattern(pattern)){
|
213
|
+
rb_raise(rb_eArgError, "argument must be Fontconfig::Pattern");
|
214
|
+
}
|
215
|
+
FcResult res; // result of FcFontRenderPrepare for font and the provided pattern //???
|
216
|
+
FcPattern* match = FcFontMatch(CONFIG_UNWRAP(self), RTYPEDDATA_DATA(pattern), &res);
|
217
|
+
if(match){
|
218
|
+
return pattern_wrap(match);
|
219
|
+
}
|
220
|
+
return Qnil;
|
221
|
+
}
|
222
|
+
|
223
|
+
VALUE symPattern, symFont, symScan;
|
224
|
+
|
225
|
+
FcMatchKind sym2match_kind(VALUE match_kind){
|
226
|
+
if(match_kind == symPattern)
|
227
|
+
return FcMatchPattern;
|
228
|
+
else if(match_kind == symFont)
|
229
|
+
return FcMatchFont;
|
230
|
+
else if(match_kind == symScan)
|
231
|
+
return FcMatchScan;
|
232
|
+
else
|
233
|
+
rb_raise(rb_eArgError, "match_kind argument must be one of [:pattern, :font, :scan]");
|
234
|
+
return FcMatchPattern;
|
235
|
+
}
|
236
|
+
|
237
|
+
// FcConfigSubstitute -- Execute substitutions
|
238
|
+
static VALUE rb_config_substitute(int argc, VALUE *argv, VALUE self){
|
239
|
+
VALUE pattern, match_kind;
|
240
|
+
rb_scan_args(argc, argv, "11", &pattern, &match_kind);
|
241
|
+
|
242
|
+
if(!is_fc_pattern(pattern)){
|
243
|
+
rb_raise(rb_eArgError, "argument must be Fontconfig::Pattern");
|
244
|
+
}
|
245
|
+
FcMatchKind kind = FcMatchPattern; //TODO: default?
|
246
|
+
if(RTEST(match_kind))
|
247
|
+
kind = sym2match_kind(match_kind);
|
248
|
+
|
249
|
+
return BOOL2VAL(FcConfigSubstitute(CONFIG_UNWRAP(self), RTYPEDDATA_DATA(pattern), kind));
|
250
|
+
}
|
251
|
+
|
252
|
+
// FcConfigSubstituteWithPat -- Execute substitutions
|
253
|
+
static VALUE rb_config_substitute_with_pat(int argc, VALUE *argv, VALUE self){
|
254
|
+
VALUE pattern, pat, match_kind;
|
255
|
+
int n = rb_scan_args(argc, argv, "12", &pattern, &pat, &match_kind);
|
256
|
+
|
257
|
+
if(n == 2){
|
258
|
+
match_kind = pat;
|
259
|
+
pat = Qnil;
|
260
|
+
}
|
261
|
+
|
262
|
+
if(!is_fc_pattern(pattern)){
|
263
|
+
rb_raise(rb_eArgError, "argument must be Fontconfig::Pattern");
|
264
|
+
}
|
265
|
+
FcPattern* pat_pat = 0;
|
266
|
+
if(RTEST(pat)){
|
267
|
+
if(!is_fc_pattern(pat)){
|
268
|
+
rb_raise(rb_eArgError, "argument must be Fontconfig::Pattern");
|
269
|
+
}
|
270
|
+
pat_pat = RTYPEDDATA_DATA(pat);
|
271
|
+
}
|
272
|
+
FcMatchKind kind = FcMatchPattern; //TODO: default?
|
273
|
+
if(RTEST(match_kind))
|
274
|
+
kind = sym2match_kind(match_kind);
|
275
|
+
|
276
|
+
return BOOL2VAL(FcConfigSubstituteWithPat(CONFIG_UNWRAP(self), RTYPEDDATA_DATA(pattern), pat_pat, kind));
|
277
|
+
}
|
278
|
+
|
279
|
+
// FcFontList -- List fonts
|
280
|
+
static VALUE rb_config_font_list(int argc, VALUE *argv, VALUE self){
|
281
|
+
// FcPattern *p, FcObjectSet *os(optional)
|
282
|
+
VALUE pattern, object_set;
|
283
|
+
FcObjectSet* os = 0;
|
284
|
+
rb_scan_args(argc, argv, "11", &pattern, &object_set);
|
285
|
+
if(!is_fc_pattern(pattern)){
|
286
|
+
rb_raise(rb_eArgError, "argument must be Fontconfig::Pattern");
|
287
|
+
}
|
288
|
+
if(object_set){
|
289
|
+
if(is_FcObjectSet(object_set)){
|
290
|
+
os = RTYPEDDATA_DATA(object_set);
|
291
|
+
} else {
|
292
|
+
//TODO: convert array to os?
|
293
|
+
rb_raise(rb_eArgError, "os must be Fontconfig::ObjectSet");
|
294
|
+
}
|
295
|
+
}
|
296
|
+
FcFontSet* set = FcFontList(CONFIG_UNWRAP(self), RTYPEDDATA_DATA(pattern), os);
|
297
|
+
|
298
|
+
return self;
|
299
|
+
}
|
300
|
+
|
301
|
+
// FcConfigGetFonts -- Get config font set
|
302
|
+
static VALUE config_get_fonts(VALUE self, FcSetName set_name){
|
303
|
+
FcFontSet* set = FcConfigGetFonts(CONFIG_UNWRAP(self), set_name);
|
304
|
+
|
305
|
+
}
|
306
|
+
|
307
|
+
static VALUE rb_config_get_system_fonts(VALUE self){
|
308
|
+
return config_get_fonts(self, FcSetSystem);
|
309
|
+
}
|
310
|
+
|
311
|
+
static VALUE rb_config_get_application_fonts(VALUE self){
|
312
|
+
return config_get_fonts(self, FcSetApplication);
|
313
|
+
}
|
314
|
+
|
315
|
+
|
316
|
+
void Init_fontconfig_config(){
|
317
|
+
rb_cFcConfig = rb_define_class_under(rb_cFontconfig, "Config", rb_cObject);
|
318
|
+
rb_define_singleton_method(rb_cFcConfig, "new", rb_config_new, -1);
|
319
|
+
rb_define_method(rb_cFcConfig, "parse_and_load", rb_config_parse_and_load, -1);
|
320
|
+
rb_define_singleton_method(rb_cFcConfig, "filename", rb_config_filename, 1);
|
321
|
+
rb_define_singleton_method(rb_cFcConfig, "get_current", rb_config_get_current, 0);
|
322
|
+
rb_define_method(rb_cFcConfig, "set_current!", rb_config_set_current, 0);
|
323
|
+
rb_define_method(rb_cFcConfig, "up_to_date?", rb_config_up_to_date_p, 0);
|
324
|
+
rb_define_singleton_method(rb_cFcConfig, "home", rb_config_home, 0);
|
325
|
+
rb_define_singleton_method(rb_cFcConfig, "enable_home!", rb_config_enable_home, -1);
|
326
|
+
rb_define_method(rb_cFcConfig, "build_fonts!", rb_config_build_fonts, 0);
|
327
|
+
|
328
|
+
rb_define_method(rb_cFcConfig, "config_dirs", rb_config_get_config_dirs, 0);
|
329
|
+
rb_define_method(rb_cFcConfig, "font_dirs", rb_config_get_font_dirs, 0);
|
330
|
+
rb_define_method(rb_cFcConfig, "config_files", rb_config_get_config_files, 0);
|
331
|
+
rb_define_method(rb_cFcConfig, "cache_dirs", rb_config_get_cache_dirs, 0);
|
332
|
+
|
333
|
+
rb_define_method(rb_cFcConfig, "rescan_interval", rb_config_get_rescan_interval, 0);
|
334
|
+
rb_define_method(rb_cFcConfig, "rescan_interval=", rb_config_set_rescan_interval, 1);
|
335
|
+
rb_define_method(rb_cFcConfig, "sys_root", rb_config_get_sys_root, 0);
|
336
|
+
rb_define_method(rb_cFcConfig, "set_sys_root!", rb_config_set_sys_root, 1);
|
337
|
+
|
338
|
+
rb_define_method(rb_cFcConfig, "font_render_prepare", rb_config_font_render_prepare, 2);
|
339
|
+
|
340
|
+
rb_define_method(rb_cFcConfig, "app_font_clear!", rb_config_app_font_clear, 0);
|
341
|
+
rb_define_method(rb_cFcConfig, "app_font_add_file", rb_config_app_font_add_file, 1);
|
342
|
+
rb_define_method(rb_cFcConfig, "app_font_add_dir", rb_config_app_font_add_dir, 1);
|
343
|
+
|
344
|
+
rb_define_method(rb_cFcConfig, "font_match", rb_config_font_match, 1);
|
345
|
+
|
346
|
+
symPattern = ID2SYM(rb_intern("pattern"));
|
347
|
+
symFont = ID2SYM(rb_intern("font"));
|
348
|
+
symScan = ID2SYM(rb_intern("scan"));
|
349
|
+
rb_define_method(rb_cFcConfig, "substitute", rb_config_substitute, -1);
|
350
|
+
rb_define_method(rb_cFcConfig, "substitute_with_pat", rb_config_substitute_with_pat, -1);
|
351
|
+
|
352
|
+
|
353
|
+
// FcConfigGetBlanks -- Get config blanks
|
354
|
+
// FcFontSort -- Return list of matching fonts
|
355
|
+
|
356
|
+
// FcConfigGetCache -- DEPRECATED used to return per-user cache filename
|
357
|
+
}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#include "rb_fontconfig.h"
|
2
|
+
|
3
|
+
VALUE rb_cFcFontSet;
|
4
|
+
|
5
|
+
static size_t fc_object_set_memsize(const void *p) { return 0; }
|
6
|
+
static void fc_object_set_free(void* p){
|
7
|
+
if(p){
|
8
|
+
FcFontSetDestroy((FcFontSet*)p);
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
static const rb_data_type_t FcFontSet_data_type = {
|
13
|
+
"FcFontSet", 0, fc_object_set_free, fc_object_set_memsize,
|
14
|
+
};
|
15
|
+
|
16
|
+
VALUE font_set_wrap(FcFontSet* p){
|
17
|
+
return TypedData_Wrap_Struct(rb_cFcFontSet, &FcFontSet_data_type, p);
|
18
|
+
}
|
19
|
+
|
20
|
+
int is_FcFontSet(VALUE val){
|
21
|
+
return rb_typeddata_is_kind_of(val, &FcFontSet_data_type);
|
22
|
+
}
|
23
|
+
|
24
|
+
#define OSET_UNWRAP(c) ((FcFontSet*)RTYPEDDATA_DATA(c))
|
25
|
+
|
26
|
+
static VALUE rb_oset_add(VALUE self, VALUE val){
|
27
|
+
if(!is_fc_pattern(val)){
|
28
|
+
rb_raise(rb_eArgError, "argument must be a FcPattern");
|
29
|
+
}
|
30
|
+
if(!FcFontSetAdd(OSET_UNWRAP(self), pattern_unwrap(val))){
|
31
|
+
rb_raise(rb_eRuntimeError, "cannot insert into FcFontSet");
|
32
|
+
}
|
33
|
+
return val;
|
34
|
+
}
|
35
|
+
|
36
|
+
static VALUE oset_add_i(VALUE str, VALUE self, int argc, VALUE *argv){
|
37
|
+
return rb_oset_add(self, str);
|
38
|
+
}
|
39
|
+
|
40
|
+
static VALUE rb_oset_new(int argc, VALUE *argv, VALUE klass){
|
41
|
+
VALUE optional = Qnil;
|
42
|
+
rb_scan_args(argc, argv, "01", &optional);
|
43
|
+
FcFontSet* set = FcFontSetCreate();
|
44
|
+
if(!set)
|
45
|
+
rb_raise(rb_eRuntimeError, "cannot create FcFontSet");
|
46
|
+
|
47
|
+
VALUE self = object_set_wrap(set);
|
48
|
+
if(optional != Qnil){
|
49
|
+
ID each = rb_intern("each");
|
50
|
+
if(!rb_respond_to(optional, each))
|
51
|
+
rb_raise(rb_eArgError, "parameter must be enumerable");
|
52
|
+
rb_block_call(optional, each, 0, 0, oset_add_i, self);
|
53
|
+
}
|
54
|
+
return self;
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
static VALUE rb_oset_each(VALUE self){
|
59
|
+
int i;
|
60
|
+
FcFontSet* os = OSET_UNWRAP(self);
|
61
|
+
for (i = 0; i < os->nfont; i++){
|
62
|
+
rb_yield(pattern_wrap(os->fonts[i]));
|
63
|
+
}
|
64
|
+
return self;
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE rb_oset_size(VALUE self){
|
68
|
+
return INT2NUM(OSET_UNWRAP(self)->nfont);
|
69
|
+
}
|
70
|
+
|
71
|
+
static VALUE rb_oset_at(VALUE self, VALUE index){
|
72
|
+
|
73
|
+
int i = NUM2INT(index);
|
74
|
+
FcFontSet* os = OSET_UNWRAP(self);
|
75
|
+
|
76
|
+
if(i < 0 || i >= os->nfont)
|
77
|
+
return Qnil;
|
78
|
+
return pattern_wrap(os->fonts[i]);
|
79
|
+
}
|
80
|
+
|
81
|
+
static VALUE rb_oset_print(VALUE self){
|
82
|
+
FcFontSetPrint(OSET_UNWRAP(self));
|
83
|
+
return self;
|
84
|
+
}
|
85
|
+
|
86
|
+
static VALUE rb_oset_match(VALUE self, VALUE config, VALUE pattern){
|
87
|
+
FcFontSet* set = OSET_UNWRAP(self);
|
88
|
+
FcConfig* conf = 0;
|
89
|
+
if(RTEST(config) && is_fc_config(config))
|
90
|
+
conf = CONFIG_UNWRAP(config);
|
91
|
+
if(!RTEST(pattern) || !is_fc_pattern(pattern))
|
92
|
+
rb_raise(rb_eArgError, "pattern must be Fontconfig::Pattern");
|
93
|
+
FcResult res;
|
94
|
+
FcPattern* result = FcFontSetMatch(conf, &set, 1, pattern_unwrap(pattern), &res);
|
95
|
+
if(!result)
|
96
|
+
return Qnil;
|
97
|
+
return pattern_wrap(result);
|
98
|
+
}
|
99
|
+
|
100
|
+
void Init_fontconfig_fontset(){
|
101
|
+
rb_cFcFontSet = rb_define_class_under(rb_cFontconfig, "FontSet", rb_cObject);
|
102
|
+
rb_define_singleton_method(rb_cFcFontSet, "new", rb_oset_new, -1);
|
103
|
+
rb_define_method(rb_cFcFontSet, "add", rb_oset_add, 1);
|
104
|
+
rb_define_method(rb_cFcFontSet, "<<", rb_oset_add, 1);
|
105
|
+
rb_define_method(rb_cFcFontSet, "each", rb_oset_each, 0);
|
106
|
+
rb_define_method(rb_cFcFontSet, "size", rb_oset_size, 0);
|
107
|
+
rb_define_method(rb_cFcFontSet, "[]", rb_oset_at, 1);
|
108
|
+
rb_define_method(rb_cFcFontSet, "debug_print", rb_oset_print, 0);
|
109
|
+
rb_define_method(rb_cFcFontSet, "match_pattern", rb_oset_match, 1);
|
110
|
+
rb_include_module(rb_cFcFontSet, rb_mEnumerable);
|
111
|
+
}
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#include "rb_fontconfig.h"
|
2
|
+
|
3
|
+
VALUE rb_cFcObjectSet;
|
4
|
+
|
5
|
+
static size_t fc_object_set_memsize(const void *p) { return 0; }
|
6
|
+
static void fc_object_set_free(void* p){
|
7
|
+
if(p){
|
8
|
+
FcObjectSetDestroy((FcObjectSet*)p);
|
9
|
+
}
|
10
|
+
}
|
11
|
+
|
12
|
+
static const rb_data_type_t FcObjectSet_data_type = {
|
13
|
+
"FcObjectSet", 0, fc_object_set_free, fc_object_set_memsize,
|
14
|
+
};
|
15
|
+
|
16
|
+
static VALUE object_set_wrap(FcObjectSet* p){
|
17
|
+
return TypedData_Wrap_Struct(rb_cFcObjectSet, &FcObjectSet_data_type, p);
|
18
|
+
}
|
19
|
+
|
20
|
+
int is_FcObjectSet(VALUE val){
|
21
|
+
return rb_typeddata_is_kind_of(val, &FcObjectSet_data_type);
|
22
|
+
}
|
23
|
+
|
24
|
+
#define OSET_UNWRAP(c) ((FcObjectSet*)RTYPEDDATA_DATA(c))
|
25
|
+
|
26
|
+
static VALUE rb_oset_add(VALUE self, VALUE str){
|
27
|
+
if(!FcObjectSetAdd(OSET_UNWRAP(self), StringValuePtr(str))){
|
28
|
+
rb_raise(rb_eRuntimeError, "cannot insert into FcObjectSet");
|
29
|
+
}
|
30
|
+
return str;
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE oset_add_i(VALUE str, VALUE self, int argc, VALUE *argv){
|
34
|
+
return rb_oset_add(self, str);
|
35
|
+
}
|
36
|
+
|
37
|
+
static VALUE rb_oset_new(int argc, VALUE *argv, VALUE klass){
|
38
|
+
VALUE optional = Qnil;
|
39
|
+
rb_scan_args(argc, argv, "01", &optional);
|
40
|
+
FcObjectSet* set = FcObjectSetCreate();
|
41
|
+
if(!set)
|
42
|
+
rb_raise(rb_eRuntimeError, "cannot create FcObjectSet");
|
43
|
+
|
44
|
+
VALUE self = object_set_wrap(set);
|
45
|
+
if(optional != Qnil){
|
46
|
+
ID each = rb_intern("each");
|
47
|
+
if(!rb_respond_to(optional, each))
|
48
|
+
rb_raise(rb_eArgError, "parameter must be enumerable");
|
49
|
+
rb_block_call(optional, each, 0, 0, oset_add_i, self);
|
50
|
+
}
|
51
|
+
return self;
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
static VALUE rb_oset_each(VALUE self){
|
56
|
+
int i;
|
57
|
+
FcObjectSet* os = OSET_UNWRAP(self);
|
58
|
+
for (i = 0; i < os->nobject; i++){
|
59
|
+
rb_yield(rb_str_new2(os->objects[i]));
|
60
|
+
}
|
61
|
+
return self;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE rb_oset_size(VALUE self){
|
65
|
+
return INT2NUM(OSET_UNWRAP(self)->nobject);
|
66
|
+
}
|
67
|
+
|
68
|
+
static VALUE rb_oset_at(VALUE self, VALUE index){
|
69
|
+
|
70
|
+
int i = NUM2INT(index);
|
71
|
+
FcObjectSet* os = OSET_UNWRAP(self);
|
72
|
+
|
73
|
+
if(i < 0 || i >= os->nobject)
|
74
|
+
return Qnil;
|
75
|
+
return rb_str_new2(os->objects[i]);
|
76
|
+
}
|
77
|
+
|
78
|
+
void Init_fontconfig_objectset(){
|
79
|
+
rb_cFcObjectSet = rb_define_class_under(rb_cFontconfig, "ObjectSet", rb_cObject);
|
80
|
+
rb_define_singleton_method(rb_cFcObjectSet, "new", rb_oset_new, -1);
|
81
|
+
rb_define_method(rb_cFcObjectSet, "add", rb_oset_add, 1);
|
82
|
+
rb_define_method(rb_cFcObjectSet, "<<", rb_oset_add, 1);
|
83
|
+
rb_define_method(rb_cFcObjectSet, "each", rb_oset_each, 0);
|
84
|
+
rb_define_method(rb_cFcObjectSet, "size", rb_oset_size, 0);
|
85
|
+
rb_define_method(rb_cFcObjectSet, "[]", rb_oset_at, 1);
|
86
|
+
rb_include_module(rb_cFcObjectSet, rb_mEnumerable);
|
87
|
+
}
|
@@ -0,0 +1,202 @@
|
|
1
|
+
#include "rb_fontconfig.h"
|
2
|
+
#include <fontconfig/fontconfig.h>
|
3
|
+
|
4
|
+
VALUE rb_cFcPattern;
|
5
|
+
|
6
|
+
static size_t fc_pattern_memsize(const void *p) { return 0; }
|
7
|
+
static void fc_pattern_free(void* p){
|
8
|
+
if(p){
|
9
|
+
FcPatternDestroy((FcPattern*)p);
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
static const rb_data_type_t Fc_Pattern_data_type = {
|
14
|
+
"FcPattern", 0, fc_pattern_free, fc_pattern_memsize,
|
15
|
+
};
|
16
|
+
|
17
|
+
VALUE pattern_wrap(FcPattern* p){
|
18
|
+
return TypedData_Wrap_Struct(rb_cFcPattern, &Fc_Pattern_data_type, p);
|
19
|
+
}
|
20
|
+
|
21
|
+
int is_fc_pattern(VALUE val){
|
22
|
+
return rb_typeddata_is_kind_of(val, &Fc_Pattern_data_type);
|
23
|
+
}
|
24
|
+
|
25
|
+
#define PATTERN_UNWRAP(c) ((FcPattern*)RTYPEDDATA_DATA(c))
|
26
|
+
|
27
|
+
|
28
|
+
static VALUE rb_pattern_parse(VALUE klass, VALUE string){
|
29
|
+
if(TYPE(string) != T_STRING)
|
30
|
+
string = rb_any_to_s(string);
|
31
|
+
FcPattern* p = FcNameParse(RSTRING_PTR(string));
|
32
|
+
return pattern_wrap(p);
|
33
|
+
}
|
34
|
+
|
35
|
+
static VALUE rb_pattern_new(int argc, VALUE *argv, VALUE klass){
|
36
|
+
VALUE optional = Qnil;
|
37
|
+
rb_scan_args(argc, argv, "01", &optional);
|
38
|
+
if(optional != Qnil){
|
39
|
+
if(TYPE(optional) == T_STRING)
|
40
|
+
return rb_pattern_parse(klass, optional);
|
41
|
+
|
42
|
+
rb_raise(rb_eArgError, "parameter must be a string");
|
43
|
+
} else {
|
44
|
+
return pattern_wrap(FcPatternCreate());
|
45
|
+
}
|
46
|
+
}
|
47
|
+
|
48
|
+
static VALUE rb_pattern_format(VALUE self, VALUE format){
|
49
|
+
if(TYPE(format) != T_STRING)
|
50
|
+
format = rb_any_to_s(format);
|
51
|
+
char* res = FcPatternFormat(PATTERN_UNWRAP(self), RSTRING_PTR(format));
|
52
|
+
VALUE str = rb_str_new2((char*)res);
|
53
|
+
FcStrFree(res);
|
54
|
+
return str;
|
55
|
+
}
|
56
|
+
|
57
|
+
static VALUE rb_pattern_to_s(VALUE self){
|
58
|
+
char* res = FcNameUnparse(PATTERN_UNWRAP(self));
|
59
|
+
VALUE str = rb_str_new2((char*)res);
|
60
|
+
FcStrFree(res);
|
61
|
+
return str;
|
62
|
+
}
|
63
|
+
|
64
|
+
static VALUE rb_pattern_duplicate(VALUE self){
|
65
|
+
FcPattern* p = FcPatternDuplicate(PATTERN_UNWRAP(self));
|
66
|
+
return pattern_wrap(p);
|
67
|
+
}
|
68
|
+
|
69
|
+
static VALUE rb_pattern_debugprint(VALUE self){
|
70
|
+
FcPatternPrint(PATTERN_UNWRAP(self));
|
71
|
+
return Qnil;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE rb_pattern_equal(VALUE self, VALUE other){
|
75
|
+
if(!is_fc_pattern(other)){
|
76
|
+
//TODO: cast?
|
77
|
+
return Qfalse;
|
78
|
+
}
|
79
|
+
return FcPatternEqual(PATTERN_UNWRAP(self), PATTERN_UNWRAP(other)) ? Qtrue : Qfalse;
|
80
|
+
}
|
81
|
+
|
82
|
+
static VALUE rb_pattern_hash(VALUE self){
|
83
|
+
int res = FcPatternHash(PATTERN_UNWRAP(self));
|
84
|
+
return INT2NUM(res);
|
85
|
+
}
|
86
|
+
|
87
|
+
static VALUE rb_pattern_add(int argc, VALUE *argv, VALUE self){
|
88
|
+
VALUE object, value, append;
|
89
|
+
rb_scan_args(argc, argv, "21", &object, &value, &append);
|
90
|
+
FcValue val;
|
91
|
+
switch(TYPE(value)){
|
92
|
+
case T_NONE: case T_NIL: val.type = FcTypeVoid; break;
|
93
|
+
case T_FIXNUM: val.type = FcTypeInteger; val.u.i = NUM2INT(value); break;
|
94
|
+
case T_FLOAT: val.type = FcTypeDouble; val.u.d = NUM2DBL(value); break;
|
95
|
+
case T_STRING: val.type = FcTypeString; val.u.s = RSTRING_PTR(value); break;
|
96
|
+
case T_TRUE: val.type = FcTypeBool; val.u.b = 1; break;
|
97
|
+
case T_FALSE: val.type = FcTypeBool; val.u.b = 0; break;
|
98
|
+
case T_OBJECT:
|
99
|
+
//TODO: increment object references?
|
100
|
+
// ...
|
101
|
+
// FcTypeMatrix: // m FcMatrix *
|
102
|
+
// FcTypeCharSet: // c FcCharSet *
|
103
|
+
// FcTypeFTFace: // f void * (FT_Face)
|
104
|
+
// FcTypeLangSet
|
105
|
+
default:
|
106
|
+
rb_raise(rb_eArgError, "unsupported type for value");
|
107
|
+
break;
|
108
|
+
}
|
109
|
+
if(TYPE(object)!=T_STRING)
|
110
|
+
object = rb_any_to_s(object);
|
111
|
+
int res = FcPatternAdd(PATTERN_UNWRAP(self), RSTRING_PTR(object), val, RTEST(append));
|
112
|
+
//TODO: raise on errors?
|
113
|
+
return res? Qtrue : Qfalse;
|
114
|
+
}
|
115
|
+
|
116
|
+
static VALUE fc_value_to_value(FcValue* val){
|
117
|
+
//FcTypeString, FcTypeMatrix and FcTypeCharSet reference memory, need FcValueDestroy or so
|
118
|
+
switch(val->type){
|
119
|
+
case FcTypeVoid: return Qnil;
|
120
|
+
case FcTypeInteger: return INT2FIX(val->u.i);
|
121
|
+
case FcTypeDouble: return rb_float_new(val->u.d);
|
122
|
+
case FcTypeString: return rb_str_new2(val->u.s);
|
123
|
+
case FcTypeBool: return val->u.b? Qtrue : Qfalse;
|
124
|
+
case FcTypeMatrix: // m FcMatrix *
|
125
|
+
case FcTypeCharSet: // c FcCharSet *
|
126
|
+
case FcTypeFTFace: // f void * (FT_Face)
|
127
|
+
case FcTypeLangSet: // l FcLangSet * l
|
128
|
+
//TODO
|
129
|
+
// note: data is not copied, we have a pointer to internal structure
|
130
|
+
return Qnil;
|
131
|
+
default:
|
132
|
+
rb_raise(rb_eRuntimeError, "got unknown FcValue type %d", val->type);
|
133
|
+
break;
|
134
|
+
}
|
135
|
+
return Qnil;
|
136
|
+
}
|
137
|
+
|
138
|
+
static VALUE rb_pattern_get(VALUE self, VALUE object, VALUE id){
|
139
|
+
Check_Type(id, T_FIXNUM);
|
140
|
+
if(TYPE(object)!=T_STRING)
|
141
|
+
object = rb_any_to_s(object);
|
142
|
+
FcValue val;
|
143
|
+
FcResult res = FcPatternGet(PATTERN_UNWRAP(self), RSTRING_PTR(object), FIX2INT(id), &val);
|
144
|
+
if(res == FcResultMatch){
|
145
|
+
VALUE r_res = fc_value_to_value(&val);
|
146
|
+
// FcValueDestroy(val); // gives malloc error
|
147
|
+
return r_res;
|
148
|
+
}
|
149
|
+
if(res == FcResultNoMatch || res == FcResultNoId){
|
150
|
+
//raise?
|
151
|
+
return Qnil;
|
152
|
+
}
|
153
|
+
if(res == FcResultOutOfMemory){
|
154
|
+
rb_raise(rb_eRuntimeError, "FcResultOutOfMemory");
|
155
|
+
}
|
156
|
+
//FcResultTypeMismatch cannot be here
|
157
|
+
return Qnil;
|
158
|
+
}
|
159
|
+
|
160
|
+
static VALUE rb_pattern_delete(VALUE self, VALUE object){
|
161
|
+
if(TYPE(object)!=T_STRING)
|
162
|
+
object = rb_any_to_s(object);
|
163
|
+
int res = FcPatternDel(PATTERN_UNWRAP(self), RSTRING_PTR(object));
|
164
|
+
return res? Qtrue : Qfalse;
|
165
|
+
}
|
166
|
+
|
167
|
+
static VALUE rb_pattern_remove(VALUE self, VALUE object, VALUE id){
|
168
|
+
Check_Type(id, T_FIXNUM);
|
169
|
+
if(TYPE(object)!=T_STRING)
|
170
|
+
object = rb_any_to_s(object);
|
171
|
+
int res = FcPatternRemove(PATTERN_UNWRAP(self), RSTRING_PTR(object), FIX2INT(id));
|
172
|
+
return res? Qtrue : Qfalse;
|
173
|
+
}
|
174
|
+
|
175
|
+
rb_pattern_default_substitute(VALUE self){
|
176
|
+
FcDefaultSubstitute(PATTERN_UNWRAP(self));
|
177
|
+
return self;
|
178
|
+
}
|
179
|
+
|
180
|
+
|
181
|
+
void Init_fontconfig_pattern(){
|
182
|
+
rb_cFcPattern = rb_define_class_under(rb_cFontconfig, "Pattern", rb_cObject);
|
183
|
+
rb_define_singleton_method(rb_cFcPattern, "new", rb_pattern_new, -1);
|
184
|
+
rb_define_singleton_method(rb_cFcPattern, "parse", rb_pattern_parse, 1);
|
185
|
+
rb_define_method(rb_cFcPattern, "dup", rb_pattern_duplicate, 0);
|
186
|
+
|
187
|
+
rb_define_method(rb_cFcPattern, "==", rb_pattern_equal, 1);
|
188
|
+
// rb_define_method(rb_cFcPattern, "equal_subset", rb_pattern_equal, 1);
|
189
|
+
// filter - need set
|
190
|
+
rb_define_method(rb_cFcPattern, "add", rb_pattern_add, -1);
|
191
|
+
rb_define_method(rb_cFcPattern, "get", rb_pattern_get, 2);
|
192
|
+
rb_define_method(rb_cFcPattern, "delete", rb_pattern_delete, 1);
|
193
|
+
rb_define_method(rb_cFcPattern, "remove", rb_pattern_remove, 2);
|
194
|
+
|
195
|
+
rb_define_method(rb_cFcPattern, "hash", rb_pattern_hash, 0);
|
196
|
+
rb_define_method(rb_cFcPattern, "to_s", rb_pattern_to_s, 0);
|
197
|
+
rb_define_method(rb_cFcPattern, "unparse", rb_pattern_to_s, 0);
|
198
|
+
rb_define_method(rb_cFcPattern, "format", rb_pattern_format, 1);
|
199
|
+
rb_define_method(rb_cFcPattern, "debug_print", rb_pattern_debugprint, 0);
|
200
|
+
rb_define_method(rb_cFcPattern, "default_substitute!", rb_pattern_default_substitute, 0);
|
201
|
+
|
202
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#include "rb_fontconfig.h"
|
2
|
+
#include <fontconfig/fontconfig.h>
|
3
|
+
|
4
|
+
VALUE rb_cFontconfig;
|
5
|
+
|
6
|
+
static VALUE rb_fc_version(VALUE self){
|
7
|
+
int version = FcGetVersion();
|
8
|
+
return INT2FIX(version);
|
9
|
+
}
|
10
|
+
|
11
|
+
|
12
|
+
void Init_fontconfig_pattern();
|
13
|
+
void Init_fontconfig_objectset();
|
14
|
+
void Init_fontconfig_fontset();
|
15
|
+
void Init_fontconfig_config();
|
16
|
+
|
17
|
+
void Init_fontconfig(){
|
18
|
+
rb_cFontconfig = rb_define_module("Fontconfig");
|
19
|
+
rb_define_singleton_method(rb_cFontconfig, "library_version", rb_fc_version, 0);
|
20
|
+
Init_fontconfig_pattern();
|
21
|
+
Init_fontconfig_objectset();
|
22
|
+
Init_fontconfig_fontset();
|
23
|
+
Init_fontconfig_config();
|
24
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <fontconfig/fontconfig.h>
|
3
|
+
|
4
|
+
extern VALUE rb_cFontconfig;
|
5
|
+
|
6
|
+
|
7
|
+
#define BOOL2VAL(p) ((p) ? Qtrue : Qfalse)
|
8
|
+
|
9
|
+
int is_fc_pattern(VALUE val);
|
10
|
+
VALUE pattern_wrap(FcPattern* p);
|
11
|
+
#define pattern_unwrap(c) ((FcPattern*)RTYPEDDATA_DATA(c))
|
12
|
+
|
13
|
+
int is_FcObjectSet(VALUE val);
|
14
|
+
|
15
|
+
VALUE font_set_wrap(FcFontSet* p);
|
16
|
+
int is_FcFontSet(VALUE val);
|
17
|
+
|
18
|
+
int is_fc_config(VALUE val);
|
19
|
+
#define CONFIG_UNWRAP(c) ((FcConfig*)RTYPEDDATA_DATA(c))
|
data/fontconfig.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/fontconfig/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Vasily Fedoseyev"]
|
6
|
+
gem.email = ["vasilyfedoseyev@gmail.com"]
|
7
|
+
gem.description = %q{}
|
8
|
+
gem.summary = %q{Ruby bindings for fontconfig library}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "fontconfig"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Fontconfig::VERSION
|
17
|
+
|
18
|
+
gem.extensions = "ext/fontconfig/extconf.rb"
|
19
|
+
|
20
|
+
gem.add_dependency "pkg-config"
|
21
|
+
gem.add_development_dependency "rake-compiler"
|
22
|
+
gem.add_development_dependency "minitest"
|
23
|
+
gem.add_development_dependency "minitest-reporters"
|
24
|
+
end
|
data/lib/fontconfig.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require "fontconfig/version"
|
2
|
+
|
3
|
+
require 'rbconfig'
|
4
|
+
require "fontconfig.#{RbConfig::CONFIG['DLEXT']}"
|
5
|
+
|
6
|
+
module Fontconfig
|
7
|
+
class Pattern
|
8
|
+
|
9
|
+
class Proxy
|
10
|
+
def initialize pattern, key
|
11
|
+
@pattern = pattern
|
12
|
+
@key = key
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](num)
|
16
|
+
@pattern.get(@key, num)
|
17
|
+
end
|
18
|
+
|
19
|
+
def <<(obj)
|
20
|
+
@pattern.add(@key, obj, true)
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete!
|
24
|
+
@pattern.delete(@key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def [](key)
|
29
|
+
return Proxy.new(self, key)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
describe Fontconfig do
|
5
|
+
subject { Fontconfig }
|
6
|
+
|
7
|
+
it "should be" do
|
8
|
+
subject.wont_be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "version" do
|
12
|
+
# puts "Lib version #{subject.library_version}"
|
13
|
+
subject.library_version.must_be :>, 0
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
describe Fontconfig::Config do
|
5
|
+
describe "class methods" do
|
6
|
+
subject { Fontconfig::Config }
|
7
|
+
describe "new" do
|
8
|
+
it "works" do
|
9
|
+
subject.new.must_be_instance_of subject
|
10
|
+
end
|
11
|
+
|
12
|
+
it "loads config" do
|
13
|
+
skip
|
14
|
+
subject.new "some_config_file"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "raises if cannot load" do
|
18
|
+
assert_raises(RuntimeError){
|
19
|
+
subject.new "some_config_file"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "filename" do
|
25
|
+
res = subject.filename('')
|
26
|
+
puts "res is #{res}"
|
27
|
+
res.must_be_instance_of String
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
subject { Fontconfig::Config.new }
|
32
|
+
|
33
|
+
|
34
|
+
it "config_dirs" do
|
35
|
+
r = subject.config_dirs
|
36
|
+
puts "config_dirs is '#{r}'"
|
37
|
+
r.must_be_instance_of Array
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
describe Fontconfig::ObjectSet do
|
5
|
+
describe "class methods" do
|
6
|
+
subject { Fontconfig::ObjectSet }
|
7
|
+
describe "new" do
|
8
|
+
it "works" do
|
9
|
+
subject.new.must_be_instance_of subject
|
10
|
+
end
|
11
|
+
|
12
|
+
it "init by array of strings" do
|
13
|
+
arr = %w{str1 str2 str3}.sort
|
14
|
+
(s = subject.new(arr)).must_be_instance_of subject
|
15
|
+
s.to_a.sort.must_equal arr
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
subject { Fontconfig::ObjectSet.new }
|
21
|
+
|
22
|
+
it "add" do
|
23
|
+
subject << "str"
|
24
|
+
subject.to_a.must_equal ["str"]
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'test_helper'
|
3
|
+
|
4
|
+
describe Fontconfig::Pattern do
|
5
|
+
|
6
|
+
describe "class methods" do
|
7
|
+
subject { Fontconfig::Pattern }
|
8
|
+
|
9
|
+
it "create by parsing" do
|
10
|
+
res = subject.parse("Monospace Bold 12px")
|
11
|
+
res.must_be_instance_of subject
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "instance" do
|
17
|
+
subject { Fontconfig::Pattern.parse("monospace-Bold-Italic 21") }
|
18
|
+
|
19
|
+
it "to_s" do
|
20
|
+
res = subject.to_s
|
21
|
+
res.must_be_kind_of String
|
22
|
+
end
|
23
|
+
|
24
|
+
it "format" do
|
25
|
+
res = subject.format("%{family}")
|
26
|
+
# subject.debug_print
|
27
|
+
# puts "format #{res}"
|
28
|
+
res.must_be_kind_of String
|
29
|
+
end
|
30
|
+
|
31
|
+
it "hash" do
|
32
|
+
subject.hash.must_be_kind_of Fixnum
|
33
|
+
end
|
34
|
+
|
35
|
+
it "set/det/delete" do
|
36
|
+
subject.add("key", "value")
|
37
|
+
subject.add("key", "value2", true)
|
38
|
+
subject.get("key", 0).must_equal "value"
|
39
|
+
subject.get("key", 1).must_equal "value2"
|
40
|
+
subject.delete("key")
|
41
|
+
subject.get("key", 0).must_be_nil
|
42
|
+
end
|
43
|
+
|
44
|
+
it "default_substitute!" do
|
45
|
+
subject.default_substitute!
|
46
|
+
subject["familylang"][0].must_equal "en"
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/spec/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fontconfig
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Vasily Fedoseyev
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-07-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: pkg-config
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake-compiler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: minitest
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: minitest-reporters
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: ''
|
79
|
+
email:
|
80
|
+
- vasilyfedoseyev@gmail.com
|
81
|
+
executables: []
|
82
|
+
extensions:
|
83
|
+
- ext/fontconfig/extconf.rb
|
84
|
+
extra_rdoc_files: []
|
85
|
+
files:
|
86
|
+
- .gitignore
|
87
|
+
- Gemfile
|
88
|
+
- LICENSE
|
89
|
+
- README.md
|
90
|
+
- Rakefile
|
91
|
+
- ext/fontconfig/extconf.rb
|
92
|
+
- ext/fontconfig/fc_config.c
|
93
|
+
- ext/fontconfig/fc_fontset.c
|
94
|
+
- ext/fontconfig/fc_objectset.c
|
95
|
+
- ext/fontconfig/fc_pattern.c
|
96
|
+
- ext/fontconfig/fontconfig.c
|
97
|
+
- ext/fontconfig/rb_fontconfig.h
|
98
|
+
- fontconfig.gemspec
|
99
|
+
- lib/fontconfig.rb
|
100
|
+
- lib/fontconfig/version.rb
|
101
|
+
- spec/base_spec.rb
|
102
|
+
- spec/config_spec.rb
|
103
|
+
- spec/object_set_spec.rb
|
104
|
+
- spec/pattern_spec.rb
|
105
|
+
- spec/test_helper.rb
|
106
|
+
homepage: ''
|
107
|
+
licenses: []
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
hash: -3843724065432744597
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
hash: -3843724065432744597
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 1.8.24
|
133
|
+
signing_key:
|
134
|
+
specification_version: 3
|
135
|
+
summary: Ruby bindings for fontconfig library
|
136
|
+
test_files:
|
137
|
+
- spec/base_spec.rb
|
138
|
+
- spec/config_spec.rb
|
139
|
+
- spec/object_set_spec.rb
|
140
|
+
- spec/pattern_spec.rb
|
141
|
+
- spec/test_helper.rb
|