extract_ttc 0.3.0 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +15 -0
- data/.rspec +1 -0
- data/.rubocop.yml +12 -0
- data/Gemfile +4 -0
- data/LICENSE.adoc +13 -0
- data/README.adoc +121 -0
- data/Rakefile +104 -0
- data/ext/stripttc/LICENSE +31 -0
- data/ext/stripttc/dummy.c +2 -0
- data/ext/stripttc/extconf.rb +3 -4
- data/ext/stripttc/stripttc.c +187 -0
- data/extract_ttc.gemspec +41 -0
- data/lib/extract_ttc/version.rb +3 -0
- data/lib/extract_ttc.rb +79 -0
- metadata +31 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2cd3fa449092ff68cbb4dc4b2fe809b4cb7572cb8480e30223a4f18f90426eea
|
4
|
+
data.tar.gz: d0dd2a660ee8454b50d334143e7e39000ddd86a43687a30f192db2c3044e78ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9fa8ef273003c4818ccea55c8d3d7cc26ac722ea60050b853754de3fa0b091444984786e2aa2cc3d022ab52b0e47c1e37fdff6842ac21e668053b6fd0827aaf3
|
7
|
+
data.tar.gz: 4b04a04655a031f66456458dddddd8d23f1c9e4bba766edb7aaa9e9af7f92ccfa650a5e16f8f2332b9a5a713be49277ce75a536bc0087c5a4333f53d1fe4bb63
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.adoc
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
= BSD 3-Clause License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Ribose Inc. All rights reserved.
|
4
|
+
|
5
|
+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
8
|
+
|
9
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
10
|
+
|
11
|
+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
12
|
+
|
13
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.adoc
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
= ExtractTtc: Ruby gem to extract TTF from TTC
|
2
|
+
|
3
|
+
== Purpose
|
4
|
+
|
5
|
+
The gem lets you extract individual TrueType font files (`.ttf`) from a TrueType Collection file (`.ttc`).
|
6
|
+
|
7
|
+
`ExtractTtc` wraps functionality provided by `stripttc.c`, originally from the
|
8
|
+
https://github.com/fontforge/fontforge[FontForge project] as an FFI extension.
|
9
|
+
|
10
|
+
Specifically, `stripttc.c` is part of the `contribs` directory of FontForge, which
|
11
|
+
is
|
12
|
+
https://github.com/fontforge/fontforge/blob/21ad4a18fb3d4becfe566d8215eba4483b0ddc4b/contrib/CMakeLists.txt#L1[assigned]
|
13
|
+
the
|
14
|
+
https://github.com/fontforge/fontforge/blob/21ad4a18fb3d4becfe566d8215eba4483b0ddc4b/LICENSE#L12-L57[BSD 3-Clause license].
|
15
|
+
|
16
|
+
|
17
|
+
== Installation
|
18
|
+
|
19
|
+
Add this line to your application's `Gemfile`:
|
20
|
+
|
21
|
+
[source,ruby]
|
22
|
+
----
|
23
|
+
gem 'extract_ttc'
|
24
|
+
----
|
25
|
+
|
26
|
+
And then execute:
|
27
|
+
|
28
|
+
[source,sh]
|
29
|
+
----
|
30
|
+
$ bundle install
|
31
|
+
----
|
32
|
+
|
33
|
+
Or install it yourself as:
|
34
|
+
|
35
|
+
[source,sh]
|
36
|
+
----
|
37
|
+
$ gem install extract_ttc
|
38
|
+
----
|
39
|
+
|
40
|
+
== Usage
|
41
|
+
|
42
|
+
[source,ruby]
|
43
|
+
----
|
44
|
+
ExtractTtc.extract("path/to/ttc/Helvetica.ttc")
|
45
|
+
----
|
46
|
+
|
47
|
+
Would extract contained TTF files from TTC to a current directory.
|
48
|
+
|
49
|
+
|
50
|
+
== Development
|
51
|
+
|
52
|
+
We are following Sandi Metz's Rules for this gem, you can read the
|
53
|
+
http://robots.thoughtbot.com/post/50655960596/sandi-metz-rules-for-developers[description of the rules here].
|
54
|
+
All new code should follow these
|
55
|
+
rules. If you make changes in a pre-existing file that violates these rules you
|
56
|
+
should fix the violations as part of your contribution.
|
57
|
+
|
58
|
+
=== Setup
|
59
|
+
|
60
|
+
Clone the repository:
|
61
|
+
|
62
|
+
[source,sh]
|
63
|
+
----
|
64
|
+
git clone https://github.com/fontist/extract_ttc
|
65
|
+
----
|
66
|
+
|
67
|
+
Setup your environment:
|
68
|
+
|
69
|
+
[source,sh]
|
70
|
+
----
|
71
|
+
bin/setup
|
72
|
+
----
|
73
|
+
|
74
|
+
Run the test suite:
|
75
|
+
|
76
|
+
[source,sh]
|
77
|
+
----
|
78
|
+
bundle exec rspec
|
79
|
+
----
|
80
|
+
|
81
|
+
If any changes are made in the C code, then the extension needs to be recompiled:
|
82
|
+
|
83
|
+
[source,sh]
|
84
|
+
----
|
85
|
+
bundle exec rake recompile
|
86
|
+
----
|
87
|
+
|
88
|
+
You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
89
|
+
|
90
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to https://rubygems.org[rubygems.org].
|
91
|
+
|
92
|
+
|
93
|
+
== Contributing
|
94
|
+
|
95
|
+
First, thank you for contributing! We love pull requests from everyone. By
|
96
|
+
participating in this project, you hereby grant https://www.ribose.com[Ribose Inc.] the
|
97
|
+
right to grant or transfer an unlimited number of non exclusive licenses or
|
98
|
+
sub-licenses to third parties, under the copyright covering the contribution
|
99
|
+
to use the contribution by all means.
|
100
|
+
|
101
|
+
Here are a few technical guidelines to follow:
|
102
|
+
|
103
|
+
1. Open an https://github.com/fontist/extract_ttc/issues[issue] to discuss a new feature.
|
104
|
+
1. Write tests to support your new feature.
|
105
|
+
1. Make sure the entire test suite passes locally and on CI.
|
106
|
+
1. Open a Pull Request.
|
107
|
+
1. https://github.com/thoughtbot/guides/tree/master/protocol/git#write-a-feature[Squash your commits]
|
108
|
+
after receiving feedback.
|
109
|
+
1. Party!
|
110
|
+
|
111
|
+
|
112
|
+
== License
|
113
|
+
|
114
|
+
This gem is distributed with a BSD 3-Clause license.
|
115
|
+
|
116
|
+
`stripttc.c` is obtained from:
|
117
|
+
https://github.com/fontforge/fontforge/blob/master/contrib/fonttools/stripttc.c
|
118
|
+
|
119
|
+
The BSD 3-Clause licence for `stripttc.c` is provided in `ext/stripttc/LICENSE`.
|
120
|
+
|
121
|
+
This gem is developed, maintained and funded by https://www.ribose.com/[Ribose Inc.]
|
data/Rakefile
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/clean"
|
3
|
+
require "rake/extensiontask"
|
4
|
+
require "rake_compiler_dock"
|
5
|
+
|
6
|
+
require "rubygems"
|
7
|
+
require "rubygems/package_task"
|
8
|
+
|
9
|
+
# ++ Allow rake-compiler-dock configuration without dev. dependencies
|
10
|
+
begin
|
11
|
+
require "rubocop/rake_task"
|
12
|
+
RuboCop::RakeTask.new
|
13
|
+
rescue LoadError
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
require "rspec/core/rake_task"
|
18
|
+
RSpec::Core::RakeTask.new(:spec)
|
19
|
+
rescue LoadError
|
20
|
+
end
|
21
|
+
# -- Allow rake-compiler-dock configuration without dev. dependencies
|
22
|
+
|
23
|
+
R_CC_V = "RUBY_CC_VERSION=3.1.0:3.0.0:2.7.0".freeze
|
24
|
+
bundler_ver = ENV["BUNDLER_VER"] || "2.3.22"
|
25
|
+
|
26
|
+
task default: :spec
|
27
|
+
task spec: :compile
|
28
|
+
|
29
|
+
spec = Gem::Specification.load("extract_ttc.gemspec")
|
30
|
+
|
31
|
+
ext_thru_rc_dock = %w[x86_64-linux aarch64-linux] +
|
32
|
+
%w[x64-mingw32 x64-mingw-ucrt x86_64-darwin arm64-darwin]
|
33
|
+
|
34
|
+
ext_thru_musl_cc = %w[x86_64-linux-musl aarch64-linux-musl]
|
35
|
+
|
36
|
+
# HACK: Prevent rake-compiler from overriding required_ruby_version,
|
37
|
+
# because the shared library here is Ruby-agnostic.
|
38
|
+
# See https://github.com/rake-compiler/rake-compiler/issues/153
|
39
|
+
module FixRequiredRubyVersion
|
40
|
+
def required_ruby_version=(*); end
|
41
|
+
end
|
42
|
+
Gem::Specification.prepend(FixRequiredRubyVersion)
|
43
|
+
|
44
|
+
exttask = Rake::ExtensionTask.new("stripttc", spec) do |ext|
|
45
|
+
ext.lib_dir = "lib"
|
46
|
+
ext.cross_compile = true
|
47
|
+
ext.cross_platform = ext_thru_rc_dock + ext_thru_musl_cc
|
48
|
+
ext.cross_compiling do |s|
|
49
|
+
s.files.reject! { |path| File.fnmatch?("ext/*", path) }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
namespace "gem" do
|
54
|
+
desc "Cache dependencies"
|
55
|
+
task "cache" do
|
56
|
+
sh <<~RCD
|
57
|
+
bundle config set cache_all true &&
|
58
|
+
bundle config set --local without 'development' &&
|
59
|
+
bundle package
|
60
|
+
RCD
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "build native gems with rake-compiler-dock"
|
64
|
+
task "native" => "cache" do
|
65
|
+
ext_thru_rc_dock.each do |plat|
|
66
|
+
RakeCompilerDock.sh <<~RCD, platform: plat
|
67
|
+
gem install bundler:#{bundler_ver} --no-document &&
|
68
|
+
bundle install --local &&
|
69
|
+
bundle exec rake native:#{plat} gem #{R_CC_V}
|
70
|
+
RCD
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
namespace "gem" do
|
76
|
+
ext_thru_rc_dock.each do |plat|
|
77
|
+
desc "Build native gems with rake-compiler-dock in parallel"
|
78
|
+
multitask "parallel" => plat
|
79
|
+
|
80
|
+
desc "Build the native gem for #{plat}"
|
81
|
+
task plat => "cache" do
|
82
|
+
RakeCompilerDock.sh <<~RCD, platform: plat
|
83
|
+
gem install bundler:#{bundler_ver} --no-document &&
|
84
|
+
bundle install --local &&
|
85
|
+
bundle exec rake native:#{plat} \
|
86
|
+
pkg/#{exttask.gem_spec.full_name}-#{plat}.gem \
|
87
|
+
#{R_CC_V}
|
88
|
+
RCD
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
ext_thru_musl_cc.each do |plat|
|
93
|
+
desc "Define the gem task to build on the #{plat} platform (binary gem)"
|
94
|
+
task plat do
|
95
|
+
s = spec.dup
|
96
|
+
s.platform = Gem::Platform.new(plat)
|
97
|
+
s.files += Dir.glob("lib/extract_ttc/*.{dll,so,dylib}")
|
98
|
+
s.extensions = []
|
99
|
+
|
100
|
+
task = Gem::PackageTask.new(s)
|
101
|
+
task.define
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
BSD 3-Clause License for stripttc.c
|
2
|
+
|
3
|
+
Copyright (c) George Williams and FontForge authors. All rights reserved.
|
4
|
+
https://github.com/fontforge/fontforge/blob/master/AUTHORS
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions
|
8
|
+
are met:
|
9
|
+
|
10
|
+
Redistributions of source code must retain the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
15
|
+
documentation and/or other materials provided with the distribution.
|
16
|
+
|
17
|
+
The name of the author may not be used to endorse or promote
|
18
|
+
products derived from this software without specific prior written
|
19
|
+
permission.
|
20
|
+
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS
|
22
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
23
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
24
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
25
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
26
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
27
|
+
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
28
|
+
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
29
|
+
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
30
|
+
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
31
|
+
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/ext/stripttc/extconf.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
-
require "mkmf"
|
2
1
|
require "rbconfig"
|
3
|
-
|
4
|
-
CONFIG["LDSHARED"] << " -shared" unless RbConfig::CONFIG["host_os"].match?(/darwin/)
|
5
|
-
|
2
|
+
require "mkmf"
|
6
3
|
create_makefile "stripttc"
|
4
|
+
m = File.read("Makefile").gsub("--no-as-needed", "--as-needed")
|
5
|
+
File.write("Makefile", m)
|
@@ -0,0 +1,187 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
#include <string.h>
|
4
|
+
#include <libgen.h>
|
5
|
+
|
6
|
+
/* This program takes a ttc file and turns it into its component ttf files */
|
7
|
+
/* This makes two changes to the data: */
|
8
|
+
/* * The tables are placed at different offsets, therefore */
|
9
|
+
/* the offset fields in the table header are also different. */
|
10
|
+
/* * the 'head' table checksumAdjustment field is set correctly */
|
11
|
+
|
12
|
+
#define CHR(ch1,ch2,ch3,ch4) (((ch1)<<24)|((ch2)<<16)|((ch3)<<8)|(ch4))
|
13
|
+
|
14
|
+
#ifdef _WIN32
|
15
|
+
#define EXPORT_API __declspec(dllexport)
|
16
|
+
#else
|
17
|
+
#define EXPORT_API
|
18
|
+
#endif
|
19
|
+
|
20
|
+
static void putshort(FILE *file,int sval) {
|
21
|
+
putc((sval>>8)&0xff,file);
|
22
|
+
putc(sval&0xff,file);
|
23
|
+
}
|
24
|
+
|
25
|
+
static void putlong(FILE *file,int val) {
|
26
|
+
putc((val>>24)&0xff,file);
|
27
|
+
putc((val>>16)&0xff,file);
|
28
|
+
putc((val>>8)&0xff,file);
|
29
|
+
putc(val&0xff,file);
|
30
|
+
}
|
31
|
+
|
32
|
+
static int getushort(FILE *ttf) {
|
33
|
+
int ch1 = getc(ttf);
|
34
|
+
int ch2 = getc(ttf);
|
35
|
+
if ( ch2==EOF )
|
36
|
+
return( EOF );
|
37
|
+
return( (ch1<<8)|ch2 );
|
38
|
+
}
|
39
|
+
|
40
|
+
static int getlong(FILE *ttf) {
|
41
|
+
int ch1 = getc(ttf);
|
42
|
+
int ch2 = getc(ttf);
|
43
|
+
int ch3 = getc(ttf);
|
44
|
+
int ch4 = getc(ttf);
|
45
|
+
if ( ch4==EOF )
|
46
|
+
return( EOF );
|
47
|
+
return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
|
48
|
+
}
|
49
|
+
|
50
|
+
static unsigned int filecheck(FILE *file) {
|
51
|
+
unsigned int sum = 0, chunk;
|
52
|
+
|
53
|
+
rewind(file);
|
54
|
+
while ( 1 ) {
|
55
|
+
chunk = getlong(file);
|
56
|
+
if ( feof(file) || ferror(file))
|
57
|
+
break;
|
58
|
+
sum += chunk;
|
59
|
+
}
|
60
|
+
return( sum );
|
61
|
+
}
|
62
|
+
|
63
|
+
static void copytable(FILE *ttf,FILE *ttc,int offset,int length) {
|
64
|
+
int i, ch;
|
65
|
+
|
66
|
+
fseek(ttc,offset,SEEK_SET);
|
67
|
+
for ( i=0; i<length && (ch=getc(ttc))!=EOF ; ++i )
|
68
|
+
putc(ch,ttf);
|
69
|
+
if ( ch==EOF )
|
70
|
+
fprintf( stderr, "File ended before table\n" );
|
71
|
+
if ( length&1 ) {
|
72
|
+
putc('\0',ttf);
|
73
|
+
++length;
|
74
|
+
}
|
75
|
+
if ( length & 2 ) {
|
76
|
+
putshort(ttf,0);
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
static int handlefont(char *filename,int which,FILE *ttc,int offset) {
|
81
|
+
char outfile[2000], *pt;
|
82
|
+
FILE *ttf;
|
83
|
+
int i, cnt, *offsets, *lengths, head, tag, pos, headpos;
|
84
|
+
strcpy(outfile,basename(filename));
|
85
|
+
pt = strrchr(outfile,'.');
|
86
|
+
if ( pt==NULL )
|
87
|
+
pt = outfile + strlen(outfile);
|
88
|
+
sprintf( pt, "_%02d.ttf", which );
|
89
|
+
|
90
|
+
ttf = fopen( outfile,"wb");
|
91
|
+
if ( ttf==NULL ) {
|
92
|
+
fprintf( stderr, "Failed to open %s for output.\n", outfile );
|
93
|
+
return( -3 );
|
94
|
+
}
|
95
|
+
printf ( "%s ", outfile );
|
96
|
+
|
97
|
+
fseek(ttc,offset,SEEK_SET);
|
98
|
+
putlong(ttf,getlong(ttc)); /* sfnt version */
|
99
|
+
putshort(ttf,cnt = getushort(ttc)); /* table cnt */
|
100
|
+
putshort(ttf,getushort(ttc)); /* binary search header */
|
101
|
+
putshort(ttf,getushort(ttc));
|
102
|
+
putshort(ttf,getushort(ttc));
|
103
|
+
|
104
|
+
offsets = malloc(cnt*sizeof(int));
|
105
|
+
lengths = malloc(cnt*sizeof(int));
|
106
|
+
head = -1;
|
107
|
+
for ( i=0; i<cnt; ++i ) {
|
108
|
+
tag = getlong(ttc);
|
109
|
+
if ( tag==CHR('h','e','a','d'))
|
110
|
+
head = i;
|
111
|
+
putlong(ttf,tag);
|
112
|
+
putlong(ttf,getlong(ttc)); /* checksum */
|
113
|
+
putlong(ttf,offsets[i] = getlong(ttc)); /* Reserve space for offset, will fix later */
|
114
|
+
putlong(ttf,lengths[i] = getlong(ttc));
|
115
|
+
}
|
116
|
+
headpos = -1;
|
117
|
+
for ( i=0; i<cnt; ++i ) {
|
118
|
+
pos = ftell(ttf);
|
119
|
+
copytable(ttf,ttc,offsets[i],lengths[i]);
|
120
|
+
if ( i==head ) {
|
121
|
+
fseek(ttf,pos+8,SEEK_SET);
|
122
|
+
putlong(ttf,0);
|
123
|
+
headpos = pos;
|
124
|
+
}
|
125
|
+
fseek(ttf,12+i*16+8,SEEK_SET);
|
126
|
+
putlong(ttf,pos); /* Fix offset here */
|
127
|
+
fseek(ttf,0,SEEK_END);
|
128
|
+
}
|
129
|
+
if ( headpos!=-1 ) {
|
130
|
+
unsigned int checksum;
|
131
|
+
checksum = filecheck(ttf);
|
132
|
+
checksum = 0xb1b0afba-checksum;
|
133
|
+
fseek(ttf,headpos+2*sizeof(int),SEEK_SET);
|
134
|
+
putlong(ttf,checksum);
|
135
|
+
}
|
136
|
+
fclose(ttf);
|
137
|
+
free(offsets); free(lengths);
|
138
|
+
return( 0 );
|
139
|
+
}
|
140
|
+
|
141
|
+
EXPORT_API int handlefile(char *filename) {
|
142
|
+
FILE *ttc = fopen(filename,"rb");
|
143
|
+
int version, cnt, e, i;
|
144
|
+
int *offsets;
|
145
|
+
|
146
|
+
if ( ttc==NULL ) {
|
147
|
+
fprintf( stderr, "Could not open %s\n", filename );
|
148
|
+
return( -1 );
|
149
|
+
}
|
150
|
+
|
151
|
+
version = getlong(ttc);
|
152
|
+
if ( version!=CHR('t','t','c','f')) {
|
153
|
+
fprintf( stderr, "%s does not look like a ttc file, bad version.\n", filename );
|
154
|
+
fclose(ttc);
|
155
|
+
return( -2 );
|
156
|
+
}
|
157
|
+
|
158
|
+
version = getlong(ttc);
|
159
|
+
if ( version!=0x10000 && version != 0x20000 )
|
160
|
+
fprintf( stderr, "Unexpected ttc version number: %08x\n", (unsigned int)(version) );
|
161
|
+
cnt = getlong(ttc);
|
162
|
+
offsets = malloc(cnt*sizeof(int));
|
163
|
+
for ( i=0; i<cnt; ++i )
|
164
|
+
offsets[i] = getlong(ttc);
|
165
|
+
printf( "%s => ", filename );
|
166
|
+
for ( i=0; i<cnt; ++i )
|
167
|
+
if ( (e = handlefont(filename,i,ttc,offsets[i])) ) {
|
168
|
+
fflush(stdout);
|
169
|
+
fclose(ttc);
|
170
|
+
free(offsets);
|
171
|
+
return( e );
|
172
|
+
};
|
173
|
+
printf( "\n" );
|
174
|
+
fflush(stdout);
|
175
|
+
fclose(ttc);
|
176
|
+
free(offsets);
|
177
|
+
return( 0 );
|
178
|
+
}
|
179
|
+
|
180
|
+
int main(int argc, char *argv[]) {
|
181
|
+
int e, i;
|
182
|
+
|
183
|
+
for ( i=1; i<argc; ++i )
|
184
|
+
if ( (e = handlefile(argv[i])) )
|
185
|
+
return( e );
|
186
|
+
return( 0 );
|
187
|
+
}
|
data/extract_ttc.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require_relative "lib/extract_ttc/version"
|
2
|
+
|
3
|
+
Gem::Specification.new do |spec|
|
4
|
+
spec.name = "extract_ttc"
|
5
|
+
spec.version = ExtractTtc::VERSION
|
6
|
+
spec.authors = ["Ribose Inc."]
|
7
|
+
spec.email = ["operations@ribose.com"]
|
8
|
+
|
9
|
+
spec.summary = "Extract TTC file to TTF files"
|
10
|
+
spec.description = "Extract font collection to separate font files"
|
11
|
+
spec.homepage = "https://github.com/fontist/extract_ttc"
|
12
|
+
spec.license = "BSD-3-Clause"
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0")
|
14
|
+
|
15
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
16
|
+
spec.metadata["source_code_uri"] = "https://github.com/fontist/extract_ttc"
|
17
|
+
spec.metadata["changelog_uri"] = "https://github.com/fontist/extract_ttc"
|
18
|
+
|
19
|
+
spec.files = Dir.chdir(__dir__) do
|
20
|
+
`git ls-files -z`
|
21
|
+
.split("\x0").reject { |f| f.match(%r{^(bin|.github|test|spec|features)/}) }
|
22
|
+
end
|
23
|
+
|
24
|
+
spec.bindir = "exe"
|
25
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_runtime_dependency "bundler", "~> 2.3", ">= 2.3.22"
|
29
|
+
spec.add_runtime_dependency "ffi", "~> 1.0"
|
30
|
+
spec.add_runtime_dependency "rake", "~> 13"
|
31
|
+
spec.add_runtime_dependency "rake-compiler", "~> 1.2"
|
32
|
+
spec.add_runtime_dependency "rake-compiler-dock", "~> 1.2"
|
33
|
+
|
34
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
35
|
+
spec.add_development_dependency "rubocop", "~> 1.5"
|
36
|
+
spec.add_development_dependency "rubocop-performance", "~> 1.10"
|
37
|
+
spec.add_development_dependency "rubocop-rails", "~> 2.9"
|
38
|
+
|
39
|
+
spec.extensions << "ext/stripttc/extconf.rb"
|
40
|
+
spec.metadata["rubygems_mfa_required"] = "false"
|
41
|
+
end
|
data/lib/extract_ttc.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require "extract_ttc/version"
|
2
|
+
require "ffi"
|
3
|
+
require "tempfile"
|
4
|
+
|
5
|
+
module ExtractTtc
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
class ReadFileError < Error; end
|
9
|
+
|
10
|
+
class InvalidFileError < Error; end
|
11
|
+
|
12
|
+
class WriteFileError < Error; end
|
13
|
+
|
14
|
+
class UnknownResultError < Error; end
|
15
|
+
|
16
|
+
extend FFI::Library
|
17
|
+
# NOTE: ffi doesn't support bundles out of box https://github.com/ffi/ffi/issues/42#issuecomment-750031554
|
18
|
+
# NOTE: rake-compiler doesn't support dylib generation https://github.com/rake-compiler/rake-compiler/issues/183
|
19
|
+
lib_name = if File.exists?(File.join(File.dirname(__FILE__),
|
20
|
+
"stripttc.bundle"))
|
21
|
+
"stripttc.bundle"
|
22
|
+
else
|
23
|
+
"stripttc.so"
|
24
|
+
end
|
25
|
+
ffi_lib File.join(File.dirname(__FILE__), lib_name)
|
26
|
+
attach_function :handlefile, [:string], :int
|
27
|
+
|
28
|
+
def self.extract(path)
|
29
|
+
stdout, stderr, code = capture3 do
|
30
|
+
handlefile(path)
|
31
|
+
end
|
32
|
+
|
33
|
+
return handle_error(code, stderr) unless code.zero?
|
34
|
+
|
35
|
+
fetch_filenames(stdout)
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.handle_error(code, stderr)
|
39
|
+
case code
|
40
|
+
when -1
|
41
|
+
raise ReadFileError, stderr
|
42
|
+
when -2
|
43
|
+
raise InvalidFileError, stderr
|
44
|
+
when -3
|
45
|
+
raise WriteFileError, stderr
|
46
|
+
else
|
47
|
+
raise UnknownResultError, "Return code: #{code}"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.capture3
|
52
|
+
stderr = status = nil
|
53
|
+
|
54
|
+
stdout = capture_stream($stdout) do
|
55
|
+
stderr = capture_stream($stderr) do
|
56
|
+
status = yield
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
[stdout, stderr, status]
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.capture_stream(stream_io)
|
64
|
+
origin_stream = stream_io.dup
|
65
|
+
|
66
|
+
Tempfile.open("captured_stream") do |captured_stream|
|
67
|
+
stream_io.reopen(captured_stream)
|
68
|
+
yield
|
69
|
+
captured_stream.rewind
|
70
|
+
return captured_stream.read
|
71
|
+
end
|
72
|
+
ensure
|
73
|
+
stream_io.reopen(origin_stream)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.fetch_filenames(stdout)
|
77
|
+
stdout.split("=>").last.split
|
78
|
+
end
|
79
|
+
end
|
metadata
CHANGED
@@ -1,49 +1,49 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extract_ttc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.3'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.3.22
|
20
23
|
type: :runtime
|
21
24
|
prerelease: false
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
23
26
|
requirements:
|
24
27
|
- - "~>"
|
25
28
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
29
|
+
version: '2.3'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.3.22
|
27
33
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
34
|
+
name: ffi
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
30
36
|
requirements:
|
31
37
|
- - "~>"
|
32
38
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
- - ">="
|
35
|
-
- !ruby/object:Gem::Version
|
36
|
-
version: 2.3.22
|
39
|
+
version: '1.0'
|
37
40
|
type: :runtime
|
38
41
|
prerelease: false
|
39
42
|
version_requirements: !ruby/object:Gem::Requirement
|
40
43
|
requirements:
|
41
44
|
- - "~>"
|
42
45
|
- !ruby/object:Gem::Version
|
43
|
-
version: '
|
44
|
-
- - ">="
|
45
|
-
- !ruby/object:Gem::Version
|
46
|
-
version: 2.3.22
|
46
|
+
version: '1.0'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rake
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,7 +150,20 @@ extensions:
|
|
150
150
|
- ext/stripttc/extconf.rb
|
151
151
|
extra_rdoc_files: []
|
152
152
|
files:
|
153
|
+
- ".gitignore"
|
154
|
+
- ".rspec"
|
155
|
+
- ".rubocop.yml"
|
156
|
+
- Gemfile
|
157
|
+
- LICENSE.adoc
|
158
|
+
- README.adoc
|
159
|
+
- Rakefile
|
160
|
+
- ext/stripttc/LICENSE
|
161
|
+
- ext/stripttc/dummy.c
|
153
162
|
- ext/stripttc/extconf.rb
|
163
|
+
- ext/stripttc/stripttc.c
|
164
|
+
- extract_ttc.gemspec
|
165
|
+
- lib/extract_ttc.rb
|
166
|
+
- lib/extract_ttc/version.rb
|
154
167
|
homepage: https://github.com/fontist/extract_ttc
|
155
168
|
licenses:
|
156
169
|
- BSD-3-Clause
|
@@ -159,7 +172,7 @@ metadata:
|
|
159
172
|
source_code_uri: https://github.com/fontist/extract_ttc
|
160
173
|
changelog_uri: https://github.com/fontist/extract_ttc
|
161
174
|
rubygems_mfa_required: 'false'
|
162
|
-
post_install_message:
|
175
|
+
post_install_message:
|
163
176
|
rdoc_options: []
|
164
177
|
require_paths:
|
165
178
|
- lib
|
@@ -167,7 +180,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
167
180
|
requirements:
|
168
181
|
- - ">="
|
169
182
|
- !ruby/object:Gem::Version
|
170
|
-
version: 2.
|
183
|
+
version: 2.7.0
|
171
184
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
172
185
|
requirements:
|
173
186
|
- - ">="
|
@@ -175,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
188
|
version: '0'
|
176
189
|
requirements: []
|
177
190
|
rubygems_version: 3.3.7
|
178
|
-
signing_key:
|
191
|
+
signing_key:
|
179
192
|
specification_version: 4
|
180
193
|
summary: Extract TTC file to TTF files
|
181
194
|
test_files: []
|