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: 29 explicit HexTo(const char* in) { 30 std::stringstream ss; 31 ss << std::hex << in; 32 ss >> value_; 33 } 34 operator T() const { return value_; } 35 36 private: 37 T value_; 38 }; 39 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 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 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 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