Home | History | Annotate | Download | only in graphics
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2000 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2003, 2006 Apple Inc. All rights reserved.
      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 #include "config.h"
     25 #include "Font.h"
     26 
     27 #include "FloatRect.h"
     28 #include "FontCache.h"
     29 #include "FontFallbackList.h"
     30 #include "IntPoint.h"
     31 #include "GlyphBuffer.h"
     32 #include "WidthIterator.h"
     33 #include <wtf/MathExtras.h>
     34 #include <wtf/UnusedParam.h>
     35 
     36 using namespace WTF;
     37 using namespace Unicode;
     38 
     39 namespace WebCore {
     40 
     41 #if USE(FONT_FAST_PATH)
     42 const uint8_t Font::gRoundingHackCharacterTable[256] = {
     43     0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*\t*/, 1 /*\n*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     44     1 /*space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*-*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 /*?*/,
     45     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     46     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     47     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     48     1 /*no-break space*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     49     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     50     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     51 };
     52 
     53 Font::CodePath Font::s_codePath = Auto;
     54 #endif
     55 
     56 // ============================================================================================
     57 // Font Implementation (Cross-Platform Portion)
     58 // ============================================================================================
     59 
     60 Font::Font()
     61     : m_letterSpacing(0)
     62     , m_wordSpacing(0)
     63     , m_isPlatformFont(false)
     64 {
     65 }
     66 
     67 Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
     68     : m_fontDescription(fd)
     69     , m_letterSpacing(letterSpacing)
     70     , m_wordSpacing(wordSpacing)
     71     , m_isPlatformFont(false)
     72 {
     73 }
     74 
     75 Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
     76     : m_fontList(FontFallbackList::create())
     77     , m_letterSpacing(0)
     78     , m_wordSpacing(0)
     79     , m_isPlatformFont(true)
     80 {
     81     m_fontDescription.setUsePrinterFont(isPrinterFont);
     82     m_fontList->setPlatformFont(fontData);
     83 }
     84 
     85 Font::Font(const Font& other)
     86     : m_fontDescription(other.m_fontDescription)
     87     , m_fontList(other.m_fontList)
     88     , m_letterSpacing(other.m_letterSpacing)
     89     , m_wordSpacing(other.m_wordSpacing)
     90     , m_isPlatformFont(other.m_isPlatformFont)
     91 {
     92 }
     93 
     94 Font& Font::operator=(const Font& other)
     95 {
     96     m_fontDescription = other.m_fontDescription;
     97     m_fontList = other.m_fontList;
     98     m_letterSpacing = other.m_letterSpacing;
     99     m_wordSpacing = other.m_wordSpacing;
    100     m_isPlatformFont = other.m_isPlatformFont;
    101     return *this;
    102 }
    103 
    104 Font::~Font()
    105 {
    106 }
    107 
    108 bool Font::operator==(const Font& other) const
    109 {
    110     // Our FontData don't have to be checked, since checking the font description will be fine.
    111     // FIXME: This does not work if the font was made with the FontPlatformData constructor.
    112     if ((m_fontList && m_fontList->loadingCustomFonts()) ||
    113         (other.m_fontList && other.m_fontList->loadingCustomFonts()))
    114         return false;
    115 
    116     FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
    117     FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
    118 
    119     return first == second
    120            && m_fontDescription == other.m_fontDescription
    121            && m_letterSpacing == other.m_letterSpacing
    122            && m_wordSpacing == other.m_wordSpacing
    123            && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0);
    124 }
    125 
    126 const SimpleFontData* Font::primaryFont() const
    127 {
    128     ASSERT(m_fontList);
    129     return m_fontList->primarySimpleFontData(this);
    130 }
    131 
    132 const FontData* Font::fontDataAt(unsigned index) const
    133 {
    134     ASSERT(m_fontList);
    135     return m_fontList->fontDataAt(this, index);
    136 }
    137 
    138 const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
    139 {
    140     ASSERT(m_fontList);
    141     return m_fontList->fontDataForCharacters(this, characters, length);
    142 }
    143 
    144 void Font::update(PassRefPtr<FontSelector> fontSelector) const
    145 {
    146     // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
    147     // being reasonably safe (because inherited fonts in the render tree pick up the new
    148     // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
    149     // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
    150     // and could eventually be rectified by using RefPtrs for Fonts themselves.
    151     if (!m_fontList)
    152         m_fontList = FontFallbackList::create();
    153     m_fontList->invalidate(fontSelector);
    154 }
    155 
    156 bool Font::isFixedPitch() const
    157 {
    158     ASSERT(m_fontList);
    159     return m_fontList->isFixedPitch(this);
    160 }
    161 
    162 void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
    163 {
    164     // Don't draw anything while we are using custom fonts that are in the process of loading.
    165     if (m_fontList && m_fontList->loadingCustomFonts())
    166         return;
    167 
    168     to = (to == -1 ? run.length() : to);
    169 
    170 #if ENABLE(SVG_FONTS)
    171     if (primaryFont()->isSVGFont()) {
    172         drawTextUsingSVGFont(context, run, point, from, to);
    173         return;
    174     }
    175 #endif
    176 
    177 #if USE(FONT_FAST_PATH)
    178     if (canUseGlyphCache(run))
    179         return drawSimpleText(context, run, point, from, to);
    180 #endif
    181 
    182     return drawComplexText(context, run, point, from, to);
    183 }
    184 
    185 float Font::floatWidth(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
    186 {
    187 #if ENABLE(SVG_FONTS)
    188     if (primaryFont()->isSVGFont())
    189         return floatWidthUsingSVGFont(run);
    190 #endif
    191 
    192 #if USE(FONT_FAST_PATH)
    193     if (canUseGlyphCache(run)) {
    194         // If the complex text implementation cannot return fallback fonts, avoid
    195         // returning them for simple text as well.
    196         static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
    197         return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0);
    198     }
    199 #endif
    200 
    201     return floatWidthForComplexText(run, fallbackFonts);
    202 }
    203 
    204 float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
    205 {
    206 #if !ENABLE(SVG_FONTS)
    207     UNUSED_PARAM(extraCharsAvailable);
    208 #else
    209     if (primaryFont()->isSVGFont())
    210         return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
    211 #endif
    212 
    213     charsConsumed = run.length();
    214     glyphName = "";
    215 
    216 #if USE(FONT_FAST_PATH)
    217     if (canUseGlyphCache(run))
    218         return floatWidthForSimpleText(run, 0);
    219 #endif
    220 
    221     return floatWidthForComplexText(run);
    222 }
    223 
    224 FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
    225 {
    226 #if ENABLE(SVG_FONTS)
    227     if (primaryFont()->isSVGFont())
    228         return selectionRectForTextUsingSVGFont(run, point, h, from, to);
    229 #endif
    230 
    231     to = (to == -1 ? run.length() : to);
    232 
    233 #if USE(FONT_FAST_PATH)
    234     if (canUseGlyphCache(run))
    235         return selectionRectForSimpleText(run, point, h, from, to);
    236 #endif
    237 
    238     return selectionRectForComplexText(run, point, h, from, to);
    239 }
    240 
    241 int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
    242 {
    243 #if ENABLE(SVG_FONTS)
    244     if (primaryFont()->isSVGFont())
    245         return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
    246 #endif
    247 
    248 #if USE(FONT_FAST_PATH)
    249     if (canUseGlyphCache(run))
    250         return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
    251 #endif
    252 
    253     return offsetForPositionForComplexText(run, x, includePartialGlyphs);
    254 }
    255 
    256 #if ENABLE(SVG_FONTS)
    257 bool Font::isSVGFont() const
    258 {
    259     return primaryFont()->isSVGFont();
    260 }
    261 #endif
    262 
    263 FontSelector* Font::fontSelector() const
    264 {
    265     return m_fontList ? m_fontList->fontSelector() : 0;
    266 }
    267 
    268 String Font::normalizeSpaces(const String& string)
    269 {
    270     unsigned length = string.length();
    271     Vector<UChar, 256> buffer(length);
    272     bool didReplacement = false;
    273 
    274     for (unsigned i = 0; i < length; ++i) {
    275         UChar originalCharacter = string[i];
    276         buffer[i] = normalizeSpaces(originalCharacter);
    277         if (buffer[i] != originalCharacter)
    278             didReplacement = true;
    279     }
    280 
    281     return didReplacement ? String(buffer.data(), length) : string;
    282 }
    283 
    284 static bool shouldUseFontSmoothing = true;
    285 
    286 void Font::setShouldUseSmoothing(bool shouldUseSmoothing)
    287 {
    288     ASSERT(isMainThread());
    289     shouldUseFontSmoothing = shouldUseSmoothing;
    290 }
    291 
    292 bool Font::shouldUseSmoothing()
    293 {
    294     return shouldUseFontSmoothing;
    295 }
    296 
    297 }
    298