1/*
2 * Copyright (c) 2006, 2007, 2008, 2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32
33#include "SkFontMgr.h"
34#include "SkTypeface.h"
35#include "platform/NotImplemented.h"
36#include "platform/fonts/AlternateFontFamily.h"
37#include "platform/fonts/FontCache.h"
38#include "platform/fonts/FontDescription.h"
39#include "platform/fonts/SimpleFontData.h"
40#include "wtf/Assertions.h"
41#include "wtf/text/AtomicString.h"
42#include "wtf/text/CString.h"
43#include <unicode/locid.h>
44
45namespace WebCore {
46
47void FontCache::platformInit()
48{
49}
50
51#if !OS(WIN) && !OS(ANDROID)
52PassRefPtr<SimpleFontData> FontCache::platformFallbackForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*, bool)
53{
54    icu::Locale locale = icu::Locale::getDefault();
55    FontCache::SimpleFontFamily family;
56    FontCache::getFontFamilyForCharacter(c, locale.getLanguage(), &family);
57    if (family.name.isEmpty())
58        return 0;
59
60    AtomicString atomicFamily(family.name);
61    // Changes weight and/or italic of given FontDescription depends on
62    // the result of fontconfig so that keeping the correct font mapping
63    // of the given character. See http://crbug.com/32109 for details.
64    bool shouldSetFakeBold = false;
65    bool shouldSetFakeItalic = false;
66    FontDescription description(fontDescription);
67    if (family.isBold && description.weight() < FontWeightBold)
68        description.setWeight(FontWeightBold);
69    if (!family.isBold && description.weight() >= FontWeightBold) {
70        shouldSetFakeBold = true;
71        description.setWeight(FontWeightNormal);
72    }
73    if (family.isItalic && description.italic() == FontItalicOff)
74        description.setItalic(FontItalicOn);
75    if (!family.isItalic && description.italic() == FontItalicOn) {
76        shouldSetFakeItalic = true;
77        description.setItalic(FontItalicOff);
78    }
79
80    FontPlatformData* substitutePlatformData = getFontPlatformData(description, atomicFamily);
81    if (!substitutePlatformData)
82        return 0;
83    FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
84    platformData.setFakeBold(shouldSetFakeBold);
85    platformData.setFakeItalic(shouldSetFakeItalic);
86    return fontDataFromFontPlatformData(&platformData, DoNotRetain);
87}
88
89#endif // !OS(WIN) && !OS(ANDROID)
90
91PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
92{
93    const AtomicString fallbackFontFamily = getFallbackFontFamily(description);
94    const FontPlatformData* fontPlatformData = 0;
95    if (!fallbackFontFamily.isEmpty())
96        fontPlatformData = getFontPlatformData(description, fallbackFontFamily);
97
98    if (!fontPlatformData) {
99        // we should at least have Arial; this is the SkFontHost_fontconfig last resort fallback
100        DEFINE_STATIC_LOCAL(const AtomicString, arialStr, ("Arial", AtomicString::ConstructFromLiteral));
101        fontPlatformData = getFontPlatformData(description, arialStr);
102    }
103
104    ASSERT(fontPlatformData);
105    return fontDataFromFontPlatformData(fontPlatformData, shouldRetain);
106}
107
108PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const AtomicString& family, CString& name)
109{
110    // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
111    // the fallback name (like "monospace") that fontconfig understands.
112    if (!family.length() || family.startsWith("-webkit-")) {
113        name = getFallbackFontFamily(fontDescription).string().utf8();
114    } else {
115        // convert the name to utf8
116        name = family.string().utf8();
117    }
118
119    int style = SkTypeface::kNormal;
120    if (fontDescription.weight() >= FontWeightBold)
121        style |= SkTypeface::kBold;
122    if (fontDescription.italic())
123        style |= SkTypeface::kItalic;
124
125    // FIXME: Use SkFontStyle and matchFamilyStyle instead of legacyCreateTypeface.
126#if OS(WIN) && !ENABLE(GDI_FONTS_ON_WINDOWS)
127    if (m_fontManager)
128        return adoptRef(m_fontManager->legacyCreateTypeface(name.data(), style));
129#endif
130
131    return adoptRef(SkTypeface::CreateFromName(name.data(), static_cast<SkTypeface::Style>(style)));
132}
133
134#if !OS(WIN)
135FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family, float fontSize)
136{
137    CString name;
138    RefPtr<SkTypeface> tf(createTypeface(fontDescription, family, name));
139    if (!tf)
140        return 0;
141
142    FontPlatformData* result = new FontPlatformData(tf,
143        name.data(),
144        fontSize,
145        (fontDescription.weight() >= FontWeightBold && !tf->isBold()) || fontDescription.isSyntheticBold(),
146        (fontDescription.italic() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
147        fontDescription.orientation(),
148        fontDescription.useSubpixelPositioning());
149    return result;
150}
151#endif // !OS(WIN)
152
153} // namespace WebCore
154