File indexing completed on 2024-04-28 15:23:53

0001 /*
0002  * This file is part of the html renderer for KDE.
0003  *
0004  * Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
0005  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
0006  *           (C) 2000 Dirk Mueller (mueller@kde.org)
0007  *
0008  * This library is free software; you can redistribute it and/or
0009  * modify it under the terms of the GNU Library General Public
0010  * License as published by the Free Software Foundation; either
0011  * version 2 of the License, or (at your option) any later version.
0012  *
0013  * This library is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016  * Library General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU Library General Public License
0019  * along with this library; see the file COPYING.LIB.  If not, write to
0020  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021  * Boston, MA 02110-1301, USA.
0022  *
0023  */
0024 
0025 #ifndef KHTMLFONT_H
0026 #define KHTMLFONT_H
0027 
0028 #include <khtml_global.h>
0029 #include <khtml_settings.h>
0030 
0031 #include <QCache>
0032 #include <QFont>
0033 #include <QFontMetrics>
0034 #include <QPainter>
0035 
0036 #include "misc/shared.h"
0037 
0038 namespace DOM
0039 {
0040 class DOMString;
0041 }
0042 
0043 namespace khtml
0044 {
0045 class RenderStyle;
0046 class CSSStyleSelector;
0047 
0048 class CachedFontFamily;
0049 
0050 class CachedFontInstance: public Shared<CachedFontInstance>
0051 {
0052 public:
0053     CachedFontInstance(CachedFontFamily *parent, int size);
0054 
0055     QFont        f;
0056     QFontMetrics fm; // note:stuff below is faster when applicable.
0057     // Also, do not rearrange these two fields --- one neefs f to initialize fm
0058 
0059     // We store cached width metrics as a two-level tree ---
0060     // top-level is row for the codepoint, second is column.
0061     // Some rows may have no information on them.
0062     // For a cell, value 255 means no known width (or a width >= 255)
0063     unsigned cachedCharWidth(unsigned short codePoint)
0064     {
0065         unsigned width = 0xFF;
0066         if (RowInfo *row = rows[codePoint >> 8]) {
0067             width = row->widths[codePoint & 0xFF];
0068         }
0069         if (width != 0xFF) {
0070             return width;
0071         } else {
0072             return calcAndCacheWidth(codePoint);
0073         }
0074     }
0075 
0076     unsigned cachedCharWidth(const QChar &c)
0077     {
0078         return cachedCharWidth(c.unicode());
0079     }
0080 
0081     // query again all metrics
0082     void invalidate();
0083 
0084     // Simple cached metrics, set on creation
0085     int ascent;
0086     int descent;
0087     int height;
0088     int lineSpacing;
0089     int xHeight;
0090     int m_zeroCharWidth;
0091     mutable bool invalidated;
0092 
0093     ~CachedFontInstance();
0094 private:
0095     unsigned calcAndCacheWidth(unsigned short codePoint);
0096 
0097     struct RowInfo {
0098         unsigned char widths[256];
0099 
0100         RowInfo()
0101         {
0102             for (int i = 0; i < 256; ++i) {
0103                 widths[i] = 0xFF;
0104             }
0105         }
0106     };
0107 
0108     RowInfo *rows[256];
0109     CachedFontFamily *parent;
0110     int size; // the size we were created with
0111 };
0112 
0113 class FontDef
0114 {
0115 public:
0116     FontDef()
0117         : family(KHTMLGlobal::defaultHTMLSettings()->stdFontName()), size(0), italic(false), smallCaps(false), weight(QFont::Normal) {}
0118     bool operator == (const FontDef &other) const
0119     {
0120         return (family == other.family &&
0121                 size == other.size &&
0122                 italic == other.italic &&
0123                 smallCaps == other.smallCaps &&
0124                 weight == other.weight);
0125     }
0126 
0127     QString family;
0128     short int size;
0129     bool italic         : 1;
0130     bool smallCaps      : 1;
0131     unsigned int weight         : 8;
0132 };
0133 
0134 class Font
0135 {
0136     friend class RenderStyle;
0137     friend class CSSStyleSelector;
0138 
0139     static CachedFontInstance *defaultCFI;
0140 public:
0141     static void initDefault();
0142 
0143     Font() : fontDef(), cfi(defaultCFI), scFont(nullptr), letterSpacing(0), wordSpacing(0) {}
0144     Font(const FontDef &fd)
0145         :  fontDef(fd), cfi(defaultCFI), scFont(nullptr), letterSpacing(0), wordSpacing(0)
0146     {}
0147     Font(const Font &o)
0148         : fontDef(o.fontDef), cfi(o.cfi), scFont(o.scFont), letterSpacing(o.letterSpacing), wordSpacing(o.wordSpacing)
0149     {
0150         if (o.scFont) {
0151             scFont = new QFont(*o.scFont);
0152         }
0153     }
0154     ~Font()
0155     {
0156         delete scFont;
0157     }
0158 
0159     bool operator == (const Font &other) const
0160     {
0161         return (fontDef == other.fontDef &&
0162                 letterSpacing == other.letterSpacing &&
0163                 wordSpacing == other.wordSpacing);
0164     }
0165 
0166     const FontDef &getFontDef() const
0167     {
0168         return fontDef;
0169     }
0170 
0171     void update(int logicalDpiY) const;
0172 
0173     static void invalidateCachedFontFamily(const QString &familyName);
0174     static void markAllCachedFontsAsValid();
0175 
0176     /**
0177      * Draws a piece from the given piece of text.
0178      * @param p painter
0179      * @param x x-coordinate to begin drawing, always denotes leftmost position
0180      * @param y y-coordinate of baseline of text
0181      * @param str string to draw a piece from
0182      * @param slen total length of string
0183      * @param pos zero-based offset of beginning of piece
0184      * @param len length of piece
0185      * @param width additional pixels to be distributed equally among all
0186      *      spaces
0187      * @param d text direction
0188      * @param from begin with this position relative to @p pos, -1 to start
0189      *      at @p pos
0190      * @param to stop before this position relative to @p pos, -1 to use full
0191      *      length of piece
0192      * @param bg if valid, fill the background of the drawn piece with this
0193      *      color
0194      * @param uy y-coordinate of top position, used for background and text
0195      *      decoration painting
0196      * @param h total height of line, only used for background and text
0197      *      decoration painting
0198      * @param deco combined text decoration (see Decoration)
0199      */
0200     void drawText(QPainter *p, int x, int y, const QChar *str, const int slen, int pos, int len, int width,
0201                   Qt::LayoutDirection d, int from = -1, int to = -1, QColor bg = QColor(),
0202                   int uy = -1, int h = -1, int deco = 0) const;
0203 
0204     /** returns the width of the given string chunk in pixels.
0205      *
0206      * The method also considers various styles like text-align and font-variant
0207      * @param str pointer to string
0208      * @param slen total length of string
0209      * @param pos zero-based position in string where to start measuring
0210      * @param len count of characters up to which the width should be determined
0211      * @param fast Use simplest/fastest algorithm (for e.g strings without special/combining chars)
0212      * @param start starting position of inline text box within str, only
0213      * used when toAdd is specified.
0214      * @param end ending position of inline text box within str, only
0215      * used when toAdd is specified.
0216      * @param toAdd amount of pixels to distribute evenly among all spaces of
0217      * str. Note that toAdd applies to all spaces within str, but only those
0218      * within [pos, pos+len) are counted towards the width.
0219      */
0220     int width(const QChar *str, int slen, int pos, int len, bool fast, int start = 0, int end = 0, int toAdd = 0) const;
0221     /** return the width of the given char in pixels.
0222      *
0223      * The method also considers various styles like text-align and font-variant
0224      * @param str pointer to string
0225      * @param slen total length of string
0226      * @param pos zero-based position of char in string
0227      */
0228     int charWidth(const QChar *str, int slen, int pos, bool fast) const;
0229 
0230     /** Text decoration constants.
0231      *
0232      * The enumeration constant values match those of ETextDecoration, but only
0233      * a subset is supported.
0234      */
0235     enum Decoration { UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH = 0x4 };
0236     // Keep in sync with ETextDecoration
0237 
0238     /** draws text decoration
0239      * @param p painter
0240      * @param x x-coordinate
0241      * @param y top y-coordinate of line box
0242      * @param baseline baseline
0243      * @param width length of decoration in pixels
0244      * @param height height of line box
0245      * @param deco decoration to be drawn (see Decoration). The enumeration
0246      *      constants may be combined.
0247      */
0248     void drawDecoration(QPainter *p, int x, int y, int baseline, int width, int height, int deco) const;
0249 
0250     /** returns letter spacing
0251      */
0252     int getLetterSpacing() const
0253     {
0254         return letterSpacing;
0255     }
0256     /** returns word spacing
0257      */
0258     int getWordSpacing() const
0259     {
0260         return wordSpacing;
0261     }
0262 
0263     // for SVG
0264     int ascent() const
0265     {
0266         return cfi->ascent;
0267     }
0268     int descent() const
0269     {
0270         return cfi->descent;
0271     }
0272     int height() const
0273     {
0274         return cfi->height;
0275     }
0276     int lineSpacing() const
0277     {
0278         return cfi->lineSpacing;
0279     }
0280     int xHeight() const
0281     {
0282         return cfi->xHeight;
0283     }
0284 
0285     // return -1 if '0' char glyph not in font
0286     int zeroCharWidth() const
0287     {
0288         return cfi->m_zeroCharWidth;
0289     }
0290     //FIXME: IMPLEMENT ME
0291     unsigned unitsPerEm() const
0292     {
0293         return 0;
0294     }
0295     int spaceWidth() const
0296     {
0297         return 0;
0298     }
0299     int tabWidth() const
0300     {
0301         return 8 * spaceWidth();
0302     }
0303 
0304     bool isInvalidated() const
0305     {
0306         return cfi->invalidated;
0307     }
0308     void validate() const
0309     {
0310         cfi->invalidated = false;
0311     }
0312 
0313     // SVG helper function
0314     float floatWidth(QChar *str, int pos, int len, int extraCharsAvailable, int &charsConsumed, DOM::DOMString &glyphName) const;
0315 
0316     float floatWidth(QChar *str, int pos, int len) const;
0317 
0318 private:
0319     static CachedFontFamily *queryFamily(const QString &name, int weight, bool italic);
0320 
0321     mutable FontDef fontDef;
0322     mutable WTF::SharedPtr<CachedFontInstance> cfi;
0323     mutable QFont *scFont;
0324     short letterSpacing;
0325     short wordSpacing;
0326 };
0327 
0328 } // namespace
0329 
0330 #endif