1 /* 2 * Copyright (C) 2000 Lars Knoll (knoll (at) kde.org) 3 * (C) 2000 Antti Koivisto (koivisto (at) kde.org) 4 * (C) 2000 Dirk Mueller (mueller (at) 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 "platform/PlatformExport.h" 29 #include "platform/fonts/FontDescription.h" 30 #include "platform/fonts/FontFallbackList.h" 31 #include "platform/fonts/SimpleFontData.h" 32 #include "platform/fonts/TypesettingFeatures.h" 33 #include "platform/text/TextDirection.h" 34 #include "wtf/HashMap.h" 35 #include "wtf/HashSet.h" 36 #include "wtf/MathExtras.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 45 namespace WebCore { 46 47 class FloatPoint; 48 class FloatRect; 49 class FontData; 50 class FontMetrics; 51 class FontPlatformData; 52 class FontSelector; 53 class GlyphBuffer; 54 class GraphicsContext; 55 class TextLayout; 56 class TextRun; 57 struct TextRunPaintInfo; 58 59 struct GlyphData; 60 61 struct GlyphOverflow { 62 GlyphOverflow() 63 : left(0) 64 , right(0) 65 , top(0) 66 , bottom(0) 67 , computeBounds(false) 68 { 69 } 70 71 int left; 72 int right; 73 int top; 74 int bottom; 75 bool computeBounds; 76 }; 77 78 79 class PLATFORM_EXPORT Font { 80 public: 81 Font(); 82 Font(const FontDescription&, float letterSpacing, float wordSpacing); 83 // This constructor is only used if the platform wants to start with a native font. 84 Font(const FontPlatformData&, bool isPrinting, FontSmoothingMode = AutoSmoothing); 85 ~Font(); 86 87 Font(const Font&); 88 Font& operator=(const Font&); 89 90 bool operator==(const Font& other) const; 91 bool operator!=(const Font& other) const { return !(*this == other); } 92 93 const FontDescription& fontDescription() const { return m_fontDescription; } 94 95 int pixelSize() const { return fontDescription().computedPixelSize(); } 96 float size() const { return fontDescription().computedSize(); } 97 98 void update(PassRefPtr<FontSelector>) const; 99 100 enum CustomFontNotReadyAction { DoNotPaintIfFontNotReady, UseFallbackIfFontNotReady }; 101 void drawText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&, CustomFontNotReadyAction = DoNotPaintIfFontNotReady) const; 102 void drawEmphasisMarks(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const; 103 104 float width(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 105 float width(const TextRun&, int& charsConsumed, String& glyphName) const; 106 107 PassOwnPtr<TextLayout> createLayoutForMacComplexText(const TextRun&, unsigned textLength, float xPos, bool collapseWhiteSpace) const; 108 static void deleteLayout(TextLayout*); 109 static float width(TextLayout&, unsigned from, unsigned len, HashSet<const SimpleFontData*>* fallbackFonts = 0); 110 111 int offsetForPosition(const TextRun&, float position, bool includePartialGlyphs) const; 112 FloatRect selectionRectForText(const TextRun&, const FloatPoint&, int h, int from = 0, int to = -1) const; 113 114 bool isSmallCaps() const { return m_fontDescription.smallCaps(); } 115 116 float wordSpacing() const { return m_wordSpacing; } 117 float letterSpacing() const { return m_letterSpacing; } 118 void setWordSpacing(float s) { m_wordSpacing = s; } 119 void setLetterSpacing(float s) { m_letterSpacing = s; } 120 bool isFixedPitch() const; 121 bool isPrinterFont() const { return m_fontDescription.usePrinterFont(); } 122 123 TypesettingFeatures typesettingFeatures() const { return static_cast<TypesettingFeatures>(m_typesettingFeatures); } 124 125 FontFamily& firstFamily() { return m_fontDescription.firstFamily(); } 126 const FontFamily& family() const { return m_fontDescription.family(); } 127 128 FontItalic italic() const { return m_fontDescription.italic(); } 129 FontWeight weight() const { return m_fontDescription.weight(); } 130 FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); } 131 132 bool isPlatformFont() const { return m_isPlatformFont; } 133 134 // Metrics that we query the FontFallbackList for. 135 const FontMetrics& fontMetrics() const { return primaryFont()->fontMetrics(); } 136 float spaceWidth() const { return primaryFont()->spaceWidth() + m_letterSpacing; } 137 float tabWidth(const SimpleFontData&, unsigned tabSize, float position) const; 138 float tabWidth(unsigned tabSize, float position) const { return tabWidth(*primaryFont(), tabSize, position); } 139 140 int emphasisMarkAscent(const AtomicString&) const; 141 int emphasisMarkDescent(const AtomicString&) const; 142 int emphasisMarkHeight(const AtomicString&) const; 143 144 const SimpleFontData* primaryFont() const; 145 const FontData* fontDataAt(unsigned) const; 146 inline GlyphData glyphDataForCharacter(UChar32 c, bool mirror, FontDataVariant variant = AutoVariant) const 147 { 148 return glyphDataAndPageForCharacter(c, mirror, variant).first; 149 } 150 #if OS(MACOSX) 151 const SimpleFontData* fontDataForCombiningCharacterSequence(const UChar*, size_t length, FontDataVariant) const; 152 #endif 153 std::pair<GlyphData, GlyphPage*> glyphDataAndPageForCharacter(UChar32, bool mirror, FontDataVariant = AutoVariant) const; 154 bool primaryFontHasGlyphForCharacter(UChar32) const; 155 156 static bool isCJKIdeograph(UChar32); 157 static bool isCJKIdeographOrSymbol(UChar32); 158 159 static unsigned expansionOpportunityCount(const LChar*, size_t length, TextDirection, bool& isAfterExpansion); 160 static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion); 161 162 static void setShouldUseSmoothing(bool); 163 static bool shouldUseSmoothing(); 164 165 enum CodePath { Auto, Simple, Complex, SimpleWithGlyphOverflow }; 166 CodePath codePath(const TextRun&) const; 167 static CodePath characterRangeCodePath(const LChar*, unsigned) { return Simple; } 168 static CodePath characterRangeCodePath(const UChar*, unsigned len); 169 170 private: 171 enum ForTextEmphasisOrNot { NotForTextEmphasis, ForTextEmphasis }; 172 173 // Returns the initial in-stream advance. 174 float getGlyphsAndAdvancesForSimpleText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; 175 void drawSimpleText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const; 176 void drawEmphasisMarksForSimpleText(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const; 177 void drawGlyphs(GraphicsContext*, const SimpleFontData*, const GlyphBuffer&, unsigned from, unsigned numGlyphs, const FloatPoint&, const FloatRect& textRect) const; 178 void drawGlyphBuffer(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const FloatPoint&) const; 179 void drawEmphasisMarks(GraphicsContext*, const TextRunPaintInfo&, const GlyphBuffer&, const AtomicString&, const FloatPoint&) const; 180 float floatWidthForSimpleText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 181 int offsetForPositionForSimpleText(const TextRun&, float position, bool includePartialGlyphs) const; 182 FloatRect selectionRectForSimpleText(const TextRun&, const FloatPoint&, int h, int from, int to) const; 183 184 bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const; 185 186 static bool canReturnFallbackFontsForComplexText(); 187 static bool canExpandAroundIdeographsInComplexText(); 188 189 // Returns the initial in-stream advance. 190 float getGlyphsAndAdvancesForComplexText(const TextRun&, int from, int to, GlyphBuffer&, ForTextEmphasisOrNot = NotForTextEmphasis) const; 191 void drawComplexText(GraphicsContext*, const TextRunPaintInfo&, const FloatPoint&) const; 192 void drawEmphasisMarksForComplexText(GraphicsContext*, const TextRunPaintInfo&, const AtomicString& mark, const FloatPoint&) const; 193 float floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const; 194 int offsetForPositionForComplexText(const TextRun&, float position, bool includePartialGlyphs) const; 195 FloatRect selectionRectForComplexText(const TextRun&, const FloatPoint&, int h, int from, int to) const; 196 197 friend struct WidthIterator; 198 friend class SVGTextRunRenderingContext; 199 200 public: 201 // Useful for debugging the different font rendering code paths. 202 static void setCodePath(CodePath); 203 static CodePath codePath(); 204 static CodePath s_codePath; 205 206 static void setDefaultTypesettingFeatures(TypesettingFeatures); 207 static TypesettingFeatures defaultTypesettingFeatures(); 208 209 static const uint8_t s_roundingHackCharacterTable[256]; 210 static bool isRoundingHackCharacter(UChar32 c) 211 { 212 return !(c & ~0xFF) && s_roundingHackCharacterTable[c]; 213 } 214 215 FontSelector* fontSelector() const; 216 static bool treatAsSpace(UChar c) { return c == ' ' || c == '\t' || c == '\n' || c == noBreakSpace; } 217 static bool treatAsZeroWidthSpace(UChar c) { return treatAsZeroWidthSpaceInComplexScript(c) || c == 0x200c || c == 0x200d; } 218 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; } 219 static bool canReceiveTextEmphasis(UChar32 c); 220 221 static inline UChar normalizeSpaces(UChar character) 222 { 223 if (treatAsSpace(character)) 224 return space; 225 226 if (treatAsZeroWidthSpace(character)) 227 return zeroWidthSpace; 228 229 return character; 230 } 231 232 static String normalizeSpaces(const LChar*, unsigned length); 233 static String normalizeSpaces(const UChar*, unsigned length); 234 235 FontFallbackList* fontList() const { return m_fontFallbackList.get(); } 236 237 void willUseFontData() const; 238 239 private: 240 bool loadingCustomFonts() const 241 { 242 return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts(); 243 } 244 245 TypesettingFeatures computeTypesettingFeatures() const 246 { 247 TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode(); 248 TypesettingFeatures features = s_defaultTypesettingFeatures; 249 250 switch (textRenderingMode) { 251 case AutoTextRendering: 252 break; 253 case OptimizeSpeed: 254 features &= ~(Kerning | Ligatures); 255 break; 256 case GeometricPrecision: 257 case OptimizeLegibility: 258 features |= Kerning | Ligatures; 259 break; 260 } 261 262 switch (m_fontDescription.kerning()) { 263 case FontDescription::NoneKerning: 264 features &= ~Kerning; 265 break; 266 case FontDescription::NormalKerning: 267 features |= Kerning; 268 break; 269 case FontDescription::AutoKerning: 270 break; 271 } 272 273 switch (m_fontDescription.commonLigaturesState()) { 274 case FontDescription::DisabledLigaturesState: 275 features &= ~Ligatures; 276 break; 277 case FontDescription::EnabledLigaturesState: 278 features |= Ligatures; 279 break; 280 case FontDescription::NormalLigaturesState: 281 break; 282 } 283 284 return features; 285 } 286 287 static TypesettingFeatures s_defaultTypesettingFeatures; 288 289 FontDescription m_fontDescription; 290 mutable RefPtr<FontFallbackList> m_fontFallbackList; 291 float m_letterSpacing; 292 float m_wordSpacing; 293 bool m_isPlatformFont; 294 mutable unsigned m_typesettingFeatures : 2; // (TypesettingFeatures) Caches values computed from m_fontDescription. 295 }; 296 297 inline Font::~Font() 298 { 299 } 300 301 inline const SimpleFontData* Font::primaryFont() const 302 { 303 ASSERT(m_fontFallbackList); 304 return m_fontFallbackList->primarySimpleFontData(m_fontDescription); 305 } 306 307 inline const FontData* Font::fontDataAt(unsigned index) const 308 { 309 ASSERT(m_fontFallbackList); 310 return m_fontFallbackList->fontDataAt(m_fontDescription, index); 311 } 312 313 inline bool Font::isFixedPitch() const 314 { 315 ASSERT(m_fontFallbackList); 316 return m_fontFallbackList->isFixedPitch(m_fontDescription); 317 } 318 319 inline FontSelector* Font::fontSelector() const 320 { 321 return m_fontFallbackList ? m_fontFallbackList->fontSelector() : 0; 322 } 323 324 inline float Font::tabWidth(const SimpleFontData& fontData, unsigned tabSize, float position) const 325 { 326 if (!tabSize) 327 return letterSpacing(); 328 float tabWidth = tabSize * fontData.spaceWidth() + letterSpacing(); 329 return tabWidth - fmodf(position, tabWidth); 330 } 331 332 } 333 334 namespace WTF { 335 336 template <> struct PLATFORM_EXPORT OwnedPtrDeleter<WebCore::TextLayout> { 337 static void deletePtr(WebCore::TextLayout*); 338 }; 339 340 } 341 342 #endif 343