Font::primaryFontData() should return a reference
[WebKit-https.git] / Source / WebCore / platform / graphics / opentype / OpenTypeMathData.cpp
1 /*
2  * Copyright (C) 2014 Frederic Wang (fred.wang@free.fr). All rights reserved.
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 THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "OpenTypeMathData.h"
28
29 #include "FontPlatformData.h"
30 #if ENABLE(OPENTYPE_MATH)
31 #include "OpenTypeTypes.h"
32 #endif
33 #include "SharedBuffer.h"
34 #include "SimpleFontData.h"
35
36 using namespace std;
37
38 namespace WebCore {
39
40 #if ENABLE(OPENTYPE_MATH)
41 namespace OpenType {
42
43 #if OS(DARWIN)
44 const FourCharCode MATHTag = 'MATH';
45 #else
46 const uint32_t MATHTag = OT_MAKE_TAG('M', 'A', 'T', 'H');
47 #endif
48
49 #pragma pack(1)
50
51 struct MathValueRecord {
52     OpenType::Int16 value;
53     OpenType::Offset deviceTableOffset;
54 };
55
56 struct MathConstants {
57     OpenType::Int16 intConstants[OpenTypeMathData::ScriptScriptPercentScaleDown - OpenTypeMathData::ScriptPercentScaleDown + 1];
58     OpenType::UInt16 uIntConstants[OpenTypeMathData::DisplayOperatorMinHeight - OpenTypeMathData::DelimitedSubFormulaMinHeight + 1];
59     OpenType::MathValueRecord mathValuesConstants[OpenTypeMathData::RadicalKernAfterDegree - OpenTypeMathData::MathLeading + 1];
60     OpenType::UInt16 radicalDegreeBottomRaisePercent;
61 };
62
63 struct MathItalicsCorrectionInfo : TableWithCoverage {
64     OpenType::Offset coverageOffset;
65     OpenType::UInt16 italicsCorrectionCount;
66     OpenType::MathValueRecord italicsCorrection[1]; // There are italicsCorrectionCount italic correction values.
67
68     int16_t getItalicCorrection(const SharedBuffer& buffer, Glyph glyph) const
69     {
70         uint16_t count = uint16_t(italicsCorrectionCount);
71         if (!isValidEnd(buffer, &italicsCorrection[count]))
72             return 0;
73
74         uint16_t offset = coverageOffset;
75         if (!offset)
76             return 0;
77         const CoverageTable* coverage = validateOffset<CoverageTable>(buffer, offset);
78         if (!coverage)
79             return 0;
80
81         // We determine the index in the italicsCorrection table.
82         uint32_t i;
83         if (!getCoverageIndex(buffer, coverage, glyph, i) || i >= count)
84             return 0;
85
86         return int16_t(italicsCorrection[i].value);
87     }
88 };
89
90 struct MathGlyphInfo : TableWithCoverage {
91     OpenType::Offset mathItalicsCorrectionInfoOffset;
92     OpenType::Offset mathTopAccentAttachmentOffset;
93     OpenType::Offset extendedShapeCoverageOffset;
94     OpenType::Offset mathKernInfoOffset;
95
96     const MathItalicsCorrectionInfo* mathItalicsCorrectionInfo(const SharedBuffer& buffer) const
97     {
98         uint16_t offset = mathItalicsCorrectionInfoOffset;
99         if (offset)
100             return validateOffset<MathItalicsCorrectionInfo>(buffer, offset);
101         return nullptr;
102     }
103 };
104
105 struct GlyphAssembly : TableBase {
106     OpenType::MathValueRecord italicsCorrection;
107     OpenType::UInt16 partCount;
108     struct GlyphPartRecord {
109         OpenType::GlyphID glyph;
110         OpenType::UInt16 startConnectorLength;
111         OpenType::UInt16 endConnectorLength;
112         OpenType::UInt16 fullAdvance;
113         OpenType::UInt16 partFlags;
114     } partRecords[1]; // There are partCount GlyphPartRecord's.
115
116     // PartFlags enumeration currently uses only one bit:
117     // 0x0001 If set, the part can be skipped or repeated.
118     // 0xFFFE Reserved.
119     enum {
120         PartFlagsExtender = 0x01
121     };
122
123     void getAssemblyParts(const SharedBuffer& buffer, Vector<OpenTypeMathData::AssemblyPart>& assemblyParts) const
124     {
125         uint16_t count = partCount;
126         if (!isValidEnd(buffer, &partRecords[count]))
127             return;
128         assemblyParts.resize(count);
129         for (uint16_t i = 0; i < count; i++) {
130             assemblyParts[i].glyph = partRecords[i].glyph;
131             uint16_t flag = partRecords[i].partFlags;
132             assemblyParts[i].isExtender = flag & PartFlagsExtender;
133         }
134     }
135
136 };
137
138 struct MathGlyphConstruction : TableBase {
139     OpenType::Offset glyphAssemblyOffset;
140     OpenType::UInt16 variantCount;
141     struct MathGlyphVariantRecord {
142         OpenType::GlyphID variantGlyph;
143         OpenType::UInt16 advanceMeasurement;
144     } mathGlyphVariantRecords[1]; // There are variantCount MathGlyphVariantRecord's.
145
146     void getSizeVariants(const SharedBuffer& buffer, Vector<Glyph>& variants) const
147     {
148         uint16_t count = variantCount;
149         if (!isValidEnd(buffer, &mathGlyphVariantRecords[count]))
150             return;
151         variants.resize(count);
152         for (uint16_t i = 0; i < count; i++)
153             variants[i] = mathGlyphVariantRecords[i].variantGlyph;
154     }
155
156     void getAssemblyParts(const SharedBuffer& buffer, Vector<OpenTypeMathData::AssemblyPart>& assemblyParts) const
157     {
158         uint16_t offset = glyphAssemblyOffset;
159         const GlyphAssembly* glyphAssembly = validateOffset<GlyphAssembly>(buffer, offset);
160         if (glyphAssembly)
161             glyphAssembly->getAssemblyParts(buffer, assemblyParts);
162     }
163 };
164
165 struct MathVariants : TableWithCoverage {
166     OpenType::UInt16 minConnectorOverlap;
167     OpenType::Offset verticalGlyphCoverageOffset;
168     OpenType::Offset horizontalGlyphCoverageOffset;
169     OpenType::UInt16 verticalGlyphCount;
170     OpenType::UInt16 horizontalGlyphCount;
171     OpenType::Offset mathGlyphConstructionsOffset[1]; // There are verticalGlyphCount vertical glyph contructions and horizontalGlyphCount vertical glyph contructions.
172
173     const MathGlyphConstruction* mathGlyphConstruction(const SharedBuffer& buffer, Glyph glyph, bool isVertical) const
174     {
175         uint32_t count = uint16_t(verticalGlyphCount) + uint16_t(horizontalGlyphCount);
176         if (!isValidEnd(buffer, &mathGlyphConstructionsOffset[count]))
177             return nullptr;
178
179         // We determine the coverage table for the specified glyph.
180         uint16_t coverageOffset = isVertical ? verticalGlyphCoverageOffset : horizontalGlyphCoverageOffset;
181         if (!coverageOffset)
182             return nullptr;
183         const CoverageTable* coverage = validateOffset<CoverageTable>(buffer, coverageOffset);
184         if (!coverage)
185             return nullptr;
186
187         // We determine the index in the mathGlyphConstructionsOffset table.
188         uint32_t i;
189         if (!getCoverageIndex(buffer, coverage, glyph, i))
190             return nullptr;
191         count = isVertical ? verticalGlyphCount : horizontalGlyphCount;
192         if (i >= count)
193             return nullptr;
194         if (!isVertical)
195             i += uint16_t(verticalGlyphCount);
196
197         return validateOffset<MathGlyphConstruction>(buffer, mathGlyphConstructionsOffset[i]);
198     }
199 };
200
201 struct MATHTable : TableBase {
202     OpenType::Fixed version;
203     OpenType::Offset mathConstantsOffset;
204     OpenType::Offset mathGlyphInfoOffset;
205     OpenType::Offset mathVariantsOffset;
206
207     const MathConstants* mathConstants(const SharedBuffer& buffer) const
208     {
209         uint16_t offset = mathConstantsOffset;
210         if (offset)
211             return validateOffset<MathConstants>(buffer, offset);
212         return nullptr;
213     }
214
215     const MathGlyphInfo* mathGlyphInfo(const SharedBuffer& buffer) const
216     {
217         uint16_t offset = mathGlyphInfoOffset;
218         if (offset)
219             return validateOffset<MathGlyphInfo>(buffer, offset);
220         return nullptr;
221     }
222
223     const MathVariants* mathVariants(const SharedBuffer& buffer) const
224     {
225         uint16_t offset = mathVariantsOffset;
226         if (offset)
227             return validateOffset<MathVariants>(buffer, offset);
228         return nullptr;
229     }
230 };
231
232 #pragma pack()
233
234 } // namespace OpenType
235 #endif // ENABLE(OPENTYPE_MATH)
236
237 #if ENABLE(OPENTYPE_MATH)
238 OpenTypeMathData::OpenTypeMathData(const FontPlatformData& fontData)
239 {
240     m_mathBuffer = fontData.openTypeTable(OpenType::MATHTag);
241     const OpenType::MATHTable* math = OpenType::validateTable<OpenType::MATHTable>(m_mathBuffer);
242     if (!math) {
243         m_mathBuffer = nullptr;
244         return;
245     }
246
247     const OpenType::MathConstants* mathConstants = math->mathConstants(*m_mathBuffer);
248     if (!mathConstants) {
249         m_mathBuffer = nullptr;
250         return;
251     }
252
253     const OpenType::MathVariants* mathVariants = math->mathVariants(*m_mathBuffer);
254     if (!mathVariants)
255         m_mathBuffer = nullptr;
256 #else
257 OpenTypeMathData::OpenTypeMathData(const FontPlatformData&)
258 {
259     m_mathBuffer = nullptr;
260 #endif
261 }
262
263 OpenTypeMathData::~OpenTypeMathData()
264 {
265 }
266
267 #if ENABLE(OPENTYPE_MATH)
268 float OpenTypeMathData::getMathConstant(const SimpleFontData& font, MathConstant constant) const
269 {
270     int32_t value = 0;
271
272     const OpenType::MATHTable* math = OpenType::validateTable<OpenType::MATHTable>(m_mathBuffer);
273     ASSERT(math);
274     const OpenType::MathConstants* mathConstants = math->mathConstants(*m_mathBuffer);
275     ASSERT(mathConstants);
276
277     if (constant >= 0 && constant <= ScriptScriptPercentScaleDown)
278         value = int16_t(mathConstants->intConstants[constant]);
279     else if (constant >= DelimitedSubFormulaMinHeight && constant <= DisplayOperatorMinHeight)
280         value = uint16_t(mathConstants->uIntConstants[constant - DelimitedSubFormulaMinHeight]);
281     else if (constant >= MathLeading && constant <= RadicalKernAfterDegree)
282         value = int16_t(mathConstants->mathValuesConstants[constant - MathLeading].value);
283     else if (constant == RadicalDegreeBottomRaisePercent)
284         value = uint16_t(mathConstants->radicalDegreeBottomRaisePercent);
285
286     if (constant == ScriptPercentScaleDown || constant == ScriptScriptPercentScaleDown || constant == RadicalDegreeBottomRaisePercent)
287         return value / 100.0;
288
289     return value * font.sizePerUnit();
290 #else
291 float OpenTypeMathData::getMathConstant(const SimpleFontData&, MathConstant) const
292 {
293     ASSERT_NOT_REACHED();
294     return 0;
295 #endif
296 }
297
298 #if ENABLE(OPENTYPE_MATH)
299 float OpenTypeMathData::getItalicCorrection(const SimpleFontData& font, Glyph glyph) const
300 {
301     const OpenType::MATHTable* math = OpenType::validateTable<OpenType::MATHTable>(m_mathBuffer);
302     ASSERT(math);
303     const OpenType::MathGlyphInfo* mathGlyphInfo = math->mathGlyphInfo(*m_mathBuffer);
304     if (!mathGlyphInfo)
305         return 0;
306
307     const OpenType::MathItalicsCorrectionInfo* mathItalicsCorrectionInfo = mathGlyphInfo->mathItalicsCorrectionInfo(*m_mathBuffer);
308     if (!mathItalicsCorrectionInfo)
309         return 0;
310
311     return mathItalicsCorrectionInfo->getItalicCorrection(*m_mathBuffer, glyph) * font.sizePerUnit();
312 #else
313 float OpenTypeMathData::getItalicCorrection(const SimpleFontData&, Glyph) const
314 {
315     ASSERT_NOT_REACHED();
316     return 0;
317 #endif
318 }
319
320 #if ENABLE(OPENTYPE_MATH)
321 void OpenTypeMathData::getMathVariants(Glyph glyph, bool isVertical, Vector<Glyph>& sizeVariants, Vector<AssemblyPart>& assemblyParts) const
322 {
323     sizeVariants.clear();
324     assemblyParts.clear();
325     const OpenType::MATHTable* math = OpenType::validateTable<OpenType::MATHTable>(m_mathBuffer);
326     ASSERT(math);
327     const OpenType::MathVariants* mathVariants = math->mathVariants(*m_mathBuffer);
328     ASSERT(mathVariants);
329
330     const OpenType::MathGlyphConstruction* mathGlyphConstruction = mathVariants->mathGlyphConstruction(*m_mathBuffer, glyph, isVertical);
331     if (!mathGlyphConstruction)
332         return;
333
334     mathGlyphConstruction->getSizeVariants(*m_mathBuffer, sizeVariants);
335     mathGlyphConstruction->getAssemblyParts(*m_mathBuffer, assemblyParts);
336 #else
337 void OpenTypeMathData::getMathVariants(Glyph, bool, Vector<Glyph>&, Vector<AssemblyPart>&) const
338 {
339     ASSERT_NOT_REACHED();
340 #endif
341 }
342
343 } // namespace WebCore