1/* 2 * Copyright (C) 2012 Koji Ishii <kojiishi@gmail.com> 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25#ifndef OpenTypeTypes_h 26#define OpenTypeTypes_h 27 28#include "SharedBuffer.h" 29 30namespace WebCore { 31namespace OpenType { 32 33struct BigEndianShort { 34 operator short() const { return (v & 0x00ff) << 8 | v >> 8; } 35 BigEndianShort(short u) : v((u & 0x00ff) << 8 | u >> 8) { } 36 unsigned short v; 37}; 38 39struct BigEndianUShort { 40 operator unsigned short() const { return (v & 0x00ff) << 8 | v >> 8; } 41 BigEndianUShort(unsigned short u) : v((u & 0x00ff) << 8 | u >> 8) { } 42 unsigned short v; 43}; 44 45struct BigEndianLong { 46 operator int() const { return (v & 0xff) << 24 | (v & 0xff00) << 8 | (v & 0xff0000) >> 8 | v >> 24; } 47 BigEndianLong(int u) : v((u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | u >> 24) { } 48 unsigned v; 49}; 50 51struct BigEndianULong { 52 operator unsigned() const { return (v & 0xff) << 24 | (v & 0xff00) << 8 | (v & 0xff0000) >> 8 | v >> 24; } 53 BigEndianULong(unsigned u) : v((u & 0xff) << 24 | (u & 0xff00) << 8 | (u & 0xff0000) >> 8 | u >> 24) { } 54 unsigned v; 55}; 56 57typedef BigEndianShort Int16; 58typedef BigEndianUShort UInt16; 59typedef BigEndianLong Int32; 60typedef BigEndianULong UInt32; 61 62typedef UInt32 Fixed; 63typedef UInt16 Offset; 64typedef UInt16 GlyphID; 65 66// OTTag is native because it's only compared against constants, so we don't 67// do endian conversion here but make sure constants are in big-endian order. 68// Note that multi-character literal is implementation-defined in C++0x. 69typedef uint32_t Tag; 70#define OT_MAKE_TAG(ch1, ch2, ch3, ch4) ((((uint32_t)(ch4)) << 24) | (((uint32_t)(ch3)) << 16) | (((uint32_t)(ch2)) << 8) | ((uint32_t)(ch1))) 71 72template <typename T> static const T* validateTable(const RefPtr<SharedBuffer>& buffer, size_t count = 1) 73{ 74 if (!buffer || buffer->size() < sizeof(T) * count) 75 return 0; 76 return reinterpret_cast<const T*>(buffer->data()); 77} 78 79struct TableBase { 80protected: 81 static bool isValidEnd(const SharedBuffer& buffer, const void* position) 82 { 83 if (position < buffer.data()) 84 return false; 85 size_t offset = reinterpret_cast<const char*>(position) - buffer.data(); 86 return offset <= buffer.size(); // "<=" because end is included as valid 87 } 88 89 template <typename T> static const T* validatePtr(const SharedBuffer& buffer, const void* position) 90 { 91 const T* casted = reinterpret_cast<const T*>(position); 92 if (!isValidEnd(buffer, &casted[1])) 93 return 0; 94 return casted; 95 } 96 97 template <typename T> const T* validateOffset(const SharedBuffer& buffer, uint16_t offset) const 98 { 99 return validatePtr<T>(buffer, reinterpret_cast<const int8_t*>(this) + offset); 100 } 101}; 102 103#if ENABLE(OPENTYPE_VERTICAL) || ENABLE(OPENTYPE_MATH) 104struct CoverageTable : TableBase { 105 OpenType::UInt16 coverageFormat; 106}; 107 108struct Coverage1Table : CoverageTable { 109 OpenType::UInt16 glyphCount; 110 OpenType::GlyphID glyphArray[1]; 111}; 112 113struct Coverage2Table : CoverageTable { 114 OpenType::UInt16 rangeCount; 115 struct RangeRecord { 116 OpenType::GlyphID start; 117 OpenType::GlyphID end; 118 OpenType::UInt16 startCoverageIndex; 119 } ranges[1]; 120}; 121#endif // ENABLE(OPENTYPE_VERTICAL) || ENABLE(OPENTYPE_MATH) 122 123#if ENABLE(OPENTYPE_MATH) 124struct TableWithCoverage : TableBase { 125protected: 126 bool getCoverageIndex(const SharedBuffer& buffer, const CoverageTable* coverage, Glyph glyph, uint32_t& coverageIndex) const 127 { 128 switch (coverage->coverageFormat) { 129 case 1: { // Coverage Format 1 130 const Coverage1Table* coverage1 = validatePtr<Coverage1Table>(buffer, coverage); 131 if (!coverage1) 132 return false; 133 uint16_t glyphCount = coverage1->glyphCount; 134 if (!isValidEnd(buffer, &coverage1->glyphArray[glyphCount])) 135 return false; 136 137 // We do a binary search on the glyph indexes. 138 uint32_t imin = 0, imax = glyphCount; 139 while (imin < imax) { 140 uint32_t imid = (imin + imax) >> 1; 141 uint16_t glyphMid = coverage1->glyphArray[imid]; 142 if (glyphMid == glyph) { 143 coverageIndex = imid; 144 return true; 145 } 146 if (glyphMid < glyph) 147 imin = imid + 1; 148 else 149 imax = imid; 150 } 151 break; 152 } 153 case 2: { // Coverage Format 2 154 const Coverage2Table* coverage2 = validatePtr<Coverage2Table>(buffer, coverage); 155 if (!coverage2) 156 return false; 157 uint16_t rangeCount = coverage2->rangeCount; 158 if (!isValidEnd(buffer, &coverage2->ranges[rangeCount])) 159 return false; 160 161 // We do a binary search on the ranges. 162 uint32_t imin = 0, imax = rangeCount; 163 while (imin < imax) { 164 uint32_t imid = (imin + imax) >> 1; 165 uint16_t rStart = coverage2->ranges[imid].start; 166 uint16_t rEnd = coverage2->ranges[imid].end; 167 if (rEnd < glyph) 168 imin = imid + 1; 169 else if (glyph < rStart) 170 imax = imid; 171 else { 172 coverageIndex = coverage2->ranges[imid].startCoverageIndex + glyph - rStart; 173 return true; 174 } 175 } 176 break; 177 } 178 } 179 return false; 180 } 181}; 182#endif 183 184} // namespace OpenType 185} // namespace WebCore 186#endif // OpenTypeTypes_h 187