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