Migrate from ints to unsigneds when referring to indices into strings
[WebKit-https.git] / Source / WebCore / platform / graphics / GlyphBuffer.h
1 /*
2  * Copyright (C) 2006, 2009, 2011 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 #ifndef GlyphBuffer_h
31 #define GlyphBuffer_h
32
33 #include "FloatSize.h"
34 #include "Glyph.h"
35 #include <climits>
36 #include <wtf/Vector.h>
37
38 #if USE(CG)
39 #include <CoreGraphics/CGGeometry.h>
40 #endif
41
42 #if USE(CAIRO)
43 #include <cairo.h>
44 #endif
45
46 namespace WebCore {
47
48 class Font;
49
50 #if USE(CAIRO)
51 // FIXME: Why does Cairo use such a huge struct instead of just an offset into an array?
52 typedef cairo_glyph_t GlyphBufferGlyph;
53 #elif USE(WINGDI)
54 typedef wchar_t GlyphBufferGlyph;
55 #else
56 typedef Glyph GlyphBufferGlyph;
57 #endif
58
59 // CG uses CGSize instead of FloatSize so that the result of advances()
60 // can be passed directly to CGContextShowGlyphsWithAdvances in FontMac.mm
61 #if USE(CG)
62 struct GlyphBufferAdvance : CGSize {
63 public:
64     GlyphBufferAdvance() : CGSize(CGSizeZero) { }
65     GlyphBufferAdvance(CGSize size) : CGSize(size)
66     {
67     }
68
69     void setWidth(CGFloat width) { this->CGSize::width = width; }
70     CGFloat width() const { return this->CGSize::width; }
71     CGFloat height() const { return this->CGSize::height; }
72 };
73 #else
74 typedef FloatSize GlyphBufferAdvance;
75 #endif
76
77 class GlyphBuffer {
78 public:
79     bool isEmpty() const { return m_font.isEmpty(); }
80     unsigned size() const { return m_font.size(); }
81     
82     void clear()
83     {
84         m_font.clear();
85         m_glyphs.clear();
86         m_advances.clear();
87         if (m_offsetsInString)
88             m_offsetsInString->clear();
89 #if PLATFORM(WIN)
90         m_offsets.clear();
91 #endif
92     }
93
94     GlyphBufferGlyph* glyphs(unsigned from) { return m_glyphs.data() + from; }
95     GlyphBufferAdvance* advances(unsigned from) { return m_advances.data() + from; }
96     const GlyphBufferGlyph* glyphs(unsigned from) const { return m_glyphs.data() + from; }
97     const GlyphBufferAdvance* advances(unsigned from) const { return m_advances.data() + from; }
98
99     const Font* fontAt(unsigned index) const { return m_font[index]; }
100
101     void setInitialAdvance(GlyphBufferAdvance initialAdvance) { m_initialAdvance = initialAdvance; }
102     const GlyphBufferAdvance& initialAdvance() const { return m_initialAdvance; }
103
104     void setLeadingExpansion(float leadingExpansion) { m_leadingExpansion = leadingExpansion; }
105     float leadingExpansion() const { return m_leadingExpansion; }
106     
107     Glyph glyphAt(unsigned index) const
108     {
109 #if USE(CAIRO)
110         return m_glyphs[index].index;
111 #else
112         return m_glyphs[index];
113 #endif
114     }
115
116     GlyphBufferAdvance advanceAt(unsigned index) const
117     {
118         return m_advances[index];
119     }
120
121     FloatSize offsetAt(unsigned index) const
122     {
123 #if PLATFORM(WIN)
124         return m_offsets[index];
125 #else
126         UNUSED_PARAM(index);
127         return FloatSize();
128 #endif
129     }
130     
131     static const unsigned noOffset = UINT_MAX;
132     void add(Glyph glyph, const Font* font, float width, unsigned offsetInString = noOffset, const FloatSize* offset = 0)
133     {
134         m_font.append(font);
135
136 #if USE(CAIRO)
137         cairo_glyph_t cairoGlyph;
138         cairoGlyph.index = glyph;
139         m_glyphs.append(cairoGlyph);
140 #else
141         m_glyphs.append(glyph);
142 #endif
143
144 #if USE(CG)
145         CGSize advance = { width, 0 };
146         m_advances.append(advance);
147 #else
148         m_advances.append(FloatSize(width, 0));
149 #endif
150
151 #if PLATFORM(WIN)
152         if (offset)
153             m_offsets.append(*offset);
154         else
155             m_offsets.append(FloatSize());
156 #else
157         UNUSED_PARAM(offset);
158 #endif
159         
160         if (offsetInString != noOffset && m_offsetsInString)
161             m_offsetsInString->append(offsetInString);
162     }
163     
164 #if !USE(WINGDI)
165     void add(Glyph glyph, const Font* font, GlyphBufferAdvance advance, unsigned offsetInString = noOffset)
166     {
167         m_font.append(font);
168 #if USE(CAIRO)
169         cairo_glyph_t cairoGlyph;
170         cairoGlyph.index = glyph;
171         m_glyphs.append(cairoGlyph);
172 #else
173         m_glyphs.append(glyph);
174 #endif
175
176         m_advances.append(advance);
177         
178         if (offsetInString != noOffset && m_offsetsInString)
179             m_offsetsInString->append(offsetInString);
180     }
181 #endif
182
183     void reverse(unsigned from, unsigned length)
184     {
185         for (unsigned i = from, end = from + length - 1; i < end; ++i, --end)
186             swap(i, end);
187     }
188
189     void expandLastAdvance(float width)
190     {
191         ASSERT(!isEmpty());
192         GlyphBufferAdvance& lastAdvance = m_advances.last();
193         lastAdvance.setWidth(lastAdvance.width() + width);
194     }
195     
196     void saveOffsetsInString()
197     {
198         m_offsetsInString.reset(new Vector<unsigned, 2048>());
199     }
200
201     int offsetInString(unsigned index) const
202     {
203         ASSERT(m_offsetsInString);
204         return (*m_offsetsInString)[index];
205     }
206
207     void shrink(unsigned truncationPoint)
208     {
209         m_font.shrink(truncationPoint);
210         m_glyphs.shrink(truncationPoint);
211         m_advances.shrink(truncationPoint);
212         if (m_offsetsInString)
213             m_offsetsInString->shrink(truncationPoint);
214 #if PLATFORM(WIN)
215         m_offsets.shrink(truncationPoint);
216 #endif
217     }
218
219 private:
220     void swap(unsigned index1, unsigned index2)
221     {
222         const Font* f = m_font[index1];
223         m_font[index1] = m_font[index2];
224         m_font[index2] = f;
225
226         GlyphBufferGlyph g = m_glyphs[index1];
227         m_glyphs[index1] = m_glyphs[index2];
228         m_glyphs[index2] = g;
229
230         GlyphBufferAdvance s = m_advances[index1];
231         m_advances[index1] = m_advances[index2];
232         m_advances[index2] = s;
233
234 #if PLATFORM(WIN)
235         FloatSize offset = m_offsets[index1];
236         m_offsets[index1] = m_offsets[index2];
237         m_offsets[index2] = offset;
238 #endif
239     }
240
241     Vector<const Font*, 2048> m_font;
242     Vector<GlyphBufferGlyph, 2048> m_glyphs;
243     Vector<GlyphBufferAdvance, 2048> m_advances;
244     GlyphBufferAdvance m_initialAdvance;
245     std::unique_ptr<Vector<unsigned, 2048>> m_offsetsInString;
246 #if PLATFORM(WIN)
247     Vector<FloatSize, 2048> m_offsets;
248 #endif
249     float m_leadingExpansion;
250 };
251
252 }
253 #endif