• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /*
2   * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3   *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4   *           (C) 2000 Dirk Mueller (mueller@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 "CharacterNames.h"
28  #include "FloatRect.h"
29  #include "FontCache.h"
30  #include "FontFallbackList.h"
31  #include "IntPoint.h"
32  #include "GlyphBuffer.h"
33  #include "WidthIterator.h"
34  #include <wtf/MathExtras.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  
Font()60  Font::Font()
61      : m_pageZero(0)
62      , m_cachedPrimaryFont(0)
63      , m_letterSpacing(0)
64      , m_wordSpacing(0)
65      , m_isPlatformFont(false)
66  {
67  }
68  
Font(const FontDescription & fd,short letterSpacing,short wordSpacing)69  Font::Font(const FontDescription& fd, short letterSpacing, short wordSpacing)
70      : m_fontDescription(fd)
71      , m_pageZero(0)
72      , m_cachedPrimaryFont(0)
73      , m_letterSpacing(letterSpacing)
74      , m_wordSpacing(wordSpacing)
75      , m_isPlatformFont(false)
76  {
77  }
78  
Font(const FontPlatformData & fontData,bool isPrinterFont)79  Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
80      : m_fontList(FontFallbackList::create())
81      , m_pageZero(0)
82      , m_cachedPrimaryFont(0)
83      , m_letterSpacing(0)
84      , m_wordSpacing(0)
85      , m_isPlatformFont(true)
86  {
87      m_fontDescription.setUsePrinterFont(isPrinterFont);
88      m_fontList->setPlatformFont(fontData);
89  }
90  
Font(const Font & other)91  Font::Font(const Font& other)
92      : m_fontDescription(other.m_fontDescription)
93      , m_fontList(other.m_fontList)
94      , m_pages(other.m_pages)
95      , m_pageZero(other.m_pageZero)
96      , m_cachedPrimaryFont(other.m_cachedPrimaryFont)
97      , m_letterSpacing(other.m_letterSpacing)
98      , m_wordSpacing(other.m_wordSpacing)
99      , m_isPlatformFont(other.m_isPlatformFont)
100  {
101  }
102  
operator =(const Font & other)103  Font& Font::operator=(const Font& other)
104  {
105      m_fontDescription = other.m_fontDescription;
106      m_fontList = other.m_fontList;
107      m_pages = other.m_pages;
108      m_pageZero = other.m_pageZero;
109      m_cachedPrimaryFont = other.m_cachedPrimaryFont;
110      m_letterSpacing = other.m_letterSpacing;
111      m_wordSpacing = other.m_wordSpacing;
112      m_isPlatformFont = other.m_isPlatformFont;
113      return *this;
114  }
115  
~Font()116  Font::~Font()
117  {
118  }
119  
operator ==(const Font & other) const120  bool Font::operator==(const Font& other) const
121  {
122      // Our FontData don't have to be checked, since checking the font description will be fine.
123      // FIXME: This does not work if the font was made with the FontPlatformData constructor.
124      if ((m_fontList && m_fontList->loadingCustomFonts()) ||
125          (other.m_fontList && other.m_fontList->loadingCustomFonts()))
126          return false;
127  
128      FontSelector* first = m_fontList ? m_fontList->fontSelector() : 0;
129      FontSelector* second = other.m_fontList ? other.m_fontList->fontSelector() : 0;
130  
131      return first == second
132             && m_fontDescription == other.m_fontDescription
133             && m_letterSpacing == other.m_letterSpacing
134             && m_wordSpacing == other.m_wordSpacing
135             && (m_fontList ? m_fontList->generation() : 0) == (other.m_fontList ? other.m_fontList->generation() : 0);
136  }
137  
cachePrimaryFont() const138  void Font::cachePrimaryFont() const
139  {
140      ASSERT(m_fontList);
141      ASSERT(!m_cachedPrimaryFont);
142      m_cachedPrimaryFont = m_fontList->primaryFont(this)->fontDataForCharacter(' ');
143  }
144  
fontDataAt(unsigned index) const145  const FontData* Font::fontDataAt(unsigned index) const
146  {
147      ASSERT(m_fontList);
148      return m_fontList->fontDataAt(this, index);
149  }
150  
fontDataForCharacters(const UChar * characters,int length) const151  const FontData* Font::fontDataForCharacters(const UChar* characters, int length) const
152  {
153      ASSERT(m_fontList);
154      return m_fontList->fontDataForCharacters(this, characters, length);
155  }
156  
update(PassRefPtr<FontSelector> fontSelector) const157  void Font::update(PassRefPtr<FontSelector> fontSelector) const
158  {
159      // FIXME: It is pretty crazy that we are willing to just poke into a RefPtr, but it ends up
160      // being reasonably safe (because inherited fonts in the render tree pick up the new
161      // style anyway. Other copies are transient, e.g., the state in the GraphicsContext, and
162      // won't stick around long enough to get you in trouble). Still, this is pretty disgusting,
163      // and could eventually be rectified by using RefPtrs for Fonts themselves.
164      if (!m_fontList)
165          m_fontList = FontFallbackList::create();
166      m_fontList->invalidate(fontSelector);
167      m_cachedPrimaryFont = 0;
168      m_pageZero = 0;
169      m_pages.clear();
170  }
171  
isFixedPitch() const172  bool Font::isFixedPitch() const
173  {
174      ASSERT(m_fontList);
175      return m_fontList->isFixedPitch(this);
176  }
177  
drawText(GraphicsContext * context,const TextRun & run,const FloatPoint & point,int from,int to) const178  void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
179  {
180      // Don't draw anything while we are using custom fonts that are in the process of loading.
181      if (m_fontList && m_fontList->loadingCustomFonts())
182          return;
183  
184      to = (to == -1 ? run.length() : to);
185  
186  #if ENABLE(SVG_FONTS)
187      if (primaryFont()->isSVGFont()) {
188          drawTextUsingSVGFont(context, run, point, from, to);
189          return;
190      }
191  #endif
192  
193  #if USE(FONT_FAST_PATH)
194      if (canUseGlyphCache(run))
195          return drawSimpleText(context, run, point, from, to);
196  #endif
197  
198      return drawComplexText(context, run, point, from, to);
199  }
200  
floatWidth(const TextRun & run) const201  float Font::floatWidth(const TextRun& run) const
202  {
203  #if ENABLE(SVG_FONTS)
204      if (primaryFont()->isSVGFont())
205          return floatWidthUsingSVGFont(run);
206  #endif
207  
208  #if USE(FONT_FAST_PATH)
209      if (canUseGlyphCache(run))
210          return floatWidthForSimpleText(run, 0);
211  #endif
212  
213      return floatWidthForComplexText(run);
214  }
215  
floatWidth(const TextRun & run,int extraCharsAvailable,int & charsConsumed,String & glyphName) const216  float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
217  {
218  #if ENABLE(SVG_FONTS)
219      if (primaryFont()->isSVGFont())
220          return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
221  #endif
222  
223      charsConsumed = run.length();
224      glyphName = "";
225  
226  #if USE(FONT_FAST_PATH)
227      if (canUseGlyphCache(run))
228          return floatWidthForSimpleText(run, 0);
229  #endif
230  
231      return floatWidthForComplexText(run);
232  }
233  
selectionRectForText(const TextRun & run,const IntPoint & point,int h,int from,int to) const234  FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
235  {
236  #if ENABLE(SVG_FONTS)
237      if (primaryFont()->isSVGFont())
238          return selectionRectForTextUsingSVGFont(run, point, h, from, to);
239  #endif
240  
241      to = (to == -1 ? run.length() : to);
242  
243  #if USE(FONT_FAST_PATH)
244      if (canUseGlyphCache(run))
245          return selectionRectForSimpleText(run, point, h, from, to);
246  #endif
247  
248      return selectionRectForComplexText(run, point, h, from, to);
249  }
250  
offsetForPosition(const TextRun & run,int x,bool includePartialGlyphs) const251  int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
252  {
253  #if ENABLE(SVG_FONTS)
254      if (primaryFont()->isSVGFont())
255          return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
256  #endif
257  
258  #if USE(FONT_FAST_PATH)
259      if (canUseGlyphCache(run))
260          return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
261  #endif
262  
263      return offsetForPositionForComplexText(run, x, includePartialGlyphs);
264  }
265  
266  #if ENABLE(SVG_FONTS)
isSVGFont() const267  bool Font::isSVGFont() const
268  {
269      return primaryFont()->isSVGFont();
270  }
271  #endif
272  
fontSelector() const273  FontSelector* Font::fontSelector() const
274  {
275      return m_fontList ? m_fontList->fontSelector() : 0;
276  }
277  
278  }
279