• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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