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
41namespace WebCore {
42
43class Font;
44
45#if USE(WINGDI)
46typedef wchar_t GlyphBufferGlyph;
47#else
48typedef 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)
54struct GlyphBufferAdvance : CGSize {
55public:
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
72typedef FloatSize GlyphBufferAdvance;
73#endif
74
75class GlyphBuffer {
76public:
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
172private:
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