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 |