Home | History | Annotate | Download | only in skia
      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 
     45 namespace WebCore {
     46 
     47 void FontCache::platformInit()
     48 {
     49 }
     50 
     51 #if !OS(WIN) && !OS(ANDROID)
     52 PassRefPtr<SimpleFontData> FontCache::fallbackFontForCharacter(const FontDescription& fontDescription, UChar32 c, const SimpleFontData*)
     53 {
     54     icu::Locale locale = icu::Locale::getDefault();
     55     FontCache::PlatformFallbackFont fallbackFont;
     56     FontCache::getFontForCharacter(c, locale.getLanguage(), &fallbackFont);
     57     if (fallbackFont.name.isEmpty())
     58         return nullptr;
     59 
     60     AtomicString atomicFamily(fallbackFont.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 shouldSetSyntheticBold = false;
     65     bool shouldSetSyntheticItalic = false;
     66     FontDescription description(fontDescription);
     67     if (fallbackFont.isBold && description.weight() < FontWeightBold)
     68         description.setWeight(FontWeightBold);
     69     if (!fallbackFont.isBold && description.weight() >= FontWeightBold) {
     70         shouldSetSyntheticBold = true;
     71         description.setWeight(FontWeightNormal);
     72     }
     73     if (fallbackFont.isItalic && description.style() == FontStyleNormal)
     74         description.setStyle(FontStyleItalic);
     75     if (!fallbackFont.isItalic && description.style() == FontStyleItalic) {
     76         shouldSetSyntheticItalic = true;
     77         description.setStyle(FontStyleNormal);
     78     }
     79 
     80     FontPlatformData* substitutePlatformData = getFontPlatformData(description, atomicFamily);
     81     if (!substitutePlatformData)
     82         return nullptr;
     83     FontPlatformData platformData = FontPlatformData(*substitutePlatformData);
     84     platformData.setSyntheticBold(shouldSetSyntheticBold);
     85     platformData.setSyntheticItalic(shouldSetSyntheticItalic);
     86     return fontDataFromFontPlatformData(&platformData, DoNotRetain);
     87 }
     88 
     89 #endif // !OS(WIN) && !OS(ANDROID)
     90 
     91 PassRefPtr<SimpleFontData> FontCache::getLastResortFallbackFont(const FontDescription& description, ShouldRetain shouldRetain)
     92 {
     93     const AtomicString fallbackFontFamily = getFallbackFontFamily(description);
     94     const FontPlatformData* fontPlatformData = getFontPlatformData(description, fallbackFontFamily);
     95 
     96     // We should at least have Sans or Arial which is the last resort fallback of SkFontHost ports.
     97     if (!fontPlatformData) {
     98         DEFINE_STATIC_LOCAL(const AtomicString, sansStr, ("Sans", AtomicString::ConstructFromLiteral));
     99         fontPlatformData = getFontPlatformData(description, sansStr);
    100     }
    101     if (!fontPlatformData) {
    102         DEFINE_STATIC_LOCAL(const AtomicString, arialStr, ("Arial", AtomicString::ConstructFromLiteral));
    103         fontPlatformData = getFontPlatformData(description, arialStr);
    104     }
    105 #if OS(WIN)
    106     // Try some more Windows-specific fallbacks.
    107     if (!fontPlatformData) {
    108         DEFINE_STATIC_LOCAL(const AtomicString, msuigothicStr, ("MS UI Gothic", AtomicString::ConstructFromLiteral));
    109         fontPlatformData = getFontPlatformData(description, msuigothicStr);
    110     }
    111     if (!fontPlatformData) {
    112         DEFINE_STATIC_LOCAL(const AtomicString, mssansserifStr, ("Microsoft Sans Serif", AtomicString::ConstructFromLiteral));
    113         fontPlatformData = getFontPlatformData(description, mssansserifStr);
    114     }
    115 #endif
    116 
    117     ASSERT(fontPlatformData);
    118     return fontDataFromFontPlatformData(fontPlatformData, shouldRetain);
    119 }
    120 
    121 PassRefPtr<SkTypeface> FontCache::createTypeface(const FontDescription& fontDescription, const AtomicString& family, CString& name)
    122 {
    123     // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
    124     // the fallback name (like "monospace") that fontconfig understands.
    125     if (!family.length() || family.startsWith("-webkit-")) {
    126         name = getFallbackFontFamily(fontDescription).string().utf8();
    127     } else {
    128         // convert the name to utf8
    129         name = family.utf8();
    130     }
    131 
    132     int style = SkTypeface::kNormal;
    133     if (fontDescription.weight() >= FontWeightBold)
    134         style |= SkTypeface::kBold;
    135     if (fontDescription.style())
    136         style |= SkTypeface::kItalic;
    137 
    138 #if OS(WIN)
    139     if (s_sideloadedFonts) {
    140         HashMap<String, SkTypeface*>::iterator sideloadedFont = s_sideloadedFonts->find(name.data());
    141         if (sideloadedFont != s_sideloadedFonts->end()) {
    142             return adoptRef(sideloadedFont->value);
    143         }
    144     }
    145     // FIXME: Use SkFontStyle and matchFamilyStyle instead of legacyCreateTypeface.
    146     if (m_fontManager)
    147         return adoptRef(m_fontManager->legacyCreateTypeface(name.data(), style));
    148 #endif
    149 
    150     return adoptRef(SkTypeface::CreateFromName(name.data(), static_cast<SkTypeface::Style>(style)));
    151 }
    152 
    153 #if !OS(WIN)
    154 FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family, float fontSize)
    155 {
    156     CString name;
    157     RefPtr<SkTypeface> tf(createTypeface(fontDescription, family, name));
    158     if (!tf)
    159         return 0;
    160 
    161     FontPlatformData* result = new FontPlatformData(tf,
    162         name.data(),
    163         fontSize,
    164         (fontDescription.weight() >= FontWeightBold && !tf->isBold()) || fontDescription.isSyntheticBold(),
    165         (fontDescription.style() && !tf->isItalic()) || fontDescription.isSyntheticItalic(),
    166         fontDescription.orientation(),
    167         fontDescription.useSubpixelPositioning());
    168     return result;
    169 }
    170 #endif // !OS(WIN)
    171 
    172 } // namespace WebCore
    173