Optimize GlyphPage for case where all glyphs are available in the same font.
[WebKit-https.git] / Source / WebCore / platform / graphics / GlyphPage.h
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
3  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
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 GlyphPage_h
31 #define GlyphPage_h
32
33 #include "Glyph.h"
34 #include <wtf/PassRefPtr.h>
35 #include <wtf/RefCounted.h>
36 #include <wtf/RefPtr.h>
37 #include <wtf/unicode/Unicode.h>
38
39 namespace WebCore {
40
41 class SimpleFontData;
42 class GlyphPageTreeNode;
43
44 // Holds the glyph index and the corresponding SimpleFontData information for a given
45 // character.
46 struct GlyphData {
47     GlyphData(Glyph g = 0, const SimpleFontData* f = 0)
48         : glyph(g)
49         , fontData(f)
50     {
51     }
52     Glyph glyph;
53     const SimpleFontData* fontData;
54 };
55
56 // A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
57 // range of characters in the Unicode code space. GlyphPages are indexed
58 // starting from 0 and incrementing for each 256 glyphs.
59 //
60 // One page may actually include glyphs from other fonts if the characters are
61 // missing in the primary font. It is owned by exactly one GlyphPageTreeNode,
62 // although multiple nodes may reference it as their "page" if they are supposed
63 // to be overriding the parent's node, but provide no additional information.
64 class GlyphPage : public RefCounted<GlyphPage> {
65 public:
66     static PassRefPtr<GlyphPage> createUninitialized(GlyphPageTreeNode* owner)
67     {
68         return adoptRef(new GlyphPage(owner, false));
69     }
70
71     static PassRefPtr<GlyphPage> createZeroedSystemFallbackPage(GlyphPageTreeNode* owner)
72     {
73         return adoptRef(new GlyphPage(owner, true));
74     }
75
76     PassRefPtr<GlyphPage> createCopiedSystemFallbackPage(GlyphPageTreeNode* owner) const
77     {
78         RefPtr<GlyphPage> page = GlyphPage::createUninitialized(owner);
79         memcpy(page->m_glyphs, m_glyphs, sizeof(m_glyphs));
80         page->m_fontDataForAllGlyphs = m_fontDataForAllGlyphs;
81         if (m_perGlyphFontData) {
82             page->m_perGlyphFontData = static_cast<const SimpleFontData**>(fastMalloc(size * sizeof(SimpleFontData*)));
83             memcpy(page->m_perGlyphFontData, m_perGlyphFontData, size * sizeof(SimpleFontData*));
84         }
85         return page.release();
86     }
87
88     ~GlyphPage()
89     {
90         if (m_perGlyphFontData)
91             fastFree(m_perGlyphFontData);
92     }
93
94     static const size_t size = 256; // Covers Latin-1 in a single page.
95
96     unsigned indexForCharacter(UChar32 c) const { return c % size; }
97     GlyphData glyphDataForCharacter(UChar32 c) const
98     {
99         return glyphDataForIndex(indexForCharacter(c));
100     }
101
102     GlyphData glyphDataForIndex(unsigned index) const
103     {
104         ASSERT_WITH_SECURITY_IMPLICATION(index < size);
105         Glyph glyph = m_glyphs[index];
106         if (!glyph)
107             return GlyphData(0, 0);
108         if (m_perGlyphFontData)
109             return GlyphData(glyph, m_perGlyphFontData[index]);
110         return GlyphData(glyph, m_fontDataForAllGlyphs);
111     }
112
113     Glyph glyphAt(unsigned index) const
114     {
115         ASSERT_WITH_SECURITY_IMPLICATION(index < size);
116         return m_glyphs[index];
117     }
118
119     const SimpleFontData* fontDataForCharacter(UChar32 c) const
120     {
121         return glyphDataForIndex(indexForCharacter(c)).fontData;
122     }
123
124     void setGlyphDataForCharacter(UChar32 c, Glyph g, const SimpleFontData* f)
125     {
126         setGlyphDataForIndex(indexForCharacter(c), g, f);
127     }
128
129     void setGlyphDataForIndex(unsigned index, Glyph glyph, const SimpleFontData* fontData)
130     {
131         ASSERT_WITH_SECURITY_IMPLICATION(index < size);
132         m_glyphs[index] = glyph;
133
134         // GlyphPage getters will always return a null SimpleFontData* for glyph #0, so don't worry about the pointer for them.
135         if (!glyph)
136             return;
137
138         // A glyph index without a font data pointer makes no sense.
139         ASSERT(fontData);
140
141         if (m_perGlyphFontData) {
142             m_perGlyphFontData[index] = fontData;
143             return;
144         }
145
146         if (!m_fontDataForAllGlyphs)
147             m_fontDataForAllGlyphs = fontData;
148
149         if (m_fontDataForAllGlyphs == fontData)
150             return;
151
152         // This GlyphPage houses glyphs from multiple fonts, transition to an array of SimpleFontData pointers.
153         const SimpleFontData* oldFontData = m_fontDataForAllGlyphs;
154         m_perGlyphFontData = static_cast<const SimpleFontData**>(fastMalloc(size * sizeof(SimpleFontData*)));
155         for (unsigned i = 0; i < size; ++i)
156             m_perGlyphFontData[i] = oldFontData;
157         m_perGlyphFontData[index] = fontData;
158     }
159
160     void setGlyphDataForIndex(unsigned index, const GlyphData& glyphData)
161     {
162         setGlyphDataForIndex(index, glyphData.glyph, glyphData.fontData);
163     }
164
165     void clearForFontData(const SimpleFontData* fontData)
166     {
167         if (!m_perGlyphFontData) {
168             if (m_fontDataForAllGlyphs == fontData) {
169                 memset(m_glyphs, 0, sizeof(m_glyphs));
170                 m_fontDataForAllGlyphs = 0;
171             }
172             return;
173         }
174         for (size_t i = 0; i < size; ++i) {
175             if (m_perGlyphFontData[i] == fontData) {
176                 m_glyphs[i] = 0;
177                 m_perGlyphFontData[i] = 0;
178             }
179         }
180     }
181
182     GlyphPageTreeNode* owner() const { return m_owner; }
183
184     // Implemented by the platform.
185     bool fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData*);
186
187 private:
188     GlyphPage(GlyphPageTreeNode* owner, bool clearGlyphs)
189         : m_fontDataForAllGlyphs(0)
190         , m_perGlyphFontData(0)
191         , m_owner(owner)
192     {
193         if (clearGlyphs)
194             memset(m_glyphs, 0, sizeof(m_glyphs));
195     }
196
197     const SimpleFontData* m_fontDataForAllGlyphs;
198     const SimpleFontData** m_perGlyphFontData;
199
200     GlyphPageTreeNode* m_owner;
201     Glyph m_glyphs[size];
202 };
203
204 } // namespace WebCore
205
206 #endif // GlyphPage_h