Home | History | Annotate | Download | only in cache
      1 /*
      2  * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
      3  * Copyright (C) 2009 Torch Mobile, Inc.
      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  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "CachedFont.h"
     29 
     30 // FIXME: This should really be a blacklist instead of a whitelist
     31 #if USE(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (OS(WINDOWS) || OS(LINUX) || OS(FREEBSD) || USE(SKIA_MAC_ON_CHROME))) || PLATFORM(HAIKU) || OS(WINCE) || PLATFORM(ANDROID) || PLATFORM(BREWMP)
     32 #define STORE_FONT_CUSTOM_PLATFORM_DATA
     33 #endif
     34 
     35 #include "CachedResourceClient.h"
     36 #include "CachedResourceClientWalker.h"
     37 #include "CachedResourceLoader.h"
     38 #include "FontPlatformData.h"
     39 #include "MemoryCache.h"
     40 #include "SharedBuffer.h"
     41 #include "TextResourceDecoder.h"
     42 #include <wtf/Vector.h>
     43 
     44 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
     45 #include "FontCustomPlatformData.h"
     46 #endif
     47 
     48 #if ENABLE(SVG_FONTS)
     49 #include "NodeList.h"
     50 #include "SVGElement.h"
     51 #include "SVGFontElement.h"
     52 #include "SVGGElement.h"
     53 #include "SVGNames.h"
     54 #endif
     55 
     56 namespace WebCore {
     57 
     58 CachedFont::CachedFont(const String &url)
     59     : CachedResource(url, FontResource)
     60     , m_fontData(0)
     61     , m_loadInitiated(false)
     62 {
     63 }
     64 
     65 CachedFont::~CachedFont()
     66 {
     67 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
     68     delete m_fontData;
     69 #endif
     70 }
     71 
     72 void CachedFont::load(CachedResourceLoader*)
     73 {
     74     // Don't load the file yet.  Wait for an access before triggering the load.
     75     setLoading(true);
     76 }
     77 
     78 void CachedFont::didAddClient(CachedResourceClient* c)
     79 {
     80     if (!isLoading())
     81         c->fontLoaded(this);
     82 }
     83 
     84 void CachedFont::data(PassRefPtr<SharedBuffer> data, bool allDataReceived)
     85 {
     86     if (!allDataReceived)
     87         return;
     88 
     89     m_data = data;
     90     setEncodedSize(m_data.get() ? m_data->size() : 0);
     91     setLoading(false);
     92     checkNotify();
     93 }
     94 
     95 void CachedFont::beginLoadIfNeeded(CachedResourceLoader* dl)
     96 {
     97     if (!m_loadInitiated) {
     98         m_loadInitiated = true;
     99         dl->load(this, false);
    100     }
    101 }
    102 
    103 bool CachedFont::ensureCustomFontData()
    104 {
    105 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
    106     if (!m_fontData && !errorOccurred() && !isLoading() && m_data) {
    107         m_fontData = createFontCustomPlatformData(m_data.get());
    108         if (!m_fontData)
    109             setStatus(DecodeError);
    110     }
    111 #endif
    112     return m_fontData;
    113 }
    114 
    115 FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, TextOrientation textOrientation, FontWidthVariant widthVariant, FontRenderingMode renderingMode)
    116 {
    117 #if ENABLE(SVG_FONTS)
    118     if (m_externalSVGDocument)
    119         return FontPlatformData(size, bold, italic);
    120 #endif
    121 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
    122     ASSERT(m_fontData);
    123     return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, textOrientation, widthVariant, renderingMode);
    124 #else
    125     return FontPlatformData();
    126 #endif
    127 }
    128 
    129 #if ENABLE(SVG_FONTS)
    130 bool CachedFont::ensureSVGFontData()
    131 {
    132     if (!m_externalSVGDocument && !errorOccurred() && !isLoading() && m_data) {
    133         m_externalSVGDocument = SVGDocument::create(0, KURL());
    134 
    135         RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml");
    136         String svgSource = decoder->decode(m_data->data(), m_data->size());
    137         svgSource += decoder->flush();
    138 
    139         m_externalSVGDocument->setContent(svgSource);
    140 
    141         if (decoder->sawError())
    142             m_externalSVGDocument = 0;
    143     }
    144 
    145     return m_externalSVGDocument;
    146 }
    147 
    148 SVGFontElement* CachedFont::getSVGFontById(const String& fontName) const
    149 {
    150     RefPtr<NodeList> list = m_externalSVGDocument->getElementsByTagNameNS(SVGNames::fontTag.namespaceURI(), SVGNames::fontTag.localName());
    151     if (!list)
    152         return 0;
    153 
    154     unsigned listLength = list->length();
    155     if (!listLength)
    156         return 0;
    157 
    158 #ifndef NDEBUG
    159     for (unsigned i = 0; i < listLength; ++i) {
    160         ASSERT(list->item(i));
    161         ASSERT(list->item(i)->hasTagName(SVGNames::fontTag));
    162     }
    163 #endif
    164 
    165     if (fontName.isEmpty())
    166         return static_cast<SVGFontElement*>(list->item(0));
    167 
    168     for (unsigned i = 0; i < listLength; ++i) {
    169         SVGFontElement* element = static_cast<SVGFontElement*>(list->item(i));
    170         if (element->getIdAttribute() == fontName)
    171             return element;
    172     }
    173 
    174     return 0;
    175 }
    176 #endif
    177 
    178 void CachedFont::allClientsRemoved()
    179 {
    180 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
    181     if (m_fontData) {
    182         delete m_fontData;
    183         m_fontData = 0;
    184     }
    185 #endif
    186 }
    187 
    188 void CachedFont::checkNotify()
    189 {
    190     if (isLoading())
    191         return;
    192 
    193     CachedResourceClientWalker w(m_clients);
    194     while (CachedResourceClient *c = w.next())
    195          c->fontLoaded(this);
    196 }
    197 
    198 
    199 void CachedFont::error(CachedResource::Status status)
    200 {
    201     setStatus(status);
    202     ASSERT(errorOccurred());
    203     setLoading(false);
    204     checkNotify();
    205 }
    206 
    207 }
    208