1 | /* |
2 | * Copyright (C) 2006, 2009, 2011, 2016 Apple Inc. All rights reserved. |
3 | * Copyright (C) 2007-2008 Torch Mobile Inc. |
4 | * |
5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions |
7 | * are met: |
8 | * |
9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. |
14 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of |
15 | * its contributors may be used to endorse or promote products derived |
16 | * from this software without specific prior written permission. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
19 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
21 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
22 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
23 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
24 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
25 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
27 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ |
29 | |
30 | #pragma once |
31 | |
32 | #include "FloatSize.h" |
33 | #include "Glyph.h" |
34 | #include <climits> |
35 | #include <wtf/Vector.h> |
36 | |
37 | #if USE(CG) |
38 | #include <CoreGraphics/CGGeometry.h> |
39 | #endif |
40 | |
41 | namespace WebCore { |
42 | |
43 | class Font; |
44 | |
45 | #if USE(WINGDI) |
46 | typedef wchar_t GlyphBufferGlyph; |
47 | #else |
48 | typedef Glyph GlyphBufferGlyph; |
49 | #endif |
50 | |
51 | // CG uses CGSize instead of FloatSize so that the result of advances() |
52 | // can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm |
53 | #if USE(CG) |
54 | struct GlyphBufferAdvance : CGSize { |
55 | public: |
56 | GlyphBufferAdvance() : CGSize(CGSizeZero) { } |
57 | GlyphBufferAdvance(CGSize size) |
58 | : CGSize(size) |
59 | { |
60 | } |
61 | GlyphBufferAdvance(float width, float height) |
62 | : CGSize(CGSizeMake(width, height)) |
63 | { |
64 | } |
65 | |
66 | void setWidth(CGFloat width) { this->CGSize::width = width; } |
67 | void setHeight(CGFloat height) { this->CGSize::height = height; } |
68 | CGFloat width() const { return this->CGSize::width; } |
69 | CGFloat height() const { return this->CGSize::height; } |
70 | }; |
71 | #else |
72 | typedef FloatSize GlyphBufferAdvance; |
73 | #endif |
74 | |
75 | class GlyphBuffer { |
76 | public: |
77 | bool isEmpty() const { return m_font.isEmpty(); } |
78 | unsigned size() const { return m_font.size(); } |
79 | |
80 | void clear() |
81 | { |
82 | m_font.clear(); |
83 | m_glyphs.clear(); |
84 | m_advances.clear(); |
85 | if (m_offsetsInString) |
86 | m_offsetsInString->clear(); |
87 | } |
88 | |
89 | GlyphBufferGlyph* glyphs(unsigned from) { return m_glyphs.data() + from; } |
90 | GlyphBufferAdvance* advances(unsigned from) { return m_advances.data() + from; } |
91 | const GlyphBufferGlyph* glyphs(unsigned from) const { return m_glyphs.data() + from; } |
92 | const GlyphBufferAdvance* advances(unsigned from) const { return m_advances.data() + from; } |
93 | size_t advancesCount() const { return m_advances.size(); } |
94 | |
95 | const Font* fontAt(unsigned index) const { return m_font[index]; } |
96 | |
97 | void setInitialAdvance(GlyphBufferAdvance initialAdvance) { m_initialAdvance = initialAdvance; } |
98 | const GlyphBufferAdvance& initialAdvance() const { return m_initialAdvance; } |
99 | |
100 | Glyph glyphAt(unsigned index) const |
101 | { |
102 | return m_glyphs[index]; |
103 | } |
104 | |
105 | GlyphBufferAdvance advanceAt(unsigned index) const |
106 | { |
107 | return m_advances[index]; |
108 | } |
109 | |
110 | static const unsigned noOffset = UINT_MAX; |
111 | void add(Glyph glyph, const Font* font, float width, unsigned offsetInString = noOffset) |
112 | { |
113 | GlyphBufferAdvance advance; |
114 | advance.setWidth(width); |
115 | advance.setHeight(0); |
116 | |
117 | add(glyph, font, advance, offsetInString); |
118 | } |
119 | |
120 | void add(Glyph glyph, const Font* font, GlyphBufferAdvance advance, unsigned offsetInString) |
121 | { |
122 | m_font.append(font); |
123 | m_glyphs.append(glyph); |
124 | |
125 | m_advances.append(advance); |
126 | |
127 | if (offsetInString != noOffset && m_offsetsInString) |
128 | m_offsetsInString->append(offsetInString); |
129 | } |
130 | |
131 | void reverse(unsigned from, unsigned length) |
132 | { |
133 | for (unsigned i = from, end = from + length - 1; i < end; ++i, --end) |
134 | swap(i, end); |
135 | } |
136 | |
137 | void expandLastAdvance(float width) |
138 | { |
139 | ASSERT(!isEmpty()); |
140 | GlyphBufferAdvance& lastAdvance = m_advances.last(); |
141 | lastAdvance.setWidth(lastAdvance.width() + width); |
142 | } |
143 | |
144 | void expandLastAdvance(GlyphBufferAdvance expansion) |
145 | { |
146 | ASSERT(!isEmpty()); |
147 | GlyphBufferAdvance& lastAdvance = m_advances.last(); |
148 | lastAdvance.setWidth(lastAdvance.width() + expansion.width()); |
149 | lastAdvance.setHeight(lastAdvance.height() + expansion.height()); |
150 | } |
151 | |
152 | void saveOffsetsInString() |
153 | { |
154 | m_offsetsInString.reset(new Vector<unsigned, 2048>()); |
155 | } |
156 | |
157 | int offsetInString(unsigned index) const |
158 | { |
159 | ASSERT(m_offsetsInString); |
160 | return (*m_offsetsInString)[index]; |
161 | } |
162 | |
163 | void shrink(unsigned truncationPoint) |
164 | { |
165 | m_font.shrink(truncationPoint); |
166 | m_glyphs.shrink(truncationPoint); |
167 | m_advances.shrink(truncationPoint); |
168 | if (m_offsetsInString) |
169 | m_offsetsInString->shrink(truncationPoint); |
170 | } |
171 | |
172 | private: |
173 | void swap(unsigned index1, unsigned index2) |
174 | { |
175 | const Font* f = m_font[index1]; |
176 | m_font[index1] = m_font[index2]; |
177 | m_font[index2] = f; |
178 | |
179 | GlyphBufferGlyph g = m_glyphs[index1]; |
180 | m_glyphs[index1] = m_glyphs[index2]; |
181 | m_glyphs[index2] = g; |
182 | |
183 | GlyphBufferAdvance s = m_advances[index1]; |
184 | m_advances[index1] = m_advances[index2]; |
185 | m_advances[index2] = s; |
186 | } |
187 | |
188 | Vector<const Font*, 2048> m_font; |
189 | Vector<GlyphBufferGlyph, 2048> m_glyphs; |
190 | Vector<GlyphBufferAdvance, 2048> m_advances; |
191 | GlyphBufferAdvance m_initialAdvance; |
192 | std::unique_ptr<Vector<unsigned, 2048>> m_offsetsInString; |
193 | }; |
194 | |
195 | } |
196 | |