diff options
Diffstat (limited to 'WebCore/platform/graphics/qt/FontQt.cpp')
-rw-r--r-- | WebCore/platform/graphics/qt/FontQt.cpp | 550 |
1 files changed, 16 insertions, 534 deletions
diff --git a/WebCore/platform/graphics/qt/FontQt.cpp b/WebCore/platform/graphics/qt/FontQt.cpp index e2ef605..deeea99 100644 --- a/WebCore/platform/graphics/qt/FontQt.cpp +++ b/WebCore/platform/graphics/qt/FontQt.cpp @@ -1,5 +1,6 @@ /* Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) + Copyright (C) 2008 Holger Hans Peter Freyther This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public @@ -20,6 +21,7 @@ #include "config.h" #include "Font.h" #include "FontDescription.h" +#include "FontFallbackList.h" #include "FontSelector.h" #include "GraphicsContext.h" @@ -31,66 +33,9 @@ #include <qdebug.h> #include <limits.h> -namespace WebCore { #if QT_VERSION >= 0x040400 - -Font::Font() - : m_letterSpacing(0) - , m_wordSpacing(0) - , m_font() - , m_scFont() -{ - QFontMetrics metrics(m_font); - m_spaceWidth = metrics.width(QLatin1Char(' ')); -} - -Font::Font(const FontDescription& description, short letterSpacing, short wordSpacing) - : m_fontDescription(description) - , m_letterSpacing(letterSpacing) - , m_wordSpacing(wordSpacing) -{ - const FontFamily* family = &description.family(); - QString familyName; - while (family) { - familyName += family->family(); - family = family->next(); - if (family) - familyName += QLatin1Char(','); - } - - m_font.setFamily(familyName); - m_font.setPixelSize(qRound(description.computedSize())); - m_font.setItalic(description.italic()); - // FIXME: Map all FontWeight values to QFont weights. - if (description.weight() >= FontWeight600) - m_font.setWeight(QFont::Bold); - else - m_font.setWeight(QFont::Normal); - - bool smallCaps = description.smallCaps(); - m_font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase); - - QFontMetrics metrics = QFontMetrics(m_font); - m_spaceWidth = metrics.width(QLatin1Char(' ')); - - if (wordSpacing) - m_font.setWordSpacing(wordSpacing); - if (letterSpacing) - m_font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing); -} - -void Font::setWordSpacing(short s) -{ - m_font.setWordSpacing(s); - m_wordSpacing = s; -} -void Font::setLetterSpacing(short s) -{ - m_font.setLetterSpacing(QFont::AbsoluteSpacing, s); - m_letterSpacing = s; -} - +namespace WebCore { static QString qstring(const TextRun& run) { @@ -121,10 +66,11 @@ static QTextLine setupLayout(QTextLayout* layout, const TextRun& style) return line; } -void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const +void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const { if (to < 0) to = run.length(); + QPainter *p = ctx->platformContext(); Color color = ctx->fillColor(); p->setPen(QColor(color)); @@ -138,14 +84,14 @@ void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& bool hasShadow = ctx->textDrawingMode() == cTextFill && ctx->getShadow(shadowSize, shadowBlur, shadowColor); if (from > 0 || to < run.length()) { - QTextLayout layout(string, m_font); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); float x1 = line.cursorToX(from); float x2 = line.cursorToX(to); if (x2 < x1) qSwap(x1, x2); - QFontMetrics fm(m_font); + QFontMetrics fm(font()); int ascent = fm.ascent(); QRectF clip(point.x() + x1, point.y() - ascent, x2 - x1, fm.height()); @@ -179,7 +125,7 @@ void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& return; } - p->setFont(m_font); + p->setFont(font()); QPointF pt(point.x(), point.y()); int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight; @@ -194,12 +140,12 @@ void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& p->drawText(pt, string, flags, run.padding()); } -int Font::width(const TextRun& run) const +float Font::floatWidthForComplexText(const TextRun& run) const { if (!run.length()) return 0; QString string = qstring(run); - QTextLayout layout(string, m_font); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); int w = int(line.naturalTextWidth()); // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does) @@ -209,30 +155,18 @@ int Font::width(const TextRun& run) const return w + run.padding(); } -float Font::floatWidth(const TextRun& run) const -{ - return width(run); -} - -float Font::floatWidth(const TextRun& run, int /*extraCharsAvailable*/, int& charsConsumed, String& glyphName) const -{ - charsConsumed = run.length(); - glyphName = ""; - return width(run); -} - -int Font::offsetForPosition(const TextRun& run, int position, bool /*includePartialGlyphs*/) const +int Font::offsetForPositionForComplexText(const TextRun& run, int position, bool includePartialGlyphs) const { QString string = qstring(run); - QTextLayout layout(string, m_font); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); return line.xToCursor(position); } -FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const +FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const { QString string = qstring(run); - QTextLayout layout(string, m_font); + QTextLayout layout(string, font()); QTextLine line = setupLayout(&layout, run); float x1 = line.cursorToX(from); @@ -243,464 +177,12 @@ FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt, int return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h); } -#else - - -struct TextRunComponent { - TextRunComponent() : font(0) {} - TextRunComponent(const UChar *start, int length, bool rtl, const QFont *font, int offset, bool sc = false); - TextRunComponent(int spaces, bool rtl, const QFont *font, int offset); - - inline bool isSpace() const { return spaces != 0; } - - QString string; - const QFont *font; - int width; - int offset; - int spaces; -}; - -TextRunComponent::TextRunComponent(const UChar *start, int length, bool rtl, const QFont *f, int o, bool sc) - : string(reinterpret_cast<const QChar*>(start), length) - , font(f) - , offset(o) - , spaces(0) -{ - if (sc) - string = string.toUpper(); - string.prepend(rtl ? QChar(0x202e) : QChar(0x202d)); - width = QFontMetrics(*font).width(string); -} - -TextRunComponent::TextRunComponent(int s, bool rtl, const QFont *f, int o) - : string(s, QLatin1Char(' ')) - , font(f) - , offset(o) - , spaces(s) -{ - string.prepend(rtl ? QChar(0x202e) : QChar(0x202d)); - width = spaces * QFontMetrics(*font).width(QLatin1Char(' ')); -} - - -Font::Font() - : m_letterSpacing(0) - , m_wordSpacing(0) - , m_font() - , m_scFont() -{ - QFontMetrics metrics(m_font); - m_spaceWidth = metrics.width(QLatin1Char(' ')); - qreal pointsize = m_font.pointSizeF(); - if (pointsize > 0) - m_scFont.setPointSizeF(pointsize*0.7); - else - m_scFont.setPixelSize(qRound(m_font.pixelSize()*.7)); -} - -Font::Font(const FontDescription& description, short letterSpacing, short wordSpacing) - : m_fontDescription(description) - , m_letterSpacing(letterSpacing) - , m_wordSpacing(wordSpacing) -{ - const FontFamily* family = &description.family(); - QString familyName; - while (family) { - familyName += family->family(); - family = family->next(); - if (family) - familyName += QLatin1Char(','); - } - - m_font.setFamily(familyName); - m_font.setPixelSize(qRound(description.computedSize())); - m_font.setItalic(description.italic()); - // FIXME: Map all FontWeight values to QFont weights. - if (description.weight() >= FontWeight600) - m_font.setWeight(QFont::Bold); - else - m_font.setWeight(QFont::Normal); - - QFontMetrics metrics = QFontMetrics(m_font); - m_spaceWidth = metrics.width(QLatin1Char(' ')); - m_scFont = m_font; - m_scFont.setPixelSize(qRound(description.computedSize()*.7)); -} - -void Font::setWordSpacing(short s) -{ - m_wordSpacing = s; -} -void Font::setLetterSpacing(short s) -{ - m_letterSpacing = s; -} - -static int generateComponents(Vector<TextRunComponent, 1024>* components, const Font &font, const TextRun &run) -{ -// qDebug() << "generateComponents" << QString((const QChar *)run.characters(), run.length()); - int letterSpacing = font.letterSpacing(); - int wordSpacing = font.wordSpacing(); - bool smallCaps = font.fontDescription().smallCaps(); - int padding = run.padding(); - int numSpaces = 0; - if (padding) { - for (int i = 0; i < run.length(); i++) - if (Font::treatAsSpace(run[i])) - ++numSpaces; - } - - int offset = 0; - const QFont *f = &font.font(); - if (letterSpacing || smallCaps) { - // need to draw every letter on it's own - int start = 0; - if (Font::treatAsSpace(run[0])) { - int add = 0; - if (numSpaces) { - add = padding/numSpaces; - padding -= add; - --numSpaces; - } - components->append(TextRunComponent(1, run.rtl(), &font.font(), offset)); - offset += add + letterSpacing + components->last().width; - start = 1; -// qDebug() << "space at 0" << offset; - } else if (smallCaps) { - f = (QChar::category(run[0]) == QChar::Letter_Lowercase ? &font.scFont() : &font.font()); - } - for (int i = 1; i < run.length(); ++i) { - uint ch = run[i]; - if (QChar(ch).isHighSurrogate() && QChar(run[i-1]).isLowSurrogate()) - ch = QChar::surrogateToUcs4(ch, run[i-1]); - if (QChar(ch).isLowSurrogate() || QChar::category(ch) == QChar::Mark_NonSpacing) - continue; - if (Font::treatAsSpace(run[i])) { - int add = 0; -// qDebug() << " treatAsSpace:" << i << start; - if (i - start > 0) { - components->append(TextRunComponent(run.characters() + start, i - start, - run.rtl(), - f, offset, f == &font.scFont())); - offset += components->last().width + letterSpacing; -// qDebug() << " appending(1) " << components->last().string << components->last().width; - } - if (numSpaces) { - add = padding/numSpaces; - padding -= add; - --numSpaces; - } - components->append(TextRunComponent(1, run.rtl(), &font.font(), offset)); - offset += wordSpacing + add + components->last().width + letterSpacing; - start = i + 1; - continue; - } else if (!letterSpacing) { -// qDebug() << i << char(run[i]) << (QChar::category(ch) == QChar::Letter_Lowercase) << -// QFontInfo(*f).pointSizeF(); - if (QChar::category(ch) == QChar::Letter_Lowercase) { - if (f == &font.scFont()) - continue; - } else { - if (f == &font.font()) - continue; - } - } - if (i - start > 0) { - components->append(TextRunComponent(run.characters() + start, i - start, - run.rtl(), - f, offset, f == &font.scFont())); - offset += components->last().width + letterSpacing; -// qDebug() << " appending(2) " << components->last().string << components->last().width; - } - if (smallCaps) - f = (QChar::category(ch) == QChar::Letter_Lowercase ? &font.scFont() : &font.font()); - start = i; - } - if (run.length() - start > 0) { - components->append(TextRunComponent(run.characters() + start, run.length() - start, - run.rtl(), - f, offset, f == &font.scFont())); - offset += components->last().width; -// qDebug() << " appending(3) " << components->last().string << components->last().width; - } - offset += letterSpacing; - } else { - int start = 0; - for (int i = 0; i < run.length(); ++i) { - if (Font::treatAsSpace(run[i])) { - if (i - start > 0) { - components->append(TextRunComponent(run.characters() + start, i - start, - run.rtl(), - f, offset)); - offset += components->last().width; - } - int add = 0; - if (numSpaces) { - add = padding/numSpaces; - padding -= add; - --numSpaces; - } - components->append(TextRunComponent(1, run.rtl(), &font.font(), offset)); - offset += add + components->last().width; - if (i) - offset += wordSpacing; - start = i + 1; - } - } - if (run.length() - start > 0) { - components->append(TextRunComponent(run.characters() + start, run.length() - start, - run.rtl(), - f, offset)); - offset += components->last().width; - } - } - return offset; -} - -void Font::drawText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const -{ - if (to < 0) - to = run.length(); - QPainter *p = ctx->platformContext(); - Color color = ctx->fillColor(); - p->setPen(QColor(color)); - - Vector<TextRunComponent, 1024> components; - int w = generateComponents(&components, *this, run); - - if (from > 0 || to < run.length()) { - FloatRect clip = selectionRectForText(run, - IntPoint(qRound(point.x()), qRound(point.y())), - QFontMetrics(m_font).height(), from, to); - QRectF rect(clip.x(), clip.y() - ascent(), clip.width(), clip.height()); - p->save(); - p->setClipRect(rect.toRect()); - } - - if (run.rtl()) { - for (int i = 0; i < components.size(); ++i) { - if (!components.at(i).isSpace()) { - p->setFont(*components.at(i).font); - QPointF pt(point.x() + w - components.at(i).offset - components.at(i).width, point.y()); - p->drawText(pt, components.at(i).string); - } - } - } else { - for (int i = 0; i < components.size(); ++i) { - if (!components.at(i).isSpace()) { - p->setFont(*components.at(i).font); - QPointF pt(point.x() + components.at(i).offset, point.y()); - p->drawText(pt, components.at(i).string); - } - } - } - if (from > 0 || to < run.length()) - p->restore(); -} - -int Font::width(const TextRun& run) const -{ - Vector<TextRunComponent, 1024> components; - int w = generateComponents(&components, *this, run); - -// qDebug() << " width=" << w; - return w; -} - -float Font::floatWidth(const TextRun& run) const -{ - return width(run); -} - -float Font::floatWidth(const TextRun& run, int /*extraCharsAvailable*/, int& charsConsumed, String& glyphName) const +QFont Font::font() const { - charsConsumed = run.length(); - glyphName = ""; - return width(run); + return primaryFont()->getQtFont(); } -int Font::offsetForPosition(const TextRun& run, int position, bool includePartialGlyphs) const -{ - Vector<TextRunComponent, 1024> components; - int w = generateComponents(&components, *this, run); - - int offset = 0; - if (run.rtl()) { - for (int i = 0; i < components.size(); ++i) { - int xe = w - components.at(i).offset; - int xs = xe - components.at(i).width; - if (position >= xs) { - QTextLayout layout(components.at(i).string, *components.at(i).font); - layout.beginLayout(); - QTextLine l = layout.createLine(); - if (!l.isValid()) - return offset; - - l.setLineWidth(INT_MAX/256); - layout.endLayout(); - - if (position - xs >= l.width()) - return offset; - int cursor = l.xToCursor(position - xs); - if (cursor > 1) - --cursor; - return offset + cursor; - } else { - offset += components.at(i).string.length() - 1; - } - } - } else { - for (int i = 0; i < components.size(); ++i) { - int xs = components.at(i).offset; - int xe = xs + components.at(i).width; - if (position <= xe) { - QTextLayout layout(components.at(i).string, *components.at(i).font); - layout.beginLayout(); - QTextLine l = layout.createLine(); - if (!l.isValid()) - return offset; - - l.setLineWidth(INT_MAX/256); - layout.endLayout(); - - if (position - xs >= l.width()) - return offset + components.at(i).string.length() - 1; - int cursor = l.xToCursor(position - xs); - if (cursor > 1) - --cursor; - return offset + cursor; - } else { - offset += components.at(i).string.length() - 1; - } - } - } - return run.length(); } -static float cursorToX(const Vector<TextRunComponent, 1024>& components, int width, bool rtl, int cursor) -{ - int start = 0; - for (int i = 0; i < components.size(); ++i) { - if (start + components.at(i).string.length() - 1 < cursor) { - start += components.at(i).string.length() - 1; - continue; - } - int xs = components.at(i).offset; - if (rtl) - xs = width - xs - components.at(i).width; - QTextLayout layout(components.at(i).string, *components.at(i).font); - layout.beginLayout(); - QTextLine l = layout.createLine(); - if (!l.isValid()) - return 0; - - l.setLineWidth(INT_MAX/256); - layout.endLayout(); - - return xs + l.cursorToX(cursor - start + 1); - } - return width; -} - -FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& pt, - int h, int from, int to) const -{ - Vector<TextRunComponent, 1024> components; - int w = generateComponents(&components, *this, run); - - if (from == 0 && to == run.length()) - return FloatRect(pt.x(), pt.y(), w, h); - - float x1 = cursorToX(components, w, run.rtl(), from); - float x2 = cursorToX(components, w, run.rtl(), to); - if (x2 < x1) - qSwap(x1, x2); - - return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h); -} #endif - -Font::~Font() -{ -} - -Font::Font(const Font& other) - : m_fontDescription(other.m_fontDescription) - , m_letterSpacing(other.m_letterSpacing) - , m_wordSpacing(other.m_wordSpacing) - , m_font(other.m_font) - , m_scFont(other.m_scFont) - , m_spaceWidth(other.m_spaceWidth) -{ -} - -Font& Font::operator=(const Font& other) -{ - m_fontDescription = other.m_fontDescription; - m_letterSpacing = other.m_letterSpacing; - m_wordSpacing = other.m_wordSpacing; - m_font = other.m_font; - m_scFont = other.m_scFont; - m_spaceWidth = other.m_spaceWidth; - return *this; -} - -bool Font::operator==(const Font& other) const -{ - return m_fontDescription == other.m_fontDescription - && m_letterSpacing == other.m_letterSpacing - && m_wordSpacing == other.m_wordSpacing - && m_font == other.m_font - && m_scFont == other.m_scFont - && m_spaceWidth == other.m_spaceWidth; -} - -void Font::update(PassRefPtr<FontSelector>) const -{ - // don't think we need this -} - - -bool Font::isFixedPitch() const -{ - return QFontInfo(m_font).fixedPitch(); -} - -// Metrics that we query the FontFallbackList for. -int Font::ascent() const -{ - return QFontMetrics(m_font).ascent(); -} - -int Font::descent() const -{ - return QFontMetrics(m_font).descent(); -} - -int Font::lineSpacing() const -{ - return QFontMetrics(m_font).lineSpacing(); -} - -int Font::lineGap() const -{ - return QFontMetrics(m_font).leading(); -} - -float Font::xHeight() const -{ - return QFontMetrics(m_font).xHeight(); -} - -unsigned Font::unitsPerEm() const -{ - return 1; // FIXME! -} - -int Font::spaceWidth() const -{ - return m_spaceWidth; -} - -} |