1/*
2 * This file is part of the internal font implementation.
3 *
4 * Copyright (C) 2006, 2008, 2010 Apple Inc. All rights reserved.
5 * Copyright (C) 2007-2008 Torch Mobile, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB.  If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#ifndef SimpleFontData_h
25#define SimpleFontData_h
26
27#include "core/platform/graphics/FloatRect.h"
28#include "core/platform/graphics/FontBaseline.h"
29#include "core/platform/graphics/FontData.h"
30#include "core/platform/graphics/FontMetrics.h"
31#include "core/platform/graphics/FontPlatformData.h"
32#include "core/platform/graphics/GlyphBuffer.h"
33#include "core/platform/graphics/GlyphMetricsMap.h"
34#include "core/platform/graphics/GlyphPageTreeNode.h"
35#if ENABLE(OPENTYPE_VERTICAL)
36#include "core/platform/graphics/opentype/OpenTypeVerticalData.h"
37#endif
38#include "core/platform/graphics/TypesettingFeatures.h"
39#include "wtf/OwnPtr.h"
40#include "wtf/PassOwnPtr.h"
41#include "wtf/text/StringHash.h"
42#include "wtf/UnusedParam.h"
43
44#if OS(DARWIN)
45#include "wtf/RetainPtr.h"
46#endif
47
48namespace WebCore {
49
50class FontDescription;
51class SharedBuffer;
52struct WidthIterator;
53
54enum FontDataVariant { AutoVariant, NormalVariant, SmallCapsVariant, EmphasisMarkVariant, BrokenIdeographVariant };
55enum Pitch { UnknownPitch, FixedPitch, VariablePitch };
56
57class SimpleFontData : public FontData {
58public:
59    class AdditionalFontData {
60        WTF_MAKE_FAST_ALLOCATED;
61    public:
62        virtual ~AdditionalFontData() { }
63
64        virtual void initializeFontData(SimpleFontData*, float fontSize) = 0;
65        virtual float widthForSVGGlyph(Glyph, float fontSize) const = 0;
66        virtual bool fillSVGGlyphPage(GlyphPage*, unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData*) const = 0;
67        virtual bool applySVGGlyphSelection(WidthIterator&, GlyphData&, bool mirror, int currentCharacter, unsigned& advanceLength) const = 0;
68    };
69
70    // Used to create platform fonts.
71    static PassRefPtr<SimpleFontData> create(const FontPlatformData& platformData, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false)
72    {
73        return adoptRef(new SimpleFontData(platformData, isCustomFont, isLoading, isTextOrientationFallback));
74    }
75
76    // Used to create SVG Fonts.
77    static PassRefPtr<SimpleFontData> create(PassOwnPtr<AdditionalFontData> fontData, float fontSize, bool syntheticBold, bool syntheticItalic)
78    {
79        return adoptRef(new SimpleFontData(fontData, fontSize, syntheticBold, syntheticItalic));
80    }
81
82    virtual ~SimpleFontData();
83
84    static const SimpleFontData* systemFallback() { return reinterpret_cast<const SimpleFontData*>(-1); }
85
86    const FontPlatformData& platformData() const { return m_platformData; }
87#if ENABLE(OPENTYPE_VERTICAL)
88    const OpenTypeVerticalData* verticalData() const { return m_verticalData.get(); }
89#endif
90
91    PassRefPtr<SimpleFontData> smallCapsFontData(const FontDescription&) const;
92    PassRefPtr<SimpleFontData> emphasisMarkFontData(const FontDescription&) const;
93    PassRefPtr<SimpleFontData> brokenIdeographFontData() const;
94
95    PassRefPtr<SimpleFontData> variantFontData(const FontDescription& description, FontDataVariant variant) const
96    {
97        switch (variant) {
98        case SmallCapsVariant:
99            return smallCapsFontData(description);
100        case EmphasisMarkVariant:
101            return emphasisMarkFontData(description);
102        case BrokenIdeographVariant:
103            return brokenIdeographFontData();
104        case AutoVariant:
105        case NormalVariant:
106            break;
107        }
108        ASSERT_NOT_REACHED();
109        return const_cast<SimpleFontData*>(this);
110    }
111
112    PassRefPtr<SimpleFontData> verticalRightOrientationFontData() const;
113    PassRefPtr<SimpleFontData> uprightOrientationFontData() const;
114
115    bool hasVerticalGlyphs() const { return m_hasVerticalGlyphs; }
116    bool isTextOrientationFallback() const { return m_isTextOrientationFallback; }
117
118    FontMetrics& fontMetrics() { return m_fontMetrics; }
119    const FontMetrics& fontMetrics() const { return m_fontMetrics; }
120    float sizePerUnit() const { return platformData().size() / (fontMetrics().unitsPerEm() ? fontMetrics().unitsPerEm() : 1); }
121
122    float maxCharWidth() const { return m_maxCharWidth; }
123    void setMaxCharWidth(float maxCharWidth) { m_maxCharWidth = maxCharWidth; }
124
125    float avgCharWidth() const { return m_avgCharWidth; }
126    void setAvgCharWidth(float avgCharWidth) { m_avgCharWidth = avgCharWidth; }
127
128    FloatRect boundsForGlyph(Glyph) const;
129    float widthForGlyph(Glyph glyph) const;
130    FloatRect platformBoundsForGlyph(Glyph) const;
131    float platformWidthForGlyph(Glyph) const;
132
133    float spaceWidth() const { return m_spaceWidth; }
134    float adjustedSpaceWidth() const { return m_adjustedSpaceWidth; }
135    void setSpaceWidth(float spaceWidth) { m_spaceWidth = spaceWidth; }
136
137#if OS(DARWIN)
138    float syntheticBoldOffset() const { return m_syntheticBoldOffset; }
139#endif
140
141    Glyph spaceGlyph() const { return m_spaceGlyph; }
142    void setSpaceGlyph(Glyph spaceGlyph) { m_spaceGlyph = spaceGlyph; }
143    Glyph zeroWidthSpaceGlyph() const { return m_zeroWidthSpaceGlyph; }
144    void setZeroWidthSpaceGlyph(Glyph spaceGlyph) { m_zeroWidthSpaceGlyph = spaceGlyph; }
145    bool isZeroWidthSpaceGlyph(Glyph glyph) const { return glyph == m_zeroWidthSpaceGlyph && glyph; }
146    Glyph zeroGlyph() const { return m_zeroGlyph; }
147    void setZeroGlyph(Glyph zeroGlyph) { m_zeroGlyph = zeroGlyph; }
148
149    virtual const SimpleFontData* fontDataForCharacter(UChar32) const;
150    virtual bool containsCharacters(const UChar*, int length) const;
151
152    Glyph glyphForCharacter(UChar32) const;
153
154    void determinePitch();
155    Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
156
157    AdditionalFontData* fontData() const { return m_fontData.get(); }
158    bool isSVGFont() const { return m_fontData; }
159
160    virtual bool isCustomFont() const { return m_isCustomFont; }
161    virtual bool isLoading() const { return m_isLoading; }
162    virtual bool isSegmented() const;
163
164    const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
165    void setMissingGlyphData(const GlyphData& glyphData) { m_missingGlyphData = glyphData; }
166
167#ifndef NDEBUG
168    virtual String description() const;
169#endif
170
171#if OS(DARWIN)
172    const SimpleFontData* getCompositeFontReferenceFontData(NSFont *key) const;
173    NSFont* getNSFont() const { return m_platformData.font(); }
174#endif
175
176#if OS(DARWIN)
177    CFDictionaryRef getCFStringAttributes(TypesettingFeatures, FontOrientation) const;
178#endif
179
180#if OS(DARWIN) || USE(HARFBUZZ)
181    bool canRenderCombiningCharacterSequence(const UChar*, size_t) const;
182#endif
183
184    bool applyTransforms(GlyphBufferGlyph* glyphs, GlyphBufferAdvance* advances, size_t glyphCount, TypesettingFeatures typesettingFeatures) const
185    {
186        UNUSED_PARAM(glyphs);
187        UNUSED_PARAM(advances);
188        UNUSED_PARAM(glyphCount);
189        UNUSED_PARAM(typesettingFeatures);
190        return false;
191    }
192
193private:
194    SimpleFontData(const FontPlatformData&, bool isCustomFont = false, bool isLoading = false, bool isTextOrientationFallback = false);
195
196    SimpleFontData(PassOwnPtr<AdditionalFontData> , float fontSize, bool syntheticBold, bool syntheticItalic);
197
198    void platformInit();
199    void platformGlyphInit();
200    void platformCharWidthInit();
201    void platformDestroy();
202
203    void initCharWidths();
204
205    PassRefPtr<SimpleFontData> createScaledFontData(const FontDescription&, float scaleFactor) const;
206    PassRefPtr<SimpleFontData> platformCreateScaledFontData(const FontDescription&, float scaleFactor) const;
207
208    FontMetrics m_fontMetrics;
209    float m_maxCharWidth;
210    float m_avgCharWidth;
211
212    FontPlatformData m_platformData;
213    OwnPtr<AdditionalFontData> m_fontData;
214
215    mutable OwnPtr<GlyphMetricsMap<FloatRect> > m_glyphToBoundsMap;
216    mutable GlyphMetricsMap<float> m_glyphToWidthMap;
217
218    bool m_treatAsFixedPitch;
219    bool m_isCustomFont;  // Whether or not we are custom font loaded via @font-face
220    bool m_isLoading; // Whether or not this custom font is still in the act of loading.
221
222    bool m_isTextOrientationFallback;
223    bool m_isBrokenIdeographFallback;
224#if ENABLE(OPENTYPE_VERTICAL)
225    RefPtr<OpenTypeVerticalData> m_verticalData;
226#endif
227    bool m_hasVerticalGlyphs;
228
229    Glyph m_spaceGlyph;
230    float m_spaceWidth;
231    Glyph m_zeroGlyph;
232    float m_adjustedSpaceWidth;
233
234    Glyph m_zeroWidthSpaceGlyph;
235
236    GlyphData m_missingGlyphData;
237
238    struct DerivedFontData {
239        static PassOwnPtr<DerivedFontData> create(bool forCustomFont);
240        ~DerivedFontData();
241
242        bool forCustomFont;
243        RefPtr<SimpleFontData> smallCaps;
244        RefPtr<SimpleFontData> emphasisMark;
245        RefPtr<SimpleFontData> brokenIdeograph;
246        RefPtr<SimpleFontData> verticalRightOrientation;
247        RefPtr<SimpleFontData> uprightOrientation;
248#if OS(DARWIN)
249        mutable RetainPtr<CFMutableDictionaryRef> compositeFontReferences;
250#endif
251
252    private:
253        DerivedFontData(bool custom)
254            : forCustomFont(custom)
255        {
256        }
257    };
258
259    mutable OwnPtr<DerivedFontData> m_derivedFontData;
260
261#if OS(DARWIN)
262    float m_syntheticBoldOffset;
263
264    mutable HashMap<unsigned, RetainPtr<CFDictionaryRef> > m_CFStringAttributes;
265#endif
266
267#if OS(DARWIN) || USE(HARFBUZZ)
268    mutable OwnPtr<HashMap<String, bool> > m_combiningCharacterSequenceSupport;
269#endif
270};
271
272ALWAYS_INLINE FloatRect SimpleFontData::boundsForGlyph(Glyph glyph) const
273{
274    if (isZeroWidthSpaceGlyph(glyph))
275        return FloatRect();
276
277    FloatRect bounds;
278    if (m_glyphToBoundsMap) {
279        bounds = m_glyphToBoundsMap->metricsForGlyph(glyph);
280        if (bounds.width() != cGlyphSizeUnknown)
281            return bounds;
282    }
283
284    bounds = platformBoundsForGlyph(glyph);
285    if (!m_glyphToBoundsMap)
286        m_glyphToBoundsMap = adoptPtr(new GlyphMetricsMap<FloatRect>);
287    m_glyphToBoundsMap->setMetricsForGlyph(glyph, bounds);
288    return bounds;
289}
290
291ALWAYS_INLINE float SimpleFontData::widthForGlyph(Glyph glyph) const
292{
293    if (isZeroWidthSpaceGlyph(glyph))
294        return 0;
295
296    float width = m_glyphToWidthMap.metricsForGlyph(glyph);
297    if (width != cGlyphSizeUnknown)
298        return width;
299
300    if (m_fontData)
301        width = m_fontData->widthForSVGGlyph(glyph, m_platformData.size());
302#if ENABLE(OPENTYPE_VERTICAL)
303    else if (m_verticalData)
304#if OS(DARWIN)
305        width = m_verticalData->advanceHeight(this, glyph) + m_syntheticBoldOffset;
306#else
307        width = m_verticalData->advanceHeight(this, glyph);
308#endif
309#endif
310    else
311        width = platformWidthForGlyph(glyph);
312
313    m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
314    return width;
315}
316
317} // namespace WebCore
318#endif // SimpleFontData_h
319