16263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Copyright (c) 2010 The Chromium Authors. All rights reserved. 26263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Use of this source code is governed by a BSD-style license that can be 36263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// found in the LICENSE file. 46263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 56263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// A parser for the Type 2 Charstring Format. 66263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// http://www.adobe.com/devnet/font/pdfs/5177.Type2.pdf 76263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 86263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org#include "cff_type2_charstring.h" 96263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 10fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org#include <climits> 116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org#include <cstdio> 126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org#include <cstring> 136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org#include <stack> 146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org#include <string> 156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org#include <utility> 166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgnamespace { 186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical 206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Note #5177. 21fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.orgconst int32_t kMaxSubrsCount = 65536; 226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgconst size_t kMaxCharStringLength = 65535; 236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgconst size_t kMaxArgumentStack = 48; 246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgconst size_t kMaxNumberOfStemHints = 96; 256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgconst size_t kMaxSubrNesting = 10; 266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 27fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org// |dummy_result| should be a huge positive integer so callsubr and callgsubr 28fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org// will fail with the dummy value. 29fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.orgconst int32_t dummy_result = INT_MAX; 30fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org 316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgbool ExecuteType2CharString(size_t call_depth, 326263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& global_subrs_index, 336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& local_subrs_index, 346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer *cff_table, 356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer *char_string, 366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::stack<int32_t> *argument_stack, 376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *out_found_endchar, 386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *out_found_width, 396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org size_t *in_out_num_stems); 406263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 416263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Read one or more bytes from the |char_string| buffer and stores the number 426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// read on |out_number|. If the number read is an operator (ex 'vstem'), sets 436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// true on |out_is_operator|. Returns true if the function read a number. 446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgbool ReadNextNumberFromType2CharString(ots::Buffer *char_string, 456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org int32_t *out_number, 466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *out_is_operator) { 476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org uint8_t v = 0; 486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->ReadU8(&v)) { 496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_is_operator = false; 526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // The conversion algorithm is described in Adobe Technical Note #5177, page 546263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // 13, Table 1. 556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (v <= 11) { 566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = v; 576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_is_operator = true; 586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v == 12) { 596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org uint16_t result = (v << 8); 606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->ReadU8(&v)) { 616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org result += v; 646263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = result; 656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_is_operator = true; 666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v <= 27) { 676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Special handling for v==19 and v==20 are implemented in 686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // ExecuteType2CharStringOperator(). 696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = v; 706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_is_operator = true; 716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v == 28) { 726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->ReadU8(&v)) { 736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 756263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org uint16_t result = (v << 8); 766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->ReadU8(&v)) { 776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org result += v; 806263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = result; 816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v <= 31) { 826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = v; 836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_is_operator = true; 846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v <= 246) { 856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = static_cast<int32_t>(v) - 139; 866263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v <= 250) { 876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org uint8_t w = 0; 886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->ReadU8(&w)) { 896263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 916263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = ((static_cast<int32_t>(v) - 247) * 256) + 926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org static_cast<int32_t>(w) + 108; 936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v <= 254) { 946263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org uint8_t w = 0; 956263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->ReadU8(&w)) { 966263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 976263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_number = -((static_cast<int32_t>(v) - 251) * 256) - 996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org static_cast<int32_t>(w) - 108; 1006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (v == 255) { 101fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org // TODO(yusukes): We should not skip the 4 bytes. Note that when v is 255, 102fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org // we should treat the following 4-bytes as a 16.16 fixed-point number 1036263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // rather than 32bit signed int. 104fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org if (!char_string->Skip(4)) { 105fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org return OTS_FAILURE(); 106fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org } 107fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org *out_number = dummy_result; 1086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else { 1096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 1106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 1136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} 1146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Executes |op| and updates |argument_stack|. Returns true if the execution 1166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively 1176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// calls ExecuteType2CharString() function. The arguments other than |op| and 1186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// |argument_stack| are passed for that reason. 1196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgbool ExecuteType2CharStringOperator(int32_t op, 1206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org size_t call_depth, 1216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& global_subrs_index, 1226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& local_subrs_index, 1236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer *cff_table, 1246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer *char_string, 1256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::stack<int32_t> *argument_stack, 1266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *out_found_endchar, 1276263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *in_out_found_width, 1286263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org size_t *in_out_num_stems) { 1296263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t stack_size = argument_stack->size(); 1306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org switch (op) { 132fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kCallSubr: 133fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kCallGSubr: { 1346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& subrs_index = 135fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org (op == ots::kCallSubr ? local_subrs_index : global_subrs_index); 1366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 1) { 1386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 1396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1406263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org int32_t subr_number = argument_stack->top(); 1416263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 1426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (subr_number == dummy_result) { 1436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // For safety, we allow subr calls only with immediate subr numbers for 1446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // now. For example, we allow "123 callgsubr", but does not allow "100 12 1456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // add callgsubr". Please note that arithmetic and conditional operators 1466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // always push the |dummy_result| in this implementation. 1476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 1486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // See Adobe Technical Note #5176 (CFF), "16. Local/GlobalSubrs INDEXes." 1516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org int32_t bias = 32768; 1526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (subrs_index.count < 1240) { 1536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bias = 107; 1546263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (subrs_index.count < 33900) { 1556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bias = 1131; 1566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org subr_number += bias; 1586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Sanity checks of |subr_number|. 1606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (subr_number < 0) { 1616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 1626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 163fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org if (subr_number >= kMaxSubrsCount) { 164fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org return OTS_FAILURE(); 165fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org } 166fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org if (subrs_index.offsets.size() <= static_cast<size_t>(subr_number + 1)) { 1676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); // The number is out-of-bounds. 1686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Prepare ots::Buffer where we're going to jump. 1716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t length = 1726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org subrs_index.offsets[subr_number + 1] - subrs_index.offsets[subr_number]; 1736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (length > kMaxCharStringLength) { 1746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 1756263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t offset = subrs_index.offsets[subr_number]; 1776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org cff_table->set_offset(offset); 1786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!cff_table->Skip(length)) { 1796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 1806263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length); 1826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 1836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return ExecuteType2CharString(call_depth + 1, 1846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org global_subrs_index, 1856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org local_subrs_index, 1866263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org cff_table, 1876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org &char_string_to_jump, 1886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack, 1896263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org out_found_endchar, 1906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org in_out_found_width, 1916263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org in_out_num_stems); 1926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 1936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 194fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kReturn: 1956263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 1966263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 197fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kEndChar: 1986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_found_endchar = true; 1996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *in_out_found_width = true; // just in case. 2006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 2016263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 202fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHStem: 203fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kVStem: 204fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHStemHm: 205fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kVStemHm: { 2066263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool successful = false; 2076263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 2) { 2086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((stack_size % 2) == 0) { 2116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((!(*in_out_found_width)) && (((stack_size - 1) % 2) == 0)) { 2136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // The -1 is for "width" argument. For details, see Adobe Technical Note 2146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // #5177, page 16, note 4. 2156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org (*in_out_num_stems) += (stack_size / 2); 2186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((*in_out_num_stems) > kMaxNumberOfStemHints) { 2196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 2226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 2236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *in_out_found_width = true; // always set true since "w" might be 0 byte. 2246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return successful ? true : OTS_FAILURE(); 2256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 227fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRMoveTo: { 2286263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool successful = false; 2296263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size == 2) { 2306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((!(*in_out_found_width)) && (stack_size - 1 == 2)) { 2326263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 2356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 2366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *in_out_found_width = true; 2376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return successful ? true : OTS_FAILURE(); 2386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 240fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kVMoveTo: 241fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHMoveTo: { 2426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool successful = false; 2436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size == 1) { 2446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((!(*in_out_found_width)) && (stack_size - 1 == 1)) { 2466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 2496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 2506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *in_out_found_width = true; 2516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return successful ? true : OTS_FAILURE(); 2526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 254fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHintMask: 255fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kCntrMask: { 2566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool successful = false; 2576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size == 0) { 2586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((!(*in_out_found_width)) && (stack_size == 1)) { 2606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // A number for "width" is found. 2616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((!(*in_out_found_width)) || // in this case, any sizes are ok. 2636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ((stack_size % 2) == 0)) { 2646263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // The numbers are vstem definition. 2656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // See Adobe Technical Note #5177, page 24, hintmask. 2666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org (*in_out_num_stems) += (stack_size / 2); 2676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((*in_out_num_stems) > kMaxNumberOfStemHints) { 2686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 2716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!successful) { 2736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2756263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 2766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((*in_out_num_stems) == 0) { 2776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t mask_bytes = (*in_out_num_stems + 7) / 8; 2806263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!char_string->Skip(mask_bytes)) { 2816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 2846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 2856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *in_out_found_width = true; 2866263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 2876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 289fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRLineTo: 2906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 2916263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // The first stack-clearing operator should be one of hstem, hstemhm, 2926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, rmoveto, or 2936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // endchar. For details, see Adobe Technical Note #5177, page 16, note 4. 2946263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2956263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2966263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 2) { 2976263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 2986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 2996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((stack_size % 2) != 0) { 3006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3016263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3026263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3036263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3046263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 3056263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 306fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHLineTo: 307fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kVLineTo: 3086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 1) { 3126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 3176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 318fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRRCurveTo: 3196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 6) { 3236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((stack_size % 6) != 0) { 3266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3276263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3286263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3296263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 3316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 332fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRCurveLine: 3336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 8) { 3376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (((stack_size - 2) % 6) != 0) { 3406263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3416263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 3456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 346fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRLineCurve: 3476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 8) { 3516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (((stack_size - 6) % 2) != 0) { 3546263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 3596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 360fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kVVCurveTo: 3616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3646263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 4) { 3656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (((stack_size % 4) != 0) && 3686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org (((stack_size - 1) % 4) != 0)) { 3696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 3746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 375fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHHCurveTo: { 3766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool successful = false; 3776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3806263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 4) { 3816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 3826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((stack_size % 4) == 0) { 3846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // {dxa dxb dyb dxc}+ 3856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 3866263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (((stack_size - 1) % 4) == 0) { 3876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // dy1? {dxa dxb dyb dxc}+ 3886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 3896263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 3916263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 3926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return successful ? true : OTS_FAILURE(); 3936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 3946263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 395fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kVHCurveTo: 396fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHVCurveTo: { 3976263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool successful = false; 3986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 3996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4016263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 4) { 4026263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4036263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4046263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (((stack_size - 4) % 8) == 0) { 4056263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* 4066263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 4076263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((stack_size >= 5) && 4086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ((stack_size - 5) % 8) == 0) { 4096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // dx1 dx2 dy2 dy3 {dya dxb dyb dxc dxd dxe dye dyf}* dxf 4106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 4116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((stack_size >= 8) && 4126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ((stack_size - 8) % 8) == 0) { 4136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // {dxa dxb dyb dyc dyd dxe dye dxf}+ 4146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 4156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if ((stack_size >= 9) && 4166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ((stack_size - 9) % 8) == 0) { 4176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // {dxa dxb dyb dyc dyd dxe dye dxf}+ dyf? 4186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org successful = true; 4196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 4216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return successful ? true : OTS_FAILURE(); 4236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 425fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kAnd: 426fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kOr: 427fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kEq: 428fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kAdd: 429fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kSub: 4306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 2) { 4316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4326263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 4366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 4376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 4386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 4396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 440fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kNot: 441fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kAbs: 442fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kNeg: 4436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 1) { 4446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 4486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 4496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 4506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 4516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 452fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kDiv: 4536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Should detect div-by-zero errors. 454fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org if (stack_size < 2) { 4556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 458fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org argument_stack->pop(); 4596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 4606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 4616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 4626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 4636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 464fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kDrop: 4656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 1) { 4666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 4706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 471fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kPut: 472fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kGet: 473fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kIndex: 4746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // For now, just call OTS_FAILURE since there is no way to check whether the 4756263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // index argument, |i|, is out-of-bounds or not. Fortunately, no OpenType 4766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // fonts I have (except malicious ones!) use the operators. 4776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement them in a secure way. 4786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 480fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRoll: 4816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Likewise, just call OTS_FAILURE for kRoll since there is no way to check 4826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // whether |N| is smaller than the current stack depth or not. 4836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement them in a secure way. 4846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 486fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kRandom: 4876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // For now, we don't handle the 'random' operator since the operator makes 4886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // it hard to analyze hinting code statically. 4896263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 491fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kIfElse: 4926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 4) { 4936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 4946263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 4956263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4966263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4976263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 4996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 5016263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 5026263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5036263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 504fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kMul: 5056263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Should detect overflows. 5066263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 2) { 5076263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 5136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 5146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 516fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kSqrt: 5176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Should check if the argument is negative. 5186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 1) { 5196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 5246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 5256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 527fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kDup: 5286263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 1) { 5296263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5326263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (argument_stack->size() > kMaxArgumentStack) { 5356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 5386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 5396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5406263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 541fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kExch: 5426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size < 2) { 5436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(dummy_result); 5496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // TODO(yusukes): Implement this. We should push a real value for all 5506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // arithmetic and conditional operations. 5516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 553fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHFlex: 5546263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 5556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size != 7) { 5586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 5616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 564fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kFlex: 5656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 5666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size != 13) { 5696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 5726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 575fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kHFlex1: 5766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 5776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size != 9) { 5806263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 5836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 586fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org case ots::kFlex1: 5876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!(*in_out_found_width)) { 5886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5896263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (stack_size != 11) { 5916263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 5926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (!argument_stack->empty()) 5946263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->pop(); 5956263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 5966263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 5976263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 5986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org OTS_WARNING("Undefined operator: %d (0x%x)", op, op); 5996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 6006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} 6016263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6026263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Executes |char_string| and updates |argument_stack|. 6036263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// 6046263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// call_depth: The current call depth. Initial value is zero. 6056263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// global_subrs_index: Global subroutines. 6066263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// local_subrs_index: Local subroutines for the current glyph. 6076263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// cff_table: A whole CFF table which contains all global and local subroutines. 6086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// char_string: A charstring we'll execute. |char_string| can be a main routine 6096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// in CharString INDEX, or a subroutine in GlobalSubr/LocalSubr. 6106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// argument_stack: The stack which an operator in |char_string| operates. 6116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// out_found_endchar: true is set if |char_string| contains 'endchar'. 6126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// in_out_found_width: true is set if |char_string| contains 'width' byte (which 6136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// is 0 or 1 byte.) 6146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// in_out_num_stems: total number of hstems and vstems processed so far. 6156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgbool ExecuteType2CharString(size_t call_depth, 6166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& global_subrs_index, 6176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex& local_subrs_index, 6186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer *cff_table, 6196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org ots::Buffer *char_string, 6206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::stack<int32_t> *argument_stack, 6216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *out_found_endchar, 6226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool *in_out_found_width, 6236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org size_t *in_out_num_stems) { 6246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (call_depth > kMaxSubrNesting) { 6256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 6266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6276263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_found_endchar = false; 6286263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6296263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t length = char_string->length(); 6306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org while (char_string->offset() < length) { 6316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org int32_t operator_or_operand = 0; 6326263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool is_operator = false; 6336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!ReadNextNumberFromType2CharString(char_string, 6346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org &operator_or_operand, 6356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org &is_operator)) { 6366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 6376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org /* 6406263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org You can dump all operators and operands (except mask bytes for hintmask 6416263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org and cntrmask) by the following code: 6426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!is_operator) { 6446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::fprintf(stderr, "#%d# ", operator_or_operand); 6456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else { 6466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::fprintf(stderr, "#%s#\n", 6476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org Type2CharStringOperatorToString( 6486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org Type2CharStringOperator(operator_or_operand)), 6496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org operator_or_operand); 6506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org */ 6526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!is_operator) { 6546263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack->push(operator_or_operand); 6556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (argument_stack->size() > kMaxArgumentStack) { 6566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 6576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org continue; 6596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // An operator is found. Execute it. 6626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!ExecuteType2CharStringOperator(operator_or_operand, 6636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org call_depth, 6646263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org global_subrs_index, 6656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org local_subrs_index, 6666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org cff_table, 6676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org char_string, 6686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org argument_stack, 6696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org out_found_endchar, 6706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org in_out_found_width, 6716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org in_out_num_stems)) { 6726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 6736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (*out_found_endchar) { 6756263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 6766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 677fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org if (operator_or_operand == ots::kReturn) { 6786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 6796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6806263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 6816263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6826263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // No endchar operator is found. 6836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 6846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} 6856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6866263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// Selects a set of subroutings for |glyph_index| from |cff| and sets it on 6876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org// |out_local_subrs_to_use|. Returns true on success. 6886263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgbool SelectLocalSubr(const std::map<uint16_t, uint8_t> &fd_select, 6896263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const std::vector<ots::CFFIndex *> &local_subrs_per_font, 6906263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex *local_subrs, 6916263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org uint16_t glyph_index, // 0-origin 6926263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const ots::CFFIndex **out_local_subrs_to_use) { 6936263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_local_subrs_to_use = NULL; 6946263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 6956263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // First, find local subrs from |local_subrs_per_font|. 6966263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if ((fd_select.size() > 0) && 6976263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org (!local_subrs_per_font.empty())) { 6986263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Look up FDArray index for the glyph. 6996263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::map<uint16_t, uint8_t>::const_iterator iter = 7006263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org fd_select.find(glyph_index); 7016263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (iter == fd_select.end()) { 7026263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 7036263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7046263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const uint8_t fd_index = iter->second; 7056263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (fd_index >= local_subrs_per_font.size()) { 7066263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 7076263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7086263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_local_subrs_to_use = local_subrs_per_font.at(fd_index); 7096263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else if (local_subrs) { 7106263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Second, try to use |local_subrs|. Most Latin fonts don't have FDSelect 7116263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // entries. If The font has a local subrs index associated with the Top 7126263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // DICT (not FDArrays), use it. 7136263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_local_subrs_to_use = local_subrs; 7146263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } else { 7156263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Just return NULL. 7166263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org *out_local_subrs_to_use = NULL; 7176263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7186263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7196263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 7206263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} 7216263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7226263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} // namespace 7236263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7246263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgnamespace ots { 7256263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7266263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.orgbool ValidateType2CharStringIndex( 7276263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const CFFIndex& char_strings_index, 7286263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const CFFIndex& global_subrs_index, 7296263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const std::map<uint16_t, uint8_t> &fd_select, 7306263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const std::vector<CFFIndex *> &local_subrs_per_font, 7316263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const CFFIndex *local_subrs, 7326263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org Buffer* cff_table) { 7336263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (char_strings_index.offsets.size() == 0) { 7346263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); // no charstring. 7356263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7366263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7376263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // For each glyph, validate the corresponding charstring. 7386263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org for (unsigned i = 1; i < char_strings_index.offsets.size(); ++i) { 7396263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Prepare a Buffer object, |char_string|, which contains the charstring 7406263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // for the |i|-th glyph. 7416263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t length = 7426263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org char_strings_index.offsets[i] - char_strings_index.offsets[i - 1]; 7436263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (length > kMaxCharStringLength) { 7446263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 7456263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7466263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const size_t offset = char_strings_index.offsets[i - 1]; 7476263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org cff_table->set_offset(offset); 7486263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!cff_table->Skip(length)) { 7496263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 7506263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7516263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org Buffer char_string(cff_table->buffer() + offset, length); 7526263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7536263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Get a local subrs for the glyph. 7546263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const unsigned glyph_index = i - 1; // index in the map is 0-origin. 7556263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org const CFFIndex *local_subrs_to_use = NULL; 7566263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!SelectLocalSubr(fd_select, 7576263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org local_subrs_per_font, 7586263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org local_subrs, 7596263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org glyph_index, 7606263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org &local_subrs_to_use)) { 7616263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 7626263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7636263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // If |local_subrs_to_use| is still NULL, use an empty one. 7646263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org CFFIndex default_empty_subrs; 7656263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!local_subrs_to_use){ 7666263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org local_subrs_to_use = &default_empty_subrs; 7676263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7686263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7696263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org // Check a charstring for the |i|-th glyph. 7706263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org std::stack<int32_t> argument_stack; 7716263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool found_endchar = false; 7726263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org bool found_width = false; 7736263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org size_t num_stems = 0; 7746263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org if (!ExecuteType2CharString(0 /* initial call_depth is zero */, 7756263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org global_subrs_index, *local_subrs_to_use, 7766263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org cff_table, &char_string, &argument_stack, 7776263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org &found_endchar, &found_width, &num_stems)) { 7786263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return OTS_FAILURE(); 7796263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 780fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org if (!found_endchar) { 781fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org return OTS_FAILURE(); 782fbb12969b4421ce7a155b7b34a7d855580d0f669yusukes@chromium.org } 7836263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org } 7846263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org return true; 7856263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} 7866263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org 7876263d06109011f6cff761aed14ded117c8fa1836yusukes@chromium.org} // namespace ots 788