1/* 2 * Copyright (C) 2000 Lars Knoll (knoll@kde.org) 3 * (C) 2000 Antti Koivisto (koivisto@kde.org) 4 * (C) 2000 Dirk Mueller (mueller@kde.org) 5 * Copyright (C) 2003, 2006, 2007, 2010, 2011 Apple Inc. All rights reserved. 6 * Copyright (C) 2008 Holger Hans Peter Freyther 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Library General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Library General Public License for more details. 17 * 18 * You should have received a copy of the GNU Library General Public License 19 * along with this library; see the file COPYING.LIB. If not, write to 20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 * Boston, MA 02110-1301, USA. 22 * 23 */ 24 25#ifndef Font_h 26#define Font_h 27 28#include "DashArray.h" 29#include "FontDescription.h" 30#include "FontGlyphs.h" 31#include "Path.h" 32#include "SimpleFontData.h" 33#include "TextDirection.h" 34#include "TypesettingFeatures.h" 35#include <wtf/HashMap.h> 36#include <wtf/HashSet.h> 37#include <wtf/unicode/CharacterNames.h> 38 39// "X11/X.h" defines Complex to 0 and conflicts 40// with Complex value in CodePath enum. 41#ifdef Complex 42#undef Complex 43#endif 44 45namespace WebCore { 46 47class FloatPoint; 48class FloatRect; 49class FontData; 50class FontMetrics; 51class FontPlatformData; 52class FontSelector; 53class GlyphBuffer; 54class GraphicsContext; 55class LayoutRect; 56class RenderText; 57class TextLayout; 58class TextRun; 59 60struct GlyphData; 61 62struct GlyphOverflow { 63 GlyphOverflow() 64 : left(0) 65 , right(0) 66 , top(0) 67 , bottom(0) 68 , computeBounds(false) 69 { 70 } 71 72 inline bool isEmpty() 73 { 74 return !left && !right && !top && !bottom; 75 } 76 77 inline void extendTo(const GlyphOverflow& other) 78 { 79 left = std::max(left, other.left); 80 right = std::max(right, other.right); 81 top = std::max(top, other.top); 82 bottom = std::max(bottom, other.bottom); 83 } 84 85 bool operator!=(const GlyphOverflow& other) 86 { 87 return left != other.left || right != other.right || top != other.top || bottom != other.bottom; 88 } 89 90 int left; 91 int right; 92 int top; 93 int bottom; 94 bool computeBounds; 95}; 96 97class GlyphToPathTranslator { 98public: 99 enum class GlyphUnderlineType {SkipDescenders, SkipGlyph, DrawOverGlyph}; 100 virtual bool containsMorePaths() = 0; 101 virtual Path path() = 0; 102 virtual std::pair<float, float> extents() = 0; 103 virtual GlyphUnderlineType underlineType() = 0; 104 virtual void advance() = 0; 105 virtual ~GlyphToPathTranslator() { } 106}; 107GlyphToPathTranslator::GlyphUnderlineType computeUnderlineType(const TextRun&, const GlyphBuffer&, int index); 108 109class Font { 110public: 111 Font(); 112 Font(const FontDescription&, float letterSpacing, float wordSpacing); 113 // This constructor is only used if the platform wants to start with a native font. 114 Font(const FontPlatformData&, bool isPrinting, FontSmoothingMode = AutoSmoothing); 115 116 // FIXME: We should make this constructor platform-independent. 117#if PLATFORM(IOS) 118 Font(const FontPlatformData&, PassRefPtr<FontSelector>); 119#endif 120 ~Font(); 121 122 Font(const Font&); 123 Font& operator=(const Font&); 124 125 bool operator==(const Font& other) const; 126 bool operator!=(const Font& other) const { return !(*this == other); } 127 128 const FontDescription& fontDescription() const { return m_fontDescription; } 129 130 int pixelSize() const { return fontDescription().computedPixelSize(); } 131 float size() const { return fontDescription().computedSize(); } 132 133 void update(PassRefPtr<FontSelector>) const; 134 135 enum CustomFontNotReadyAction { DoNotPaintIfFontNotReady, UseFallbackIfFontNotReady }; 136 float drawText(GraphicsContext*, const TextRun&, const FloatPoint&, int from = 0, int to = -1, CustomFontNotReadyAction = DoNotPaintIfFontNotReady) const; 137 void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, int from, int numGlyphs, const FloatPoint&) const; 138 void drawEmphasisMarks(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from = 0, int to = -1) const; 139 140 DashArray dashesForIntersectionsWithRect(const TextRun&, const FloatPoint& textOrigin, const FloatRect& lineExtents) const; 141 142 float width(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 143 float width(const TextRun&, int& charsConsumed, String& glyphName) const; 144 145 PassOwnPtr<TextLayout> createLayout(RenderText*, float xPos, bool collapseWhiteSpace) const; 146 static void deleteLayout(TextLayout*); 147 static float width(TextLayout&, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts = 0); 148 149 int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const; 150 void adjustSelectionRectForText(const TextRun&, LayoutRect& selectionRect, int from = 0, int to = -1) const; 151 152 bool isSmallCaps() const { return m_fontDescription.smallCaps(); } 153 154 float wordSpacing() const { return m_wordSpacing; } 155 float letterSpacing() const { return m_letterSpacing; } 156 void setWordSpacing(float s) { m_wordSpacing = s; } 157 void setLetterSpacing(float s) { m_letterSpacing = s; } 158 bool isFixedPitch() const; 159 bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); } 160 161 FontRenderingMode renderingMode() const { return m_fontDescription.renderingMode(); } 162 163 TypesettingFeatures typesettingFeatures() const { return static_cast<TypesettingFeatures>(m_typesettingFeatures); } 164 165 const AtomicString& firstFamily() const { return m_fontDescription.firstFamily(); } 166 unsigned familyCount() const { return m_fontDescription.familyCount(); } 167 const AtomicString& familyAt(unsigned i) const { return m_fontDescription.familyAt(i); } 168 169 FontItalic italic() const { return m_fontDescription.italic(); } 170 FontWeight weight() const { return m_fontDescription.weight(); } 171 FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); } 172 173 bool isPlatformFont() const { return m_glyphs->isForPlatformFont(); } 174 175 const FontMetrics& fontMetrics() const { return primaryFont()->fontMetrics(); } 176 float spaceWidth() const { return primaryFont()->spaceWidth() + m_letterSpacing; } 177 float tabWidth(const SimpleFontData&, unsigned tabSize, float position) const; 178 float tabWidth(unsigned tabSize, float position) const { return tabWidth(*primaryFont(), tabSize, position); } 179 bool hasValidAverageCharWidth() const; 180 bool fastAverageCharWidthIfAvailable(float &width) const; // returns true on success 181 182 int emphasisMarkAscent(const AtomicString&) const; 183 int emphasisMarkDescent(const AtomicString&) const; 184 int emphasisMarkHeight(const AtomicString&) const; 185 186 const SimpleFontData* primaryFont() const; 187 const FontData* fontDataAt(unsigned) const; 188 GlyphData glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant = AutoVariant) const 189 { 190 return glyphDataAndPageForCharacter(c, mirror, variant).first; 191 } 192#if PLATFORM(COCOA) 193 const SimpleFontData* fontDataForCombiningCharacterSequence(const UChar*, size_t length, FontDataVariant) const; 194#endif 195 std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacter(UChar32 c, bool mirror, FontDataVariant variant) const 196 { 197 return m_glyphs->glyphDataAndPageForCharacter(m_fontDescription, c, mirror, variant); 198 } 199 bool primaryFontHasGlyphForCharacter(UChar32) const; 200 201 static bool isCJKIdeograph(UChar32); 202 static bool isCJKIdeographOrSymbol(UChar32); 203 204 static unsigned expansionOpportunityCount(const LChar*, size_t length, TextDirection, bool& isAfterExpansion); 205 static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion); 206 207 static void setShouldUseSmoothing(bool); 208 static bool shouldUseSmoothing(); 209 210 enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow }; 211 CodePath codePath(const TextRun&) const; 212 static CodePath characterRangeCodePath(const LChar*, unsigned) { return Simple; } 213 static CodePath characterRangeCodePath(const UChar*, unsigned len); 214 215 bool primaryFontDataIsSystemFont() const; 216 217private: 218 enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis }; 219 220 // Returns the initial in-stream advance. 221 float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; 222 float drawSimpleText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; 223 void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const; 224 void drawGlyphBuffer(GraphicsContext*, const TextRun&, const GlyphBuffer&, FloatPoint&) const; 225 void drawEmphasisMarks(GraphicsContext*, const TextRun&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; 226 float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 227 int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const; 228 void adjustSelectionRectForSimpleText(const TextRun&, LayoutRect& selectionRect, int from, int to) const; 229 230 bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const; 231 232 static bool canReturnFallbackFontsForComplexText(); 233 static bool canExpandAroundIdeographsInComplexText(); 234 235 // Returns the initial in-stream advance. 236 float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; 237 float drawComplexText(GraphicsContext*, const TextRun&, const FloatPoint&, int from, int to) const; 238 void drawEmphasisMarksForComplexText(GraphicsContext*, const TextRun&, const AtomicString& mark, const FloatPoint&, int from, int to) const; 239 float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 240 int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const; 241 void adjustSelectionRectForComplexText(const TextRun&, LayoutRect& selectionRect, int from, int to) const; 242 243 friend struct WidthIterator; 244 friend class SVGTextRunRenderingContext; 245 246public: 247#if ENABLE(IOS_TEXT_AUTOSIZING) 248 bool equalForTextAutoSizing(const Font& other) const 249 { 250 return m_fontDescription.equalForTextAutoSizing(other.m_fontDescription) 251 && m_letterSpacing == other.m_letterSpacing 252 && m_wordSpacing == other.m_wordSpacing; 253 } 254#endif 255 256 // Useful for debugging the different font rendering code paths. 257 static void setCodePath(CodePath); 258 static CodePath codePath(); 259 static CodePath s_codePath; 260 261 static void setDefaultTypesettingFeatures(TypesettingFeatures); 262 static TypesettingFeatures defaultTypesettingFeatures(); 263 264 static const uint8_t s_roundingHackCharacterTable[256]; 265 static bool isRoundingHackCharacter(UChar32 c) 266 { 267 return !(c & ~0xFF) && s_roundingHackCharacterTable[c]; 268 } 269 270 FontSelector* fontSelector() const; 271 static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; } 272 static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; } 273 static bool treatAsZeroWidthSpaceInComplexScript(UChar c) { return c < 0x20 || (c >= 0x7F && c < 0xA0) || c == softHyphen || c == zeroWidthSpace || (c >= 0x200e && c <= 0x200f) || (c >= 0x202a && c <= 0x202e) || c == zeroWidthNoBreakSpace || c == objectReplacementCharacter; } 274 static bool canReceiveTextEmphasis(UChar32 c); 275 276 static inline UChar normalizeSpaces(UChar character) 277 { 278 if (treatAsSpace(character)) 279 return space; 280 281 if (treatAsZeroWidthSpace(character)) 282 return zeroWidthSpace; 283 284 return character; 285 } 286 287 static String normalizeSpaces(const LChar*, unsigned length); 288 static String normalizeSpaces(const UChar*, unsigned length); 289 290 bool useBackslashAsYenSymbol() const { return m_useBackslashAsYenSymbol; } 291 FontGlyphs* glyphs() const { return m_glyphs.get(); } 292 293private: 294 bool loadingCustomFonts() const 295 { 296 return m_glyphs && m_glyphs->loadingCustomFonts(); 297 } 298 299 TypesettingFeatures computeTypesettingFeatures() const 300 { 301 TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); 302 TypesettingFeatures features = s_defaultTypesettingFeatures; 303 304 switch (textRenderingMode) { 305 case AutoTextRendering: 306 break; 307 case OptimizeSpeed: 308 features &= ~(Kerning | Ligatures); 309 break; 310 case GeometricPrecision: 311 case OptimizeLegibility: 312 features |= Kerning | Ligatures; 313 break; 314 } 315 316 switch (m_fontDescription.kerning()) { 317 case FontDescription::NoneKerning: 318 features &= ~Kerning; 319 break; 320 case FontDescription::NormalKerning: 321 features |= Kerning; 322 break; 323 case FontDescription::AutoKerning: 324 break; 325 } 326 327 switch (m_fontDescription.commonLigaturesState()) { 328 case FontDescription::DisabledLigaturesState: 329 features &= ~Ligatures; 330 break; 331 case FontDescription::EnabledLigaturesState: 332 features |= Ligatures; 333 break; 334 case FontDescription::NormalLigaturesState: 335 break; 336 } 337 338 return features; 339 } 340 341 static TypesettingFeatures s_defaultTypesettingFeatures; 342 343 FontDescription m_fontDescription; 344 mutable RefPtr<FontGlyphs> m_glyphs; 345 float m_letterSpacing; 346 float m_wordSpacing; 347 mutable bool m_useBackslashAsYenSymbol; 348 mutable unsigned m_typesettingFeatures : 2; // (TypesettingFeatures) Caches values computed from m_fontDescription. 349}; 350 351void invalidateFontGlyphsCache(); 352void pruneUnreferencedEntriesFromFontGlyphsCache(); 353void clearWidthCaches(); 354 355inline Font::~Font() 356{ 357} 358 359inline const SimpleFontData* Font::primaryFont() const 360{ 361 ASSERT(m_glyphs); 362 return m_glyphs->primarySimpleFontData(m_fontDescription); 363} 364 365inline const FontData* Font::fontDataAt(unsigned index) const 366{ 367 ASSERT(m_glyphs); 368 return m_glyphs->realizeFontDataAt(m_fontDescription, index); 369} 370 371inline bool Font::isFixedPitch() const 372{ 373 ASSERT(m_glyphs); 374 return m_glyphs->isFixedPitch(m_fontDescription); 375} 376 377inline FontSelector* Font::fontSelector() const 378{ 379 return m_glyphs ? m_glyphs->fontSelector() : 0; 380} 381 382inline float Font::tabWidth(const SimpleFontData& fontData, unsigned tabSize, float position) const 383{ 384 if (!tabSize) 385 return letterSpacing(); 386 float tabWidth = tabSize * fontData.spaceWidth() + letterSpacing(); 387 float tabDeltaWidth = tabWidth - fmodf(position, tabWidth); 388 return (tabDeltaWidth < fontData.spaceWidth() / 2) ? tabWidth : tabDeltaWidth; 389} 390 391} 392 393namespace WTF { 394 395template <> void deleteOwnedPtr<WebCore::TextLayout>(WebCore::TextLayout*); 396 397} 398 399#endif 400