130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/* 230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved. 330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License"); 530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License. 630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at 730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * http://www.apache.org/licenses/LICENSE-2.0 930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software 1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS, 1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and 1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License. 1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */ 1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <stdio.h> 1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <vector> 2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <string> 2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <sstream> 2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/type.h" 2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "font_subsetter.h" 2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Guruntemplate <typename T> 2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunclass HexTo { 2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun public: 2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun explicit HexTo(const char* in) { 3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun std::stringstream ss; 3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ss << std::hex << in; 3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ss >> value_; 3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun operator T() const { return value_; } 3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun private: 3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun T value_; 3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}; 3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool LoadFile(const char* input_file_path, sfntly::ByteVector* input_buffer) { 4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(input_file_path); 4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(input_buffer); 4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FILE* input_file = NULL; 4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined WIN32 4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fopen_s(&input_file, input_file_path, "rb"); 4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else 4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun input_file = fopen(input_file_path, "rb"); 4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (input_file == NULL) { 5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(input_file, 0, SEEK_END); 5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t file_size = ftell(input_file); 5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fseek(input_file, 0, SEEK_SET); 5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun input_buffer->resize(file_size); 5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t bytes_read = fread(&((*input_buffer)[0]), 1, file_size, input_file); 5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fclose(input_file); 5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return bytes_read == file_size; 6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool SaveFile(const char* output_file_path, const unsigned char* output_buffer, 6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int buffer_length) { 6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int byte_count = 0; 6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (buffer_length > 0) { 6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FILE* output_file = NULL; 6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined WIN32 6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fopen_s(&output_file, output_file_path, "wb"); 6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else 7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun output_file = fopen(output_file_path, "wb"); 7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (output_file) { 7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun byte_count = fwrite(output_buffer, 1, buffer_length, output_file); 7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fflush(output_file); 7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fclose(output_file); 7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return buffer_length == byte_count; 7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool StringToGlyphId(const char* input, std::vector<unsigned int>* glyph_ids) { 8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(input); 8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun std::string hex_csv = input; 8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t start = 0; 8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t end = hex_csv.find_first_of(","); 8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun while (end != std::string::npos) { 8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_ids->push_back( 8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun HexTo<unsigned int>(hex_csv.substr(start, end - start).c_str())); 9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun start = end + 1; 9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun end = hex_csv.find_first_of(",", start); 9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_ids->push_back(HexTo<unsigned int>(hex_csv.substr(start).c_str())); 9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return glyph_ids->size() > 0; 9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint main(int argc, char** argv) { 9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (argc < 5) { 9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, 10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun "Usage: %s <input path> <output path> <font name> <glyph ids>\n", 10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun argv[0]); 10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "\tGlyph ids are comma separated hex values\n"); 10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "\te.g. 20,1a,3b,4f\n"); 10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun sfntly::ByteVector input_buffer; 10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!LoadFile(argv[1], &input_buffer)) { 10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "ERROR: unable to load font file %s\n", argv[1]); 11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun std::vector<unsigned int> glyph_ids; 11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!StringToGlyphId(argv[4], &glyph_ids)) { 11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "ERROR: unable to parse input glyph id\n"); 11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun unsigned char* output_buffer = NULL; 12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int output_length = 12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun SfntlyWrapper::SubsetFont(argv[3], 12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun &(input_buffer[0]), 12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun input_buffer.size(), 12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun &(glyph_ids[0]), 12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_ids.size(), 12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun &output_buffer); 12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int result = SaveFile(argv[2], output_buffer, output_length) ? 1 : 0; 12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete[] output_buffer; 13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return result; 13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 132