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 45namespace WebCore { 46 47class SimpleFontData; 48 49#if USE(CAIRO) 50// FIXME: Why does Cairo use such a huge struct instead of just an offset into an array? 51typedef cairo_glyph_t GlyphBufferGlyph; 52#elif USE(WINGDI) 53typedef wchar_t GlyphBufferGlyph; 54#else 55typedef 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) 61struct GlyphBufferAdvance : CGSize { 62public: 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 73typedef FloatSize GlyphBufferAdvance; 74#endif 75 76class GlyphBuffer { 77public: 78 bool isEmpty() const { return m_fontData.isEmpty(); } 79 int 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(int from) { return m_glyphs.data() + from; } 94 GlyphBufferAdvance* advances(int from) { return m_advances.data() + from; } 95 const GlyphBufferGlyph* glyphs(int from) const { return m_glyphs.data() + from; } 96 const GlyphBufferAdvance* advances(int from) const { return m_advances.data() + from; } 97 98 const SimpleFontData* fontDataAt(int 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(int index) const 113 { 114 return m_advances[index]; 115 } 116 117 FloatSize offsetAt(int 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(int from, int 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(int index) const 198 { 199 ASSERT(m_offsetsInString); 200 return (*m_offsetsInString)[index]; 201 } 202 203private: 204 void swap(int index1, int 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 237