1 /*
2 * Copyright 2011 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18
19 #include <vector>
20 #include <string>
21 #include <sstream>
22
23 #include "sfntly/port/type.h"
24 #include "font_subsetter.h"
25
26 template <typename T>
27 class HexTo {
28 public:
HexTo(const char * in)29 explicit HexTo(const char* in) {
30 std::stringstream ss;
31 ss << std::hex << in;
32 ss >> value_;
33 }
operator T() const34 operator T() const { return value_; }
35
36 private:
37 T value_;
38 };
39
LoadFile(const char * input_file_path,sfntly::ByteVector * input_buffer)40 bool LoadFile(const char* input_file_path, sfntly::ByteVector* input_buffer) {
41 assert(input_file_path);
42 assert(input_buffer);
43
44 FILE* input_file = NULL;
45 #if defined WIN32
46 fopen_s(&input_file, input_file_path, "rb");
47 #else
48 input_file = fopen(input_file_path, "rb");
49 #endif
50 if (input_file == NULL) {
51 return false;
52 }
53 fseek(input_file, 0, SEEK_END);
54 size_t file_size = ftell(input_file);
55 fseek(input_file, 0, SEEK_SET);
56 input_buffer->resize(file_size);
57 size_t bytes_read = fread(&((*input_buffer)[0]), 1, file_size, input_file);
58 fclose(input_file);
59 return bytes_read == file_size;
60 }
61
SaveFile(const char * output_file_path,const unsigned char * output_buffer,int buffer_length)62 bool SaveFile(const char* output_file_path, const unsigned char* output_buffer,
63 int buffer_length) {
64 int byte_count = 0;
65 if (buffer_length > 0) {
66 FILE* output_file = NULL;
67 #if defined WIN32
68 fopen_s(&output_file, output_file_path, "wb");
69 #else
70 output_file = fopen(output_file_path, "wb");
71 #endif
72 if (output_file) {
73 byte_count = fwrite(output_buffer, 1, buffer_length, output_file);
74 fflush(output_file);
75 fclose(output_file);
76 }
77 return buffer_length == byte_count;
78 }
79 return false;
80 }
81
StringToGlyphId(const char * input,std::vector<unsigned int> * glyph_ids)82 bool StringToGlyphId(const char* input, std::vector<unsigned int>* glyph_ids) {
83 assert(input);
84 std::string hex_csv = input;
85 size_t start = 0;
86 size_t end = hex_csv.find_first_of(",");
87 while (end != std::string::npos) {
88 glyph_ids->push_back(
89 HexTo<unsigned int>(hex_csv.substr(start, end - start).c_str()));
90 start = end + 1;
91 end = hex_csv.find_first_of(",", start);
92 }
93 glyph_ids->push_back(HexTo<unsigned int>(hex_csv.substr(start).c_str()));
94 return glyph_ids->size() > 0;
95 }
96
main(int argc,char ** argv)97 int main(int argc, char** argv) {
98 if (argc < 5) {
99 fprintf(stderr,
100 "Usage: %s <input path> <output path> <font name> <glyph ids>\n",
101 argv[0]);
102 fprintf(stderr, "\tGlyph ids are comma separated hex values\n");
103 fprintf(stderr, "\te.g. 20,1a,3b,4f\n");
104 return 0;
105 }
106
107 sfntly::ByteVector input_buffer;
108 if (!LoadFile(argv[1], &input_buffer)) {
109 fprintf(stderr, "ERROR: unable to load font file %s\n", argv[1]);
110 return 0;
111 }
112
113 std::vector<unsigned int> glyph_ids;
114 if (!StringToGlyphId(argv[4], &glyph_ids)) {
115 fprintf(stderr, "ERROR: unable to parse input glyph id\n");
116 return 0;
117 }
118
119 unsigned char* output_buffer = NULL;
120 int output_length =
121 SfntlyWrapper::SubsetFont(argv[3],
122 &(input_buffer[0]),
123 input_buffer.size(),
124 &(glyph_ids[0]),
125 glyph_ids.size(),
126 &output_buffer);
127
128 int result = SaveFile(argv[2], output_buffer, output_length) ? 1 : 0;
129 delete[] output_buffer;
130 return result;
131 }
132