variable_length.cc (3176B)
1 /* Copyright 2015 Google Inc. All Rights Reserved. 2 3 Distributed under MIT license. 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT 5 */ 6 7 /* Helper functions for woff2 variable length types: 255UInt16 and UIntBase128 */ 8 9 #include "./variable_length.h" 10 11 namespace woff2 { 12 13 size_t Size255UShort(uint16_t value) { 14 size_t result = 3; 15 if (value < 253) { 16 result = 1; 17 } else if (value < 762) { 18 result = 2; 19 } else { 20 result = 3; 21 } 22 return result; 23 } 24 25 void Write255UShort(std::vector<uint8_t>* out, int value) { 26 if (value < 253) { 27 out->push_back(value); 28 } else if (value < 506) { 29 out->push_back(255); 30 out->push_back(value - 253); 31 } else if (value < 762) { 32 out->push_back(254); 33 out->push_back(value - 506); 34 } else { 35 out->push_back(253); 36 out->push_back(value >> 8); 37 out->push_back(value & 0xff); 38 } 39 } 40 41 void Store255UShort(int val, size_t* offset, uint8_t* dst) { 42 std::vector<uint8_t> packed; 43 Write255UShort(&packed, val); 44 for (uint8_t packed_byte : packed) { 45 dst[(*offset)++] = packed_byte; 46 } 47 } 48 49 // Based on section 6.1.1 of MicroType Express draft spec 50 bool Read255UShort(Buffer* buf, unsigned int* value) { 51 static const int kWordCode = 253; 52 static const int kOneMoreByteCode2 = 254; 53 static const int kOneMoreByteCode1 = 255; 54 static const int kLowestUCode = 253; 55 uint8_t code = 0; 56 if (!buf->ReadU8(&code)) { 57 return FONT_COMPRESSION_FAILURE(); 58 } 59 if (code == kWordCode) { 60 uint16_t result = 0; 61 if (!buf->ReadU16(&result)) { 62 return FONT_COMPRESSION_FAILURE(); 63 } 64 *value = result; 65 return true; 66 } else if (code == kOneMoreByteCode1) { 67 uint8_t result = 0; 68 if (!buf->ReadU8(&result)) { 69 return FONT_COMPRESSION_FAILURE(); 70 } 71 *value = result + kLowestUCode; 72 return true; 73 } else if (code == kOneMoreByteCode2) { 74 uint8_t result = 0; 75 if (!buf->ReadU8(&result)) { 76 return FONT_COMPRESSION_FAILURE(); 77 } 78 *value = result + kLowestUCode * 2; 79 return true; 80 } else { 81 *value = code; 82 return true; 83 } 84 } 85 86 bool ReadBase128(Buffer* buf, uint32_t* value) { 87 uint32_t result = 0; 88 for (size_t i = 0; i < 5; ++i) { 89 uint8_t code = 0; 90 if (!buf->ReadU8(&code)) { 91 return FONT_COMPRESSION_FAILURE(); 92 } 93 // Leading zeros are invalid. 94 if (i == 0 && code == 0x80) { 95 return FONT_COMPRESSION_FAILURE(); 96 } 97 // If any of the top seven bits are set then we're about to overflow. 98 if (result & 0xfe000000) { 99 return FONT_COMPRESSION_FAILURE(); 100 } 101 result = (result << 7) | (code & 0x7f); 102 if ((code & 0x80) == 0) { 103 *value = result; 104 return true; 105 } 106 } 107 // Make sure not to exceed the size bound 108 return FONT_COMPRESSION_FAILURE(); 109 } 110 111 size_t Base128Size(size_t n) { 112 size_t size = 1; 113 for (; n >= 128; n >>= 7) ++size; 114 return size; 115 } 116 117 void StoreBase128(size_t len, size_t* offset, uint8_t* dst) { 118 size_t size = Base128Size(len); 119 for (size_t i = 0; i < size; ++i) { 120 int b = static_cast<int>((len >> (7 * (size - i - 1))) & 0x7f); 121 if (i < size - 1) { 122 b |= 0x80; 123 } 124 dst[(*offset)++] = b; 125 } 126 } 127 128 } // namespace woff2