/* Copyright 2015 Google Inc. All Rights Reserved. Distributed under MIT license. See file LICENSE for detail or copy at https://opensource.org/licenses/MIT */ /* Helper functions for woff2 variable length types: 255UInt16 and UIntBase128 */ #include "./variable_length.h" namespace woff2 { size_t Size255UShort(uint16_t value) { size_t result = 3; if (value < 253) { result = 1; } else if (value < 762) { result = 2; } else { result = 3; } return result; } void Write255UShort(std::vector* out, int value) { if (value < 253) { out->push_back(value); } else if (value < 506) { out->push_back(255); out->push_back(value - 253); } else if (value < 762) { out->push_back(254); out->push_back(value - 506); } else { out->push_back(253); out->push_back(value >> 8); out->push_back(value & 0xff); } } void Store255UShort(int val, size_t* offset, uint8_t* dst) { std::vector packed; Write255UShort(&packed, val); for (uint8_t packed_byte : packed) { dst[(*offset)++] = packed_byte; } } // Based on section 6.1.1 of MicroType Express draft spec bool Read255UShort(Buffer* buf, unsigned int* value) { static const int kWordCode = 253; static const int kOneMoreByteCode2 = 254; static const int kOneMoreByteCode1 = 255; static const int kLowestUCode = 253; uint8_t code = 0; if (!buf->ReadU8(&code)) { return FONT_COMPRESSION_FAILURE(); } if (code == kWordCode) { uint16_t result = 0; if (!buf->ReadU16(&result)) { return FONT_COMPRESSION_FAILURE(); } *value = result; return true; } else if (code == kOneMoreByteCode1) { uint8_t result = 0; if (!buf->ReadU8(&result)) { return FONT_COMPRESSION_FAILURE(); } *value = result + kLowestUCode; return true; } else if (code == kOneMoreByteCode2) { uint8_t result = 0; if (!buf->ReadU8(&result)) { return FONT_COMPRESSION_FAILURE(); } *value = result + kLowestUCode * 2; return true; } else { *value = code; return true; } } bool ReadBase128(Buffer* buf, uint32_t* value) { uint32_t result = 0; for (size_t i = 0; i < 5; ++i) { uint8_t code = 0; if (!buf->ReadU8(&code)) { return FONT_COMPRESSION_FAILURE(); } // Leading zeros are invalid. if (i == 0 && code == 0x80) { return FONT_COMPRESSION_FAILURE(); } // If any of the top seven bits are set then we're about to overflow. if (result & 0xfe000000) { return FONT_COMPRESSION_FAILURE(); } result = (result << 7) | (code & 0x7f); if ((code & 0x80) == 0) { *value = result; return true; } } // Make sure not to exceed the size bound return FONT_COMPRESSION_FAILURE(); } size_t Base128Size(size_t n) { size_t size = 1; for (; n >= 128; n >>= 7) ++size; return size; } void StoreBase128(size_t len, size_t* offset, uint8_t* dst) { size_t size = Base128Size(len); for (size_t i = 0; i < size; ++i) { int b = static_cast((len >> (7 * (size - i - 1))) & 0x7f); if (i < size - 1) { b |= 0x80; } dst[(*offset)++] = b; } } } // namespace woff2