| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. | 2 * Copyright (c) 2008, 2009, Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 19 matching lines...) Expand all Loading... |
| 30 | 30 |
| 31 #include "platform/fonts/VDMXParser.h" | 31 #include "platform/fonts/VDMXParser.h" |
| 32 | 32 |
| 33 #include "platform/wtf/Allocator.h" | 33 #include "platform/wtf/Allocator.h" |
| 34 #include "platform/wtf/ByteOrder.h" | 34 #include "platform/wtf/ByteOrder.h" |
| 35 #include "platform/wtf/Noncopyable.h" | 35 #include "platform/wtf/Noncopyable.h" |
| 36 | 36 |
| 37 #include <stdlib.h> | 37 #include <stdlib.h> |
| 38 #include <string.h> | 38 #include <string.h> |
| 39 | 39 |
| 40 namespace blink { |
| 41 namespace { |
| 42 |
| 40 // Buffer helper class | 43 // Buffer helper class |
| 41 // | 44 // |
| 42 // This class perform some trival buffer operations while checking for | 45 // This class perform some trival buffer operations while checking for |
| 43 // out-of-bounds errors. As a family they return false if anything is amiss, | 46 // out-of-bounds errors. As a family they return false if anything is amiss, |
| 44 // updating the current offset otherwise. | 47 // updating the current offset otherwise. |
| 45 class Buffer { | 48 class Buffer { |
| 46 STACK_ALLOCATED(); | 49 STACK_ALLOCATED(); |
| 47 WTF_MAKE_NONCOPYABLE(Buffer); | 50 WTF_MAKE_NONCOPYABLE(Buffer); |
| 48 | 51 |
| 49 public: | 52 public: |
| 50 Buffer(const uint8_t* buffer, size_t length) | 53 Buffer(const uint8_t* buffer, size_t length) |
| 51 : m_buffer(buffer), m_length(length), m_offset(0) {} | 54 : buffer_(buffer), length_(length), offset_(0) {} |
| 52 | 55 |
| 53 bool skip(size_t numBytes) { | 56 bool skip(size_t numBytes) { |
| 54 if (m_offset + numBytes > m_length) | 57 if (offset_ + numBytes > length_) |
| 55 return false; | 58 return false; |
| 56 m_offset += numBytes; | 59 offset_ += numBytes; |
| 57 return true; | 60 return true; |
| 58 } | 61 } |
| 59 | 62 |
| 60 bool readU8(uint8_t* value) { | 63 bool ReadU8(uint8_t* value) { |
| 61 if (m_offset + sizeof(uint8_t) > m_length) | 64 if (offset_ + sizeof(uint8_t) > length_) |
| 62 return false; | 65 return false; |
| 63 *value = m_buffer[m_offset]; | 66 *value = buffer_[offset_]; |
| 64 m_offset += sizeof(uint8_t); | 67 offset_ += sizeof(uint8_t); |
| 65 return true; | 68 return true; |
| 66 } | 69 } |
| 67 | 70 |
| 68 bool readU16(uint16_t* value) { | 71 bool ReadU16(uint16_t* value) { |
| 69 if (m_offset + sizeof(uint16_t) > m_length) | 72 if (offset_ + sizeof(uint16_t) > length_) |
| 70 return false; | 73 return false; |
| 71 memcpy(value, m_buffer + m_offset, sizeof(uint16_t)); | 74 memcpy(value, buffer_ + offset_, sizeof(uint16_t)); |
| 72 *value = ntohs(*value); | 75 *value = ntohs(*value); |
| 73 m_offset += sizeof(uint16_t); | 76 offset_ += sizeof(uint16_t); |
| 74 return true; | 77 return true; |
| 75 } | 78 } |
| 76 | 79 |
| 77 bool readS16(int16_t* value) { | 80 bool ReadS16(int16_t* value) { |
| 78 return readU16(reinterpret_cast<uint16_t*>(value)); | 81 return ReadU16(reinterpret_cast<uint16_t*>(value)); |
| 79 } | 82 } |
| 80 | 83 |
| 81 size_t offset() const { return m_offset; } | 84 size_t Offset() const { return offset_; } |
| 82 | 85 |
| 83 void setOffset(size_t newoffset) { m_offset = newoffset; } | 86 void SetOffset(size_t newoffset) { offset_ = newoffset; } |
| 84 | 87 |
| 85 private: | 88 private: |
| 86 const uint8_t* const m_buffer; | 89 const uint8_t* const buffer_; |
| 87 const size_t m_length; | 90 const size_t length_; |
| 88 size_t m_offset; | 91 size_t offset_; |
| 89 }; | 92 }; |
| 90 | 93 |
| 94 } // namespace |
| 95 |
| 91 // VDMX parsing code. | 96 // VDMX parsing code. |
| 92 // | 97 // |
| 93 // VDMX tables are found in some TrueType/OpenType fonts and contain | 98 // VDMX tables are found in some TrueType/OpenType fonts and contain |
| 94 // ascender/descender overrides for certain (usually small) sizes. This is | 99 // ascender/descender overrides for certain (usually small) sizes. This is |
| 95 // needed in order to match font metrics on Windows. | 100 // needed in order to match font metrics on Windows. |
| 96 // | 101 // |
| 97 // Freetype does not parse these tables so we do so here. | 102 // Freetype does not parse these tables so we do so here. |
| 98 | 103 |
| 99 namespace blink { | |
| 100 | |
| 101 // Parse a TrueType VDMX table. | 104 // Parse a TrueType VDMX table. |
| 102 // yMax: (output) the ascender value from the table | 105 // yMax: (output) the ascender value from the table |
| 103 // yMin: (output) the descender value from the table (negative!) | 106 // yMin: (output) the descender value from the table (negative!) |
| 104 // vdmx: the table bytes | 107 // vdmx: the table bytes |
| 105 // vdmxLength: length of @vdmx, in bytes | 108 // vdmxLength: length of @vdmx, in bytes |
| 106 // targetPixelSize: the pixel size of the font (e.g. 16) | 109 // targetPixelSize: the pixel size of the font (e.g. 16) |
| 107 // | 110 // |
| 108 // Returns true iff a suitable match are found. Otherwise, *yMax and *yMin are | 111 // Returns true iff a suitable match are found. Otherwise, *yMax and *yMin are |
| 109 // untouched. size_t must be 32-bits to avoid overflow. | 112 // untouched. size_t must be 32-bits to avoid overflow. |
| 110 // | 113 // |
| 111 // See http://www.microsoft.com/opentype/otspec/vdmx.htm | 114 // See http://www.microsoft.com/opentype/otspec/vdmx.htm |
| 112 bool ParseVDMX(int* y_max, | 115 bool ParseVDMX(int* y_max, |
| 113 int* y_min, | 116 int* y_min, |
| 114 const uint8_t* vdmx, | 117 const uint8_t* vdmx, |
| 115 size_t vdmx_length, | 118 size_t vdmx_length, |
| 116 unsigned target_pixel_size) { | 119 unsigned target_pixel_size) { |
| 117 Buffer buf(vdmx, vdmx_length); | 120 Buffer buf(vdmx, vdmx_length); |
| 118 | 121 |
| 119 // We ignore the version. Future tables should be backwards compatible with | 122 // We ignore the version. Future tables should be backwards compatible with |
| 120 // this layout. | 123 // this layout. |
| 121 uint16_t num_ratios; | 124 uint16_t num_ratios; |
| 122 if (!buf.skip(4) || !buf.readU16(&num_ratios)) | 125 if (!buf.skip(4) || !buf.ReadU16(&num_ratios)) |
| 123 return false; | 126 return false; |
| 124 | 127 |
| 125 // Now we have two tables. Firstly we have @numRatios Ratio records, then a | 128 // Now we have two tables. Firstly we have @numRatios Ratio records, then a |
| 126 // matching array of @numRatios offsets. We save the offset of the beginning | 129 // matching array of @numRatios offsets. We save the offset of the beginning |
| 127 // of this second table. | 130 // of this second table. |
| 128 // | 131 // |
| 129 // Range 6 <= x <= 262146 | 132 // Range 6 <= x <= 262146 |
| 130 unsigned long offset_table_offset = | 133 unsigned long offset_table_offset = |
| 131 buf.offset() + 4 /* sizeof struct ratio */ * num_ratios; | 134 buf.Offset() + 4 /* sizeof struct ratio */ * num_ratios; |
| 132 | 135 |
| 133 unsigned desired_ratio = 0xffffffff; | 136 unsigned desired_ratio = 0xffffffff; |
| 134 // We read 4 bytes per record, so the offset range is | 137 // We read 4 bytes per record, so the offset range is |
| 135 // 6 <= x <= 524286 | 138 // 6 <= x <= 524286 |
| 136 for (unsigned i = 0; i < num_ratios; ++i) { | 139 for (unsigned i = 0; i < num_ratios; ++i) { |
| 137 uint8_t x_ratio, y_ratio1, y_ratio2; | 140 uint8_t x_ratio, y_ratio1, y_ratio2; |
| 138 | 141 |
| 139 if (!buf.skip(1) || !buf.readU8(&x_ratio) || !buf.readU8(&y_ratio1) || | 142 if (!buf.skip(1) || !buf.ReadU8(&x_ratio) || !buf.ReadU8(&y_ratio1) || |
| 140 !buf.readU8(&y_ratio2)) | 143 !buf.ReadU8(&y_ratio2)) |
| 141 return false; | 144 return false; |
| 142 | 145 |
| 143 // This either covers 1:1, or this is the default entry (0, 0, 0) | 146 // This either covers 1:1, or this is the default entry (0, 0, 0) |
| 144 if ((x_ratio == 1 && y_ratio1 <= 1 && y_ratio2 >= 1) || | 147 if ((x_ratio == 1 && y_ratio1 <= 1 && y_ratio2 >= 1) || |
| 145 (x_ratio == 0 && y_ratio1 == 0 && y_ratio2 == 0)) { | 148 (x_ratio == 0 && y_ratio1 == 0 && y_ratio2 == 0)) { |
| 146 desired_ratio = i; | 149 desired_ratio = i; |
| 147 break; | 150 break; |
| 148 } | 151 } |
| 149 } | 152 } |
| 150 | 153 |
| 151 if (desired_ratio == 0xffffffff) // no ratio found | 154 if (desired_ratio == 0xffffffff) // no ratio found |
| 152 return false; | 155 return false; |
| 153 | 156 |
| 154 // Range 10 <= x <= 393216 | 157 // Range 10 <= x <= 393216 |
| 155 buf.setOffset(offset_table_offset + sizeof(uint16_t) * desired_ratio); | 158 buf.SetOffset(offset_table_offset + sizeof(uint16_t) * desired_ratio); |
| 156 | 159 |
| 157 // Now we read from the offset table to get the offset of another array | 160 // Now we read from the offset table to get the offset of another array |
| 158 uint16_t group_offset; | 161 uint16_t group_offset; |
| 159 if (!buf.readU16(&group_offset)) | 162 if (!buf.ReadU16(&group_offset)) |
| 160 return false; | 163 return false; |
| 161 // Range 0 <= x <= 65535 | 164 // Range 0 <= x <= 65535 |
| 162 buf.setOffset(group_offset); | 165 buf.SetOffset(group_offset); |
| 163 | 166 |
| 164 uint16_t num_records; | 167 uint16_t num_records; |
| 165 if (!buf.readU16(&num_records) || !buf.skip(sizeof(uint16_t))) | 168 if (!buf.ReadU16(&num_records) || !buf.skip(sizeof(uint16_t))) |
| 166 return false; | 169 return false; |
| 167 | 170 |
| 168 // We read 6 bytes per record, so the offset range is | 171 // We read 6 bytes per record, so the offset range is |
| 169 // 4 <= x <= 458749 | 172 // 4 <= x <= 458749 |
| 170 for (unsigned i = 0; i < num_records; ++i) { | 173 for (unsigned i = 0; i < num_records; ++i) { |
| 171 uint16_t pixel_size; | 174 uint16_t pixel_size; |
| 172 if (!buf.readU16(&pixel_size)) | 175 if (!buf.ReadU16(&pixel_size)) |
| 173 return false; | 176 return false; |
| 174 // the entries are sorted, so we can abort early if need be | 177 // the entries are sorted, so we can abort early if need be |
| 175 if (pixel_size > target_pixel_size) | 178 if (pixel_size > target_pixel_size) |
| 176 return false; | 179 return false; |
| 177 | 180 |
| 178 if (pixel_size == target_pixel_size) { | 181 if (pixel_size == target_pixel_size) { |
| 179 int16_t temp_y_max, temp_y_min; | 182 int16_t temp_y_max, temp_y_min; |
| 180 if (!buf.readS16(&temp_y_max) || !buf.readS16(&temp_y_min)) | 183 if (!buf.ReadS16(&temp_y_max) || !buf.ReadS16(&temp_y_min)) |
| 181 return false; | 184 return false; |
| 182 *y_min = temp_y_min; | 185 *y_min = temp_y_min; |
| 183 *y_max = temp_y_max; | 186 *y_max = temp_y_max; |
| 184 return true; | 187 return true; |
| 185 } | 188 } |
| 186 if (!buf.skip(2 * sizeof(int16_t))) | 189 if (!buf.skip(2 * sizeof(int16_t))) |
| 187 return false; | 190 return false; |
| 188 } | 191 } |
| 189 | 192 |
| 190 return false; | 193 return false; |
| 191 } | 194 } |
| 192 | 195 |
| 193 } // namespace blink | 196 } // namespace blink |
| OLD | NEW |