2 * Copyright (C) 2006, 2007, 2008, 2013 Apple Inc. All rights reserved.
3 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
33 #include "platform/PlatformExport.h"
34 #include "platform/fonts/CustomFontData.h"
35 #include "platform/fonts/Glyph.h"
36 #include "wtf/PassRefPtr.h"
37 #include "wtf/RefCounted.h"
38 #include "wtf/RefPtr.h"
39 #include "wtf/text/Unicode.h"
45 class GlyphPageTreeNodeBase
;
47 // Holds the glyph index and the corresponding SimpleFontData information for a given
50 GlyphData(Glyph g
= 0, const SimpleFontData
* f
= 0)
56 const SimpleFontData
* fontData
;
61 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning
64 // A GlyphPage contains a fixed-size set of GlyphData mappings for a contiguous
65 // range of characters in the Unicode code space. GlyphPages are indexed
66 // starting from 0 and incrementing for each 256 glyphs.
68 // One page may actually include glyphs from other fonts if the characters are
69 // missing in the primary font. It is owned by exactly one GlyphPageTreeNode,
70 // although multiple nodes may reference it as their "page" if they are supposed
71 // to be overriding the parent's node, but provide no additional information.
72 class PLATFORM_EXPORT GlyphPage
: public RefCounted
<GlyphPage
> {
74 static PassRefPtr
<GlyphPage
> createForMixedFontData(GlyphPageTreeNodeBase
* owner
)
76 void* slot
= fastMalloc(sizeof(GlyphPage
) + sizeof(SimpleFontData
*) * GlyphPage::size
);
77 return adoptRef(new (slot
) GlyphPage(owner
));
80 static PassRefPtr
<GlyphPage
> createForSingleFontData(GlyphPageTreeNodeBase
* owner
, const SimpleFontData
* fontData
)
83 return adoptRef(new GlyphPage(owner
, fontData
));
86 PassRefPtr
<GlyphPage
> createCopiedSystemFallbackPage(GlyphPageTreeNodeBase
* owner
) const
88 RefPtr
<GlyphPage
> page
= GlyphPage::createForMixedFontData(owner
);
89 memcpy(page
->m_glyphs
, m_glyphs
, sizeof(m_glyphs
));
90 if (hasPerGlyphFontData())
91 memcpy(page
->m_perGlyphFontData
, m_perGlyphFontData
, sizeof(SimpleFontData
*) * GlyphPage::size
);
93 for (size_t i
= 0; i
< GlyphPage::size
; ++i
) {
94 page
->m_perGlyphFontData
[i
] = m_glyphs
[i
] ? m_fontDataForAllGlyphs
: 0;
97 page
->m_customFontToLoad
= m_customFontToLoad
;
98 return page
.release();
103 static const unsigned char sizeBits
= 8;
104 static const size_t size
= (1 << GlyphPage::sizeBits
); // Covers Latin-1 in a single page.
105 static unsigned indexForCharacter(UChar32 c
) { return c
& 0xFF; }
107 ALWAYS_INLINE GlyphData
glyphDataForCharacter(UChar32 c
) const
109 unsigned index
= indexForCharacter(c
);
110 if (const CustomFontData
* customData
= customFontToLoadAt(index
))
111 customData
->beginLoadIfNeeded();
112 return glyphDataForIndex(index
);
115 ALWAYS_INLINE GlyphData
glyphDataForIndex(unsigned index
) const
117 ASSERT_WITH_SECURITY_IMPLICATION(index
< size
);
118 Glyph glyph
= m_glyphs
[index
];
119 if (hasPerGlyphFontData())
120 return GlyphData(glyph
, m_perGlyphFontData
[index
]);
121 return GlyphData(glyph
, glyph
? m_fontDataForAllGlyphs
: 0);
124 ALWAYS_INLINE Glyph
glyphForCharacter(UChar32 c
) const
126 return glyphAt(indexForCharacter(c
));
129 ALWAYS_INLINE Glyph
glyphAt(unsigned index
) const
131 ASSERT_WITH_SECURITY_IMPLICATION(index
< size
);
132 return m_glyphs
[index
];
135 void setGlyphDataForCharacter(UChar32 c
, Glyph g
, const SimpleFontData
* f
)
137 setGlyphDataForIndex(indexForCharacter(c
), g
, f
);
140 void setGlyphDataForIndex(unsigned index
, Glyph glyph
, const SimpleFontData
* fontData
)
142 ASSERT_WITH_SECURITY_IMPLICATION(index
< size
);
143 m_glyphs
[index
] = glyph
;
144 setCustomFontToLoad(index
, 0);
146 if (hasPerGlyphFontData()) {
147 m_perGlyphFontData
[index
] = fontData
;
149 // A single-font GlyphPage already assigned m_fontDataForAllGlyphs in the constructor.
150 ASSERT(!glyph
|| fontData
== m_fontDataForAllGlyphs
);
154 void setGlyphDataForIndex(unsigned index
, const GlyphData
& glyphData
)
156 setGlyphDataForIndex(index
, glyphData
.glyph
, glyphData
.fontData
);
159 const CustomFontData
* customFontToLoadAt(unsigned index
) const
161 ASSERT_WITH_SECURITY_IMPLICATION(index
< size
);
162 return m_customFontToLoad
? m_customFontToLoad
->at(index
) : 0;
165 void setCustomFontToLoad(unsigned index
, const CustomFontData
* customFontToLoad
)
167 if (!m_customFontToLoad
) {
168 if (!customFontToLoad
)
170 m_customFontToLoad
= CustomDataPage::create();
172 ASSERT_WITH_SECURITY_IMPLICATION(index
< size
);
173 m_customFontToLoad
->set(index
, customFontToLoad
);
176 void removePerGlyphFontData(const SimpleFontData
* fontData
)
178 // This method should only be called on the mixed page, which is never single-font.
179 ASSERT(hasPerGlyphFontData());
180 for (size_t i
= 0; i
< size
; ++i
) {
181 if (m_perGlyphFontData
[i
] == fontData
) {
183 m_perGlyphFontData
[i
] = 0;
188 GlyphPageTreeNodeBase
* owner() const { return m_owner
; }
190 bool hasPerGlyphFontData() const { return !m_fontDataForAllGlyphs
; }
193 explicit GlyphPage(GlyphPageTreeNodeBase
* owner
, const SimpleFontData
* fontDataForAllGlyphs
= 0)
194 : m_fontDataForAllGlyphs(fontDataForAllGlyphs
)
197 memset(m_glyphs
, 0, sizeof(m_glyphs
));
198 if (hasPerGlyphFontData())
199 memset(m_perGlyphFontData
, 0, sizeof(SimpleFontData
*) * GlyphPage::size
);
202 class CustomDataPage
: public RefCounted
<CustomDataPage
> {
204 static RefPtr
<CustomDataPage
> create() { return adoptRef(new CustomDataPage()); }
205 const CustomFontData
* at(size_t index
) const { return m_customData
[index
]; }
206 void set(size_t index
, const CustomFontData
* data
) { m_customData
[index
] = data
; }
208 CustomDataPage() { memset(m_customData
, 0, sizeof(m_customData
)); }
209 const CustomFontData
* m_customData
[size
];
212 const SimpleFontData
* m_fontDataForAllGlyphs
;
213 GlyphPageTreeNodeBase
* m_owner
;
214 RefPtr
<CustomDataPage
> m_customFontToLoad
;
215 Glyph m_glyphs
[size
];
217 // NOTE: This array has (GlyphPage::size) elements if m_fontDataForAllGlyphs is null.
218 const SimpleFontData
* m_perGlyphFontData
[0];
227 #endif // GlyphPage_h