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 Computer, 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/UnusedParam.h>
36 #include <wtf/Vector.h>
37 
38 #if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
39 #include <CoreGraphics/CGGeometry.h>
40 #endif
41 
42 #if USE(CAIRO) || (PLATFORM(WX) && defined(__WXGTK__))
43 #include <cairo.h>
44 #endif
45 
46 namespace WebCore {
47 
48 class SimpleFontData;
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 OS(WINCE)
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) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
62 typedef CGSize GlyphBufferAdvance;
63 #elif OS(WINCE)
64 // There is no cross-platform code that uses the height of GlyphBufferAdvance,
65 // so we can save memory space on embedded devices by storing only the width
66 typedef float GlyphBufferAdvance;
67 #else
68 typedef FloatSize GlyphBufferAdvance;
69 #endif
70 
71 class GlyphBuffer {
72 public:
isEmpty()73     bool isEmpty() const { return m_fontData.isEmpty(); }
size()74     int size() const { return m_fontData.size(); }
75 
clear()76     void clear()
77     {
78         m_fontData.clear();
79         m_glyphs.clear();
80         m_advances.clear();
81 #if PLATFORM(WIN)
82         m_offsets.clear();
83 #endif
84     }
85 
glyphs(int from)86     GlyphBufferGlyph* glyphs(int from) { return m_glyphs.data() + from; }
advances(int from)87     GlyphBufferAdvance* advances(int from) { return m_advances.data() + from; }
glyphs(int from)88     const GlyphBufferGlyph* glyphs(int from) const { return m_glyphs.data() + from; }
advances(int from)89     const GlyphBufferAdvance* advances(int from) const { return m_advances.data() + from; }
90 
fontDataAt(int index)91     const SimpleFontData* fontDataAt(int index) const { return m_fontData[index]; }
92 
swap(int index1,int index2)93     void swap(int index1, int index2)
94     {
95         const SimpleFontData* f = m_fontData[index1];
96         m_fontData[index1] = m_fontData[index2];
97         m_fontData[index2] = f;
98 
99         GlyphBufferGlyph g = m_glyphs[index1];
100         m_glyphs[index1] = m_glyphs[index2];
101         m_glyphs[index2] = g;
102 
103         GlyphBufferAdvance s = m_advances[index1];
104         m_advances[index1] = m_advances[index2];
105         m_advances[index2] = s;
106 
107 #if PLATFORM(WIN)
108         FloatSize offset = m_offsets[index1];
109         m_offsets[index1] = m_offsets[index2];
110         m_offsets[index2] = offset;
111 #endif
112     }
113 
glyphAt(int index)114     Glyph glyphAt(int index) const
115     {
116 #if USE(CAIRO)
117         return m_glyphs[index].index;
118 #else
119         return m_glyphs[index];
120 #endif
121     }
122 
advanceAt(int index)123     float advanceAt(int index) const
124     {
125 #if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
126         return m_advances[index].width;
127 #elif OS(WINCE)
128         return m_advances[index];
129 #else
130         return m_advances[index].width();
131 #endif
132     }
133 
offsetAt(int index)134     FloatSize offsetAt(int index) const
135     {
136 #if PLATFORM(WIN)
137         return m_offsets[index];
138 #else
139         UNUSED_PARAM(index);
140         return FloatSize();
141 #endif
142     }
143 
144     void add(Glyph glyph, const SimpleFontData* font, float width, const FloatSize* offset = 0)
145     {
146         m_fontData.append(font);
147 
148 #if USE(CAIRO)
149         cairo_glyph_t cairoGlyph;
150         cairoGlyph.index = glyph;
151         m_glyphs.append(cairoGlyph);
152 #else
153         m_glyphs.append(glyph);
154 #endif
155 
156 #if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
157         CGSize advance = { width, 0 };
158         m_advances.append(advance);
159 #elif OS(WINCE)
160         m_advances.append(width);
161 #else
162         m_advances.append(FloatSize(width, 0));
163 #endif
164 
165 #if PLATFORM(WIN)
166         if (offset)
167             m_offsets.append(*offset);
168         else
169             m_offsets.append(FloatSize());
170 #else
171         UNUSED_PARAM(offset);
172 #endif
173     }
174 
175 #if !OS(WINCE)
add(Glyph glyph,const SimpleFontData * font,GlyphBufferAdvance advance)176     void add(Glyph glyph, const SimpleFontData* font, GlyphBufferAdvance advance)
177     {
178         m_fontData.append(font);
179 #if USE(CAIRO)
180         cairo_glyph_t cairoGlyph;
181         cairoGlyph.index = glyph;
182         m_glyphs.append(cairoGlyph);
183 #else
184         m_glyphs.append(glyph);
185 #endif
186 
187         m_advances.append(advance);
188     }
189 #endif
190 
expandLastAdvance(float width)191     void expandLastAdvance(float width)
192     {
193         ASSERT(!isEmpty());
194         GlyphBufferAdvance& lastAdvance = m_advances.last();
195 #if USE(CG) || (PLATFORM(WX) && OS(DARWIN)) || USE(SKIA_ON_MAC_CHROME)
196         lastAdvance.width += width;
197 #elif OS(WINCE)
198         lastAdvance += width;
199 #else
200         lastAdvance += FloatSize(width, 0);
201 #endif
202     }
203 
204 private:
205     Vector<const SimpleFontData*, 2048> m_fontData;
206     Vector<GlyphBufferGlyph, 2048> m_glyphs;
207     Vector<GlyphBufferAdvance, 2048> m_advances;
208 #if PLATFORM(WIN)
209     Vector<FloatSize, 2048> m_offsets;
210 #endif
211 };
212 
213 }
214 #endif
215