| Index: src/cff_type2_charstring.cc
|
| diff --git a/src/cff_type2_charstring.cc b/src/cff_type2_charstring.cc
|
| old mode 100644
|
| new mode 100755
|
| index 2817d8073db44f054a4915b32f9a124f1c4b72e7..6dd47664d09128a1dfcbe7a92921e37e97d1cac6
|
| --- a/src/cff_type2_charstring.cc
|
| +++ b/src/cff_type2_charstring.cc
|
| @@ -14,6 +14,8 @@
|
| #include <string>
|
| #include <utility>
|
|
|
| +#define TABLE_NAME "CFF"
|
| +
|
| namespace {
|
|
|
| // Type 2 Charstring Implementation Limits. See Appendix. B in Adobe Technical
|
| @@ -28,7 +30,8 @@ const size_t kMaxSubrNesting = 10;
|
| // will fail with the dummy value.
|
| const int32_t dummy_result = INT_MAX;
|
|
|
| -bool ExecuteType2CharString(size_t call_depth,
|
| +bool ExecuteType2CharString(ots::OpenTypeFile *file,
|
| + size_t call_depth,
|
| const ots::CFFIndex& global_subrs_index,
|
| const ots::CFFIndex& local_subrs_index,
|
| ots::Buffer *cff_table,
|
| @@ -38,6 +41,112 @@ bool ExecuteType2CharString(size_t call_depth,
|
| bool *out_found_width,
|
| size_t *in_out_num_stems);
|
|
|
| +#ifdef DUMP_T2CHARSTRING
|
| +// Converts |op| to a string and returns it.
|
| +const char *Type2CharStringOperatorToString(ots::Type2CharStringOperator op) {
|
| + switch (op) {
|
| + case ots::kHStem:
|
| + return "HStem";
|
| + case ots::kVStem:
|
| + return "VStem";
|
| + case ots::kVMoveTo:
|
| + return "VMoveTo";
|
| + case ots::kRLineTo:
|
| + return "RLineTo";
|
| + case ots::kHLineTo:
|
| + return "HLineTo";
|
| + case ots::kVLineTo:
|
| + return "VLineTo";
|
| + case ots::kRRCurveTo:
|
| + return "RRCurveTo";
|
| + case ots::kCallSubr:
|
| + return "CallSubr";
|
| + case ots::kReturn:
|
| + return "Return";
|
| + case ots::kEndChar:
|
| + return "EndChar";
|
| + case ots::kHStemHm:
|
| + return "HStemHm";
|
| + case ots::kHintMask:
|
| + return "HintMask";
|
| + case ots::kCntrMask:
|
| + return "CntrMask";
|
| + case ots::kRMoveTo:
|
| + return "RMoveTo";
|
| + case ots::kHMoveTo:
|
| + return "HMoveTo";
|
| + case ots::kVStemHm:
|
| + return "VStemHm";
|
| + case ots::kRCurveLine:
|
| + return "RCurveLine";
|
| + case ots::kRLineCurve:
|
| + return "RLineCurve";
|
| + case ots::kVVCurveTo:
|
| + return "VVCurveTo";
|
| + case ots::kHHCurveTo:
|
| + return "HHCurveTo";
|
| + case ots::kCallGSubr:
|
| + return "CallGSubr";
|
| + case ots::kVHCurveTo:
|
| + return "VHCurveTo";
|
| + case ots::kHVCurveTo:
|
| + return "HVCurveTo";
|
| + case ots::kDotSection:
|
| + return "DotSection";
|
| + case ots::kAnd:
|
| + return "And";
|
| + case ots::kOr:
|
| + return "Or";
|
| + case ots::kNot:
|
| + return "Not";
|
| + case ots::kAbs:
|
| + return "Abs";
|
| + case ots::kAdd:
|
| + return "Add";
|
| + case ots::kSub:
|
| + return "Sub";
|
| + case ots::kDiv:
|
| + return "Div";
|
| + case ots::kNeg:
|
| + return "Neg";
|
| + case ots::kEq:
|
| + return "Eq";
|
| + case ots::kDrop:
|
| + return "Drop";
|
| + case ots::kPut:
|
| + return "Put";
|
| + case ots::kGet:
|
| + return "Get";
|
| + case ots::kIfElse:
|
| + return "IfElse";
|
| + case ots::kRandom:
|
| + return "Random";
|
| + case ots::kMul:
|
| + return "Mul";
|
| + case ots::kSqrt:
|
| + return "Sqrt";
|
| + case ots::kDup:
|
| + return "Dup";
|
| + case ots::kExch:
|
| + return "Exch";
|
| + case ots::kIndex:
|
| + return "Index";
|
| + case ots::kRoll:
|
| + return "Roll";
|
| + case ots::kHFlex:
|
| + return "HFlex";
|
| + case ots::kFlex:
|
| + return "Flex";
|
| + case ots::kHFlex1:
|
| + return "HFlex1";
|
| + case ots::kFlex1:
|
| + return "Flex1";
|
| + }
|
| +
|
| + return "UNKNOWN";
|
| +}
|
| +#endif
|
| +
|
| // Read one or more bytes from the |char_string| buffer and stores the number
|
| // read on |out_number|. If the number read is an operator (ex 'vstem'), sets
|
| // true on |out_is_operator|. Returns true if the function read a number.
|
| @@ -116,7 +225,8 @@ bool ReadNextNumberFromType2CharString(ots::Buffer *char_string,
|
| // succeeds. If the |op| is kCallSubr or kCallGSubr, the function recursively
|
| // calls ExecuteType2CharString() function. The arguments other than |op| and
|
| // |argument_stack| are passed for that reason.
|
| -bool ExecuteType2CharStringOperator(int32_t op,
|
| +bool ExecuteType2CharStringOperator(ots::OpenTypeFile *file,
|
| + int32_t op,
|
| size_t call_depth,
|
| const ots::CFFIndex& global_subrs_index,
|
| const ots::CFFIndex& local_subrs_index,
|
| @@ -180,7 +290,8 @@ bool ExecuteType2CharStringOperator(int32_t op,
|
| }
|
| ots::Buffer char_string_to_jump(cff_table->buffer() + offset, length);
|
|
|
| - return ExecuteType2CharString(call_depth + 1,
|
| + return ExecuteType2CharString(file,
|
| + call_depth + 1,
|
| global_subrs_index,
|
| local_subrs_index,
|
| cff_table,
|
| @@ -422,6 +533,13 @@ bool ExecuteType2CharStringOperator(int32_t op,
|
| return successful ? true : OTS_FAILURE();
|
| }
|
|
|
| + case ots::kDotSection:
|
| + // Deprecated operator but harmless, we probably should drop it some how.
|
| + if (stack_size != 0) {
|
| + return OTS_FAILURE();
|
| + }
|
| + return true;
|
| +
|
| case ots::kAnd:
|
| case ots::kOr:
|
| case ots::kEq:
|
| @@ -595,8 +713,7 @@ bool ExecuteType2CharStringOperator(int32_t op,
|
| return true;
|
| }
|
|
|
| - OTS_WARNING("Undefined operator: %d (0x%x)", op, op);
|
| - return OTS_FAILURE();
|
| + return OTS_FAILURE_MSG("Undefined operator: %d (0x%x)", op, op);
|
| }
|
|
|
| // Executes |char_string| and updates |argument_stack|.
|
| @@ -612,7 +729,8 @@ bool ExecuteType2CharStringOperator(int32_t op,
|
| // in_out_found_width: true is set if |char_string| contains 'width' byte (which
|
| // is 0 or 1 byte.)
|
| // in_out_num_stems: total number of hstems and vstems processed so far.
|
| -bool ExecuteType2CharString(size_t call_depth,
|
| +bool ExecuteType2CharString(ots::OpenTypeFile *file,
|
| + size_t call_depth,
|
| const ots::CFFIndex& global_subrs_index,
|
| const ots::CFFIndex& local_subrs_index,
|
| ots::Buffer *cff_table,
|
| @@ -636,19 +754,21 @@ bool ExecuteType2CharString(size_t call_depth,
|
| return OTS_FAILURE();
|
| }
|
|
|
| +#ifdef DUMP_T2CHARSTRING
|
| /*
|
| You can dump all operators and operands (except mask bytes for hintmask
|
| and cntrmask) by the following code:
|
| + */
|
|
|
| if (!is_operator) {
|
| std::fprintf(stderr, "#%d# ", operator_or_operand);
|
| } else {
|
| std::fprintf(stderr, "#%s#\n",
|
| Type2CharStringOperatorToString(
|
| - Type2CharStringOperator(operator_or_operand)),
|
| - operator_or_operand);
|
| + ots::Type2CharStringOperator(operator_or_operand))
|
| + );
|
| }
|
| - */
|
| +#endif
|
|
|
| if (!is_operator) {
|
| argument_stack->push(operator_or_operand);
|
| @@ -659,7 +779,8 @@ bool ExecuteType2CharString(size_t call_depth,
|
| }
|
|
|
| // An operator is found. Execute it.
|
| - if (!ExecuteType2CharStringOperator(operator_or_operand,
|
| + if (!ExecuteType2CharStringOperator(file,
|
| + operator_or_operand,
|
| call_depth,
|
| global_subrs_index,
|
| local_subrs_index,
|
| @@ -724,6 +845,7 @@ bool SelectLocalSubr(const std::map<uint16_t, uint8_t> &fd_select,
|
| namespace ots {
|
|
|
| bool ValidateType2CharStringIndex(
|
| + ots::OpenTypeFile *file,
|
| const CFFIndex& char_strings_index,
|
| const CFFIndex& global_subrs_index,
|
| const std::map<uint16_t, uint8_t> &fd_select,
|
| @@ -773,7 +895,8 @@ bool ValidateType2CharStringIndex(
|
| bool found_endchar = false;
|
| bool found_width = false;
|
| size_t num_stems = 0;
|
| - if (!ExecuteType2CharString(0 /* initial call_depth is zero */,
|
| + if (!ExecuteType2CharString(file,
|
| + 0 /* initial call_depth is zero */,
|
| global_subrs_index, *local_subrs_to_use,
|
| cff_table, &char_string, &argument_stack,
|
| &found_endchar, &found_width, &num_stems)) {
|
| @@ -787,3 +910,5 @@ bool ValidateType2CharStringIndex(
|
| }
|
|
|
| } // namespace ots
|
| +
|
| +#undef TABLE_NAME
|
|
|