Home | History | Annotate | Download | only in graphics
      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 "core/platform/graphics/FontDescription.h"
     29 #include "core/platform/graphics/FontFallbackList.h"
     30 #include "core/platform/graphics/SimpleFontData.h"
     31 #include "core/platform/graphics/TypesettingFeatures.h"
     32 #include "core/platform/text/TextDirection.h"
     33 #include "wtf/HashMap.h"
     34 #include "wtf/HashSet.h"
     35 #include "wtf/MathExtras.h"
     36 #include "wtf/unicode/CharacterNames.h"
     37 
     38 // "X11/X.h" defines Complex to 0 and conflicts
     39 // with Complex value in CodePath enum.
     40 #ifdef Complex
     41 #undef Complex
     42 #endif
     43 
     44 namespace WebCore {
     45 
     46 class FloatPoint;
     47 class FloatRect;
     48 class FontData;
     49 class FontMetrics;
     50 class FontPlatformData;
     51 class FontSelector;
     52 class GlyphBuffer;
     53 class GraphicsContext;
     54 class RenderText;
     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 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> createLayout(RenderText*, 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(DARWIN)
    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&, int from, int to, 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     bool needsTranscoding() const { return m_needsTranscoding; }
    236     FontFallbackList* fontList() const { return m_fontFallbackList.get(); }
    237 
    238 private:
    239     bool loadingCustomFonts() const
    240     {
    241         return m_fontFallbackList && m_fontFallbackList->loadingCustomFonts();
    242     }
    243 
    244     TypesettingFeatures computeTypesettingFeatures() const
    245     {
    246         TextRenderingMode textRenderingMode = m_fontDescription.textRenderingMode();
    247         TypesettingFeatures features = s_defaultTypesettingFeatures;
    248 
    249         switch (textRenderingMode) {
    250         case AutoTextRendering:
    251             break;
    252         case OptimizeSpeed:
    253             features &= ~(Kerning | Ligatures);
    254             break;
    255         case GeometricPrecision:
    256         case OptimizeLegibility:
    257             features |= Kerning | Ligatures;
    258             break;
    259         }
    260 
    261         switch (m_fontDescription.kerning()) {
    262         case FontDescription::NoneKerning:
    263             features &= ~Kerning;
    264             break;
    265         case FontDescription::NormalKerning:
    266             features |= Kerning;
    267             break;
    268         case FontDescription::AutoKerning:
    269             break;
    270         }
    271 
    272         switch (m_fontDescription.commonLigaturesState()) {
    273         case FontDescription::DisabledLigaturesState:
    274             features &= ~Ligatures;
    275             break;
    276         case FontDescription::EnabledLigaturesState:
    277             features |= Ligatures;
    278             break;
    279         case FontDescription::NormalLigaturesState:
    280             break;
    281         }
    282 
    283         return features;
    284     }
    285 
    286     static TypesettingFeatures s_defaultTypesettingFeatures;
    287 
    288     FontDescription m_fontDescription;
    289     mutable RefPtr<FontFallbackList> m_fontFallbackList;
    290     float m_letterSpacing;
    291     float m_wordSpacing;
    292     bool m_isPlatformFont;
    293     bool m_needsTranscoding;
    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(this);
    305 }
    306 
    307 inline const FontData* Font::fontDataAt(unsigned index) const
    308 {
    309     ASSERT(m_fontFallbackList);
    310     return m_fontFallbackList->fontDataAt(this, index);
    311 }
    312 
    313 inline bool Font::isFixedPitch() const
    314 {
    315     ASSERT(m_fontFallbackList);
    316     return m_fontFallbackList->isFixedPitch(this);
    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 <> void deleteOwnedPtr<WebCore::TextLayout>(WebCore::TextLayout*);
    337 
    338 }
    339 
    340 #endif
    341