| /* 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<uint8_t>* 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<uint8_t> 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<int>((len >> (7 * (size - i - 1))) & 0x7f); |
| if (i < size - 1) { |
| b |= 0x80; |
| } |
| dst[(*offset)++] = b; |
| } |
| } |
| |
| } // namespace woff2 |
| |