+2012-03-05 Pierre Rossi <pierre.rossi@gmail.com>
+
+ [Qt] Use QRawFont when building with Qt 5
+ https://bugs.webkit.org/show_bug.cgi?id=78001
+
+ Up until now, fonts in the Qt port have been handled via
+ the QFont API. QRawFont offers a lower-level API enabling
+ us to be more in line with what other WebKit ports do.
+ This patch proceeds to switching over to QRawFont, and
+ effectively use an earlier change by Andreas Kling
+ that remained guarded up until now.
+
+ Reviewed by Simon Hausmann.
+
+ No new tests since this is refactoring of existing
+ functionality.
+
+ * Target.pri:
+ * platform/graphics/Font.cpp:
+ (WebCore::Font::drawText):
+ * platform/graphics/Font.h:
+ (Font):
+ (WebCore):
+ (WebCore::Font::syntheticFont): Added.
+ * platform/graphics/SimpleFontData.h:
+ (SimpleFontData):
+ (WebCore::SimpleFontData::getQtRawFont):
+ (WebCore):
+ * platform/graphics/qt/FontCacheQt.cpp:
+ (WebCore::rawFontForCharacters):
+ (WebCore):
+ (WebCore::FontCache::getFontDataForCharacters):
+ (WebCore::FontCache::createFontPlatformData):
+ * platform/graphics/qt/FontCustomPlatformData.h:
+ (FontCustomPlatformData):
+ * platform/graphics/qt/FontCustomPlatformDataQt.cpp:
+ (WebCore::FontCustomPlatformData::~FontCustomPlatformData):
+ (WebCore::FontCustomPlatformData::fontPlatformData):
+ (WebCore::createFontCustomPlatformData):
+ * platform/graphics/qt/FontPlatformData.h:
+ (WebCore::FontPlatformDataPrivate::FontPlatformDataPrivate):
+ (FontPlatformDataPrivate):
+ (FontPlatformData):
+ * platform/graphics/qt/FontPlatformDataQt.cpp:
+ (WebCore::FontPlatformData::FontPlatformData):
+ (WebCore):
+ (WebCore::FontPlatformData::operator==):
+ * platform/graphics/qt/FontQt.cpp:
+ (WebCore::fillPenForContext):
+ (WebCore::pathForGlyphs):
+ (WebCore::drawQtGlyphRun):
+ (WebCore::Font::drawComplexText):
+ (WebCore::Font::floatWidthForComplexText):
+ (WebCore::Font::offsetForPositionForComplexText):
+ (WebCore::Font::selectionRectForComplexText):
+ (WebCore::Font::initFormatForTextLayout):
+ (WebCore):
+ (WebCore::Font::drawGlyphs):
+ (WebCore::Font::syntheticFont):
+ (WebCore::Font::rawFont):
+ * platform/graphics/qt/FontQt4.cpp: Copied from Source/WebCore/platform/graphics/qt/FontQt.cpp.
+ (WebCore):
+ (WebCore::fromRawDataWithoutRef):
+ (WebCore::setupLayout):
+ (WebCore::fillPenForContext):
+ (WebCore::strokePenForContext):
+ (WebCore::drawTextCommon):
+ (WebCore::Font::drawComplexText):
+ (WebCore::Font::floatWidthForComplexText):
+ (WebCore::Font::offsetForPositionForComplexText):
+ (WebCore::Font::selectionRectForComplexText):
+ (WebCore::Font::canReturnFallbackFontsForComplexText):
+ (WebCore::Font::drawEmphasisMarksForComplexText):
+ (WebCore::Font::drawSimpleText):
+ (WebCore::Font::offsetForPositionForSimpleText):
+ (WebCore::Font::floatWidthForSimpleText):
+ (WebCore::Font::selectionRectForSimpleText):
+ (WebCore::Font::canExpandAroundIdeographsInComplexText):
+ (WebCore::Font::primaryFontHasGlyphForCharacter):
+ (WebCore::Font::emphasisMarkAscent):
+ (WebCore::Font::emphasisMarkDescent):
+ (WebCore::Font::emphasisMarkHeight):
+ (WebCore::Font::drawEmphasisMarksForSimpleText):
+ (WebCore::Font::font):
+ * platform/graphics/qt/SimpleFontDataQt.cpp:
+ (WebCore::SimpleFontData::platformInit):
+ * platform/qt/RenderThemeQt.cpp:
+ (WebCore::RenderThemeQt::fileListNameForWidth):
+ * platform/qt/RenderThemeQtMobile.cpp:
+ (WebCore::RenderThemeQtMobile::computeSizeBasedOnStyle):
+
2012-04-12 JungJik Lee <jungjik.lee@samsung.com>
Calculate the cover rect of tiled backing store with the trajectory vector.
page/qt/EventHandlerQt.cpp \
platform/graphics/qt/TransformationMatrixQt.cpp \
platform/graphics/qt/ColorQt.cpp \
- platform/graphics/qt/FontQt.cpp \
platform/graphics/qt/FontPlatformDataQt.cpp \
platform/graphics/qt/FloatPointQt.cpp \
platform/graphics/qt/FloatRectQt.cpp \
rendering/mathml/RenderMathMLUnderOver.cpp
}
-# QRawFont feature added in Qt 4.8.0
+# QRawFont transition handling.
#
-# If available, this is used to implement the fast path for text rendering
-# and measurement in WebCore. Because the feature is still undergoing
-# development, it is disabled in builds.
-#
-# exists($$[QT_INSTALL_HEADERS]/QtGui/QRawFont): HAVE_QRAWFONT=1
-
-!isEmpty(HAVE_QRAWFONT) {
- DEFINES += HAVE_QRAWFONT=1
+# Even though QRawFont was already available in Qt 4.8, it had
+# limitations that made switching fully to it impossible.
+# We preserve the old code path when building with Qt 4.
+contains(DEFINES, HAVE_QRAWFONT=1) {
SOURCES += \
+ platform/graphics/qt/FontQt.cpp \
platform/graphics/FontFastPath.cpp \
platform/graphics/GlyphPageTreeNode.cpp \
platform/graphics/WidthIterator.cpp \
HEADERS += \
platform/graphics/WidthIterator.h \
platform/graphics/SurrogatePairAwareTextIterator.h
+} else {
+ SOURCES += \
+ platform/graphics/qt/FontQt4.cpp
}
+
contains(DEFINES, ENABLE_GEOLOCATION=1) {
v8 {
SOURCES += \
#include "FloatRect.h"
#include "FontCache.h"
#include "FontTranscoder.h"
-#if PLATFORM(QT) && HAVE(QRAWFONT)
-#include "GraphicsContext.h"
-#endif
#include "IntPoint.h"
#include "GlyphBuffer.h"
#include "TextRun.h"
CodePath codePathToUse = codePath(run);
-#if PLATFORM(QT) && HAVE(QRAWFONT)
- if (context->textDrawingMode() & TextModeStroke)
- codePathToUse = Complex;
-#endif
-
if (codePathToUse != Complex)
return drawSimpleText(context, run, point, from, to);
#include <wtf/unicode/CharacterNames.h>
#if PLATFORM(QT)
+#if HAVE(QRAWFONT)
+#include <QRawFont>
+class QTextLayout;
+#else
#include <QFont>
#endif
+#endif
namespace WebCore {
static unsigned expansionOpportunityCount(const UChar*, size_t length, TextDirection, bool& isAfterExpansion);
#if PLATFORM(QT)
+#if HAVE(QRAWFONT)
+ QRawFont rawFont() const;
+#else
QFont font() const;
#endif
+ QFont syntheticFont() const;
+#endif
static void setShouldUseSmoothing(bool);
static bool shouldUseSmoothing();
{
return m_fontList && m_fontList->loadingCustomFonts();
}
+#if PLATFORM(QT) && HAVE(QRAWFONT)
+ void initFormatForTextLayout(QTextLayout*) const;
+#endif
FontDescription m_fontDescription;
mutable RefPtr<FontFallbackList> m_fontList;
#endif
#if PLATFORM(QT)
+#if !HAVE(QRAWFONT)
#include <QFont>
+#else
+#include <QRawFont>
+#endif
#endif
namespace WebCore {
#endif
#if PLATFORM(QT)
+#if !HAVE(QRAWFONT)
QFont getQtFont() const { return m_platformData.font(); }
+#else
+ QRawFont getQtRawFont() const { return m_platformData.rawFont(); }
+#endif // !HAVE(QRAWFONT)
#endif
#if PLATFORM(WIN) || (OS(WINDOWS) && PLATFORM(WX))
m_glyphToWidthMap.setMetricsForGlyph(glyph, width);
return width;
}
-#endif
+#endif // HAVE(QRAWFONT)
} // namespace WebCore
}
#if HAVE(QRAWFONT)
-static QRawFont rawFontForCharacters(const QString& string, const QFont& requestedFont)
+static QRawFont rawFontForCharacters(const QString& string, const QRawFont& font)
{
- QFont font(requestedFont);
- font.setStyleStrategy(QFont::NoFontMerging);
-
- QTextLayout layout(string, font);
+ QTextLayout layout(string);
+ layout.setRawFont(font);
layout.beginLayout();
layout.createLine();
layout.endLayout();
QList<QGlyphRun> glyphList = layout.glyphRuns();
-
- ASSERT(glyphList.size() == 1);
-
- const QGlyphRun& glyphs(glyphList.at(0));
- QVector<quint32> glyphIndexes = glyphs.glyphIndexes();
-
- if (glyphIndexes.isEmpty())
+ ASSERT(glyphList.size() <= 1);
+ if (!glyphList.size())
return QRawFont();
+ const QGlyphRun& glyphs(glyphList.at(0));
return glyphs.rawFont();
}
-#endif
+#endif // HAVE(QRAWFONT)
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font, const UChar* characters, int length)
{
#if HAVE(QRAWFONT)
QString qstring = QString::fromRawData(reinterpret_cast<const QChar*>(characters), length);
- QRawFont computedFont = rawFontForCharacters(qstring, font.font());
+ QRawFont computedFont = rawFontForCharacters(qstring, font.rawFont());
if (!computedFont.isValid())
return 0;
FontPlatformData alternateFont(computedFont);
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
{
-#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
QFontDatabase db;
if (!db.hasFamily(familyName))
return 0;
-#endif
return new FontPlatformData(fontDescription, familyName);
}
#include <wtf/FastAllocBase.h>
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
+#if HAVE(QRAWFONT)
+#include <QRawFont>
+#endif
namespace WebCore {
FontCustomPlatformData() { }
~FontCustomPlatformData();
+#if !HAVE(QRAWFONT)
// for use with QFontDatabase::addApplicationFont/removeApplicationFont
int m_handle;
+#else
+ QRawFont m_rawFont;
+#endif
FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, TextOrientation = TextOrientationVerticalRight,
FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
#include "FontPlatformData.h"
#include "SharedBuffer.h"
+#if !HAVE(QRAWFONT)
#include <QFontDatabase>
+#endif
#include <QStringList>
namespace WebCore {
FontCustomPlatformData::~FontCustomPlatformData()
{
+#if !HAVE(QRAWFONT)
QFontDatabase::removeApplicationFont(m_handle);
+#endif
}
FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
{
+#if !HAVE(QRAWFONT)
QFont font;
font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]);
font.setPixelSize(size);
if (bold)
font.setWeight(QFont::Bold);
font.setItalic(italic);
-
return FontPlatformData(font);
+#else
+ Q_ASSERT(m_rawFont.isValid());
+ m_rawFont.setPixelSize(qreal(size));
+ return FontPlatformData(m_rawFont);
+#endif
}
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
- int id = QFontDatabase::addApplicationFontFromData(QByteArray(buffer->data(), buffer->size()));
+ const QByteArray fontData(buffer->data(), buffer->size());
+#if !HAVE(QRAWFONT)
+ int id = QFontDatabase::addApplicationFontFromData(fontData);
if (id == -1)
return 0;
-
Q_ASSERT(QFontDatabase::applicationFontFamilies(id).size() > 0);
+#endif
FontCustomPlatformData *data = new FontCustomPlatformData;
+#if !HAVE(QRAWFONT)
data->m_handle = id;
+#else
+ // Pixel size doesn't matter at this point, it is set in FontCustomPlatformData::fontPlatformData.
+ data->m_rawFont.loadFromData(fontData, /*pixelSize = */0, QFont::PreferDefaultHinting);
+#endif
return data;
}
WTF_MAKE_NONCOPYABLE(FontPlatformDataPrivate); WTF_MAKE_FAST_ALLOCATED;
public:
FontPlatformDataPrivate()
+#if !HAVE(QRAWFONT)
: size(font.pixelSize())
, bold(font.bold())
+#else
+ : size(0)
+ , bold(false)
+#endif
, oblique(false)
, isDeletedValue(false)
{ }
, oblique(oblique)
, isDeletedValue(false)
{ }
+#if !HAVE(QRAWFONT)
FontPlatformDataPrivate(const QFont& font)
: font(font)
-#if HAVE(QRAWFONT)
- , rawFont(QRawFont::fromFont(font, QFontDatabase::Any))
-#endif
, size(font.pixelSize())
, bold(font.bold())
, oblique(false)
, isDeletedValue(false)
{ }
-#if HAVE(QRAWFONT)
+#else
FontPlatformDataPrivate(const QRawFont& rawFont)
- : font()
- , rawFont(rawFont)
+ : rawFont(rawFont)
, size(rawFont.pixelSize())
, bold(rawFont.weight() >= QFont::Bold)
, oblique(false)
: isDeletedValue(true)
{ }
+#if !HAVE(QRAWFONT)
QFont font;
-#if HAVE(QRAWFONT)
+#else
QRawFont rawFont;
#endif
float size;
public:
FontPlatformData(float size, bool bold, bool oblique);
FontPlatformData(const FontDescription&, const AtomicString& familyName, int wordSpacing = 0, int letterSpacing = 0);
+#if !HAVE(QRAWFONT)
FontPlatformData(const QFont& font)
: m_data(adoptRef(new FontPlatformDataPrivate(font)))
{ }
-#if HAVE(QRAWFONT)
+#else
FontPlatformData(const FontPlatformData&, float size);
FontPlatformData(const QRawFont& rawFont)
: m_data(adoptRef(new FontPlatformDataPrivate(rawFont)))
return m_data && m_data->isDeletedValue;
}
+#if !HAVE(QRAWFONT)
QFont font() const
{
Q_ASSERT(!isHashTableDeletedValue());
return QFont();
return m_data->font;
}
-#if HAVE(QRAWFONT)
+#else
QRawFont rawFont() const
{
Q_ASSERT(!isHashTableDeletedValue());
FontPlatformData::FontPlatformData(const FontDescription& description, const AtomicString& familyName, int wordSpacing, int letterSpacing)
: m_data(adoptRef(new FontPlatformDataPrivate()))
{
+#if !HAVE(QRAWFONT)
QFont& font = m_data->font;
+#else
+ QFont font;
+#endif
int requestedSize = description.computedPixelSize();
font.setFamily(familyName);
font.setPixelSize(requestedSize);
font.setWeight(toQFontWeight(description.weight()));
font.setWordSpacing(wordSpacing);
font.setLetterSpacing(QFont::AbsoluteSpacing, letterSpacing);
- const bool smallCaps = description.smallCaps();
- font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
font.setStyleStrategy(QFont::ForceIntegerMetrics);
m_data->bold = font.bold();
+#if !HAVE(QRAWFONT)
+ const bool smallCaps = description.smallCaps();
+ font.setCapitalization(smallCaps ? QFont::SmallCaps : QFont::MixedCase);
// WebKit allows font size zero but QFont does not. We will return
// m_data->size if a font size of zero is requested and pixelSize()
// otherwise.
m_data->size = (!requestedSize) ? requestedSize : font.pixelSize();
-#if HAVE(QRAWFONT)
+#else
m_data->rawFont = QRawFont::fromFont(font, QFontDatabase::Any);
+ m_data->size = requestedSize;
#endif
}
FontPlatformData::FontPlatformData(const FontPlatformData& other, float size)
: m_data(adoptRef(new FontPlatformDataPrivate()))
{
- m_data->font = other.m_data->font;
m_data->rawFont = other.m_data->rawFont;
m_data->bold = other.m_data->bold;
m_data->oblique = other.m_data->oblique;
- m_data->font.setPixelSize(size);
m_data->rawFont.setPixelSize(size);
- m_data->size = size ? m_data->font.pixelSize() : 0;
+ m_data->size = m_data->rawFont.pixelSize();
}
-#endif
+#endif // HAVE(QRAWFONT)
bool FontPlatformData::operator==(const FontPlatformData& other) const
{
const bool equals = (m_data->size == other.m_data->size
&& m_data->bold == other.m_data->bold
&& m_data->oblique == other.m_data->oblique
+#if !HAVE(QRAWFONT)
&& m_data->font == other.m_data->font);
+#else
+ && m_data->rawFont == other.m_data->rawFont);
+#endif
return equals;
}
return 0;
if (m_data->isDeletedValue)
return 1;
- return qHash(m_data->font.toString())
- ^ qHash(*reinterpret_cast<quint32*>(&m_data->size))
- ^ qHash(m_data->bold)
- ^ qHash(m_data->oblique);
+#if !HAVE(QRAWFONT)
+ return (qHash(m_data->font.toString()) ^ qHash(m_data->bold)
+ ^ qHash(m_data->oblique))
+ ^ qHash(*reinterpret_cast<quint32*>(&m_data->size));
+#else
+ return qHash(m_data->rawFont.familyName()) ^ qHash(m_data->rawFont.style())
+ ^ qHash(m_data->rawFont.weight())
+ ^ qHash(*reinterpret_cast<quint32*>(&m_data->size));
+#endif
}
#ifndef NDEBUG
/*
- Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
Copyright (C) 2008, 2010 Holger Hans Peter Freyther
Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
#include "FontDescription.h"
#include "FontFallbackList.h"
#include "FontSelector.h"
-#if HAVE(QRAWFONT)
#include "GlyphBuffer.h"
-#endif
#include "Gradient.h"
#include "GraphicsContext.h"
#include "NotImplemented.h"
#include "TextRun.h"
#include <QBrush>
-#include <QFontInfo>
-#include <QFontMetrics>
#include <QPainter>
#include <QPainterPath>
#include <QPen>
-#if HAVE(QRAWFONT)
#include <QPointF>
-#endif
#include <QTextLayout>
#include <qalgorithms.h>
-#include <qdebug.h>
#include <limits.h>
return QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0);
}
- return QPen(QColor(ctx->fillColor()));
+ return QPen(QColor(ctx->fillColor()), 0);
}
static QPen strokePenForContext(GraphicsContext* ctx)
return QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
}
-static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
+static QPainterPath pathForGlyphs(const QGlyphRun& glyphRun, const QPointF& offset)
{
- if (to < 0)
- to = run.length();
-
- QPainter *p = ctx->platformContext();
-
- QPen textFillPen;
- if (ctx->textDrawingMode() & TextModeFill)
- textFillPen = fillPenForContext(ctx);
-
- QPen textStrokePen;
- if (ctx->textDrawingMode() & TextModeStroke)
- textStrokePen = strokePenForContext(ctx);
-
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString string = fromRawDataWithoutRef(sanitized);
- QPointF pt(point.x(), point.y());
-
- if (from > 0 || to < run.length()) {
- if (isComplexText) {
- 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(font);
- int ascent = fm.ascent();
- QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
- QRectF clip = boundingRect;
-
- ShadowBlur* ctxShadow = ctx->shadowBlur();
- if (ctxShadow->type() != ShadowBlur::NoShadow) {
- const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
- qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
- if (shadowOffset.x() > 0)
- dx2 = shadowOffset.x();
- else
- dx1 = -shadowOffset.x();
- if (shadowOffset.y() > 0)
- dy2 = shadowOffset.y();
- else
- dy1 = -shadowOffset.y();
- // expand the clip rect to include the text shadow as well
- const float blurDistance = ctx->state().shadowBlur;
- clip.adjust(dx1, dx2, dy1, dy2);
- clip.adjust(-blurDistance, -blurDistance, blurDistance, blurDistance);
- }
- p->save();
- p->setClipRect(clip.toRect(), Qt::IntersectClip);
- pt.setY(pt.y() - ascent);
-
- if (ctxShadow->type() != ShadowBlur::NoShadow) {
- ShadowBlur* ctxShadow = ctx->shadowBlur();
- if (ctxShadow->type() != ShadowBlur::BlurShadow
- && (!ctxShadow->shadowsIgnoreTransforms() || ctx->getCTM().isIdentity())) {
- p->save();
- p->setPen(ctx->state().shadowColor);
- p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
- line.draw(p, pt);
- p->restore();
- } else {
- GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- // Since it will be blurred anyway, we don't care about render hints.
- shadowPainter->setFont(p->font());
- shadowPainter->setPen(ctx->state().shadowColor);
- line.draw(shadowPainter, pt);
- ctxShadow->endShadowLayer(ctx);
- }
- }
- }
- p->setPen(textFillPen);
- line.draw(p, pt);
- p->restore();
- return;
- }
- int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
- pt.setX(pt.x() + skipWidth);
- string = fromRawDataWithoutRef(sanitized, from, to - from);
+ QPainterPath path;
+ const QRawFont rawFont(glyphRun.rawFont());
+ const QVector<quint32> glyphIndices = glyphRun.glyphIndexes();
+ const QVector<QPointF> positions = glyphRun.positions();
+ for (int i = 0; i < glyphIndices.size(); ++i) {
+ QPainterPath glyphPath = rawFont.pathForGlyph(glyphIndices.at(i));
+ glyphPath.translate(positions.at(i) + offset);
+ path.addPath(glyphPath);
}
+ return path;
+}
- p->setFont(font);
-
- int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
- if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
- flags |= Qt::TextBypassShaping;
+static void drawQtGlyphRun(GraphicsContext* context, const QGlyphRun& qtGlyphRun, const QPointF& point, int baseLineOffset)
+{
+ QPainter* painter = context->platformContext();
QPainterPath textStrokePath;
- if (ctx->textDrawingMode() & TextModeStroke)
- textStrokePath.addText(pt, font, string);
-
- ShadowBlur* ctxShadow = ctx->shadowBlur();
- if (ctx->hasShadow() && ctxShadow->type() != ShadowBlur::NoShadow) {
- if (ctx->textDrawingMode() & TextModeFill) {
- if (ctxShadow->type() != ShadowBlur::BlurShadow) {
- p->save();
- p->setPen(ctx->state().shadowColor);
- p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
- p->drawText(pt, string, flags, run.expansion());
- p->restore();
- } else {
- QFontMetrics fm(font);
- QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
- GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- // Since it will be blurred anyway, we don't care about render hints.
- shadowPainter->setFont(p->font());
- shadowPainter->setPen(ctx->state().shadowColor);
- shadowPainter->drawText(pt, string, flags, run.expansion());
- ctxShadow->endShadowLayer(ctx);
- }
- }
- } else if (ctx->textDrawingMode() & TextModeStroke) {
- if (ctxShadow->type() != ShadowBlur::BlurShadow) {
- const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
- p->translate(shadowOffset);
- p->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
- p->translate(-shadowOffset);
- } else {
- QFontMetrics fm(font);
- QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
- GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- // Since it will be blurred anyway, we don't care about render hints.
- shadowPainter->setFont(p->font());
- shadowPainter->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
- ctxShadow->endShadowLayer(ctx);
- }
+ if (context->textDrawingMode() & TextModeStroke)
+ textStrokePath = pathForGlyphs(qtGlyphRun, point);
+
+ ShadowBlur* shadow = context->shadowBlur();
+ if (context->hasShadow() && shadow->type() != ShadowBlur::NoShadow) {
+ switch (shadow->type()) {
+ case ShadowBlur::SolidShadow: {
+ QPen previousPen = painter->pen();
+ painter->setPen(context->state().shadowColor);
+ const QPointF shadowOffset(context->state().shadowOffset.width(), context->state().shadowOffset.height());
+ painter->translate(shadowOffset);
+ if (context->textDrawingMode() & TextModeFill)
+ painter->drawGlyphRun(point, qtGlyphRun);
+ else if (context->textDrawingMode() & TextModeStroke)
+ painter->strokePath(textStrokePath, painter->pen());
+ painter->translate(-shadowOffset);
+ painter->setPen(previousPen);
+ break;
+ }
+ case ShadowBlur::BlurShadow: {
+ const int width = qtGlyphRun.boundingRect().width();
+ const QRawFont& font = qtGlyphRun.rawFont();
+ const int height = font.ascent() + font.descent();
+ const QRectF boundingRect(point.x(), point.y() - font.ascent() + baseLineOffset, width, height);
+ GraphicsContext* shadowContext = shadow->beginShadowLayer(context, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ shadowPainter->setPen(shadowContext->state().shadowColor);
+ if (shadowContext->textDrawingMode() & TextModeFill)
+ shadowPainter->drawGlyphRun(point, qtGlyphRun);
+ else if (shadowContext->textDrawingMode() & TextModeStroke)
+ shadowPainter->strokePath(textStrokePath, shadowPainter->pen());
+ shadow->endShadowLayer(context);
}
+ break;
+ }
+ case ShadowBlur::NoShadow:
+ default:
+ ASSERT_NOT_REACHED();
+ break;
}
}
- if (ctx->textDrawingMode() & TextModeStroke)
- p->strokePath(textStrokePath, textStrokePen);
+ if (context->textDrawingMode() & TextModeStroke)
+ painter->strokePath(textStrokePath, strokePenForContext(context));
- if (ctx->textDrawingMode() & TextModeFill) {
- QPen previousPen = p->pen();
- p->setPen(textFillPen);
- p->drawText(pt, string, flags, run.expansion());
- p->setPen(previousPen);
+ if (context->textDrawingMode() & TextModeFill) {
+ QPen previousPen = painter->pen();
+ painter->setPen(fillPenForContext(context));
+ painter->drawGlyphRun(point, qtGlyphRun);
+ painter->setPen(previousPen);
}
}
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
{
- drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */true);
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ const QString string = fromRawDataWithoutRef(sanitized);
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
+ QTextLine line = setupLayout(&layout, run);
+ const QPointF adjustedPoint(point.x(), point.y() - line.ascent());
+
+ QList<QGlyphRun> runs = line.glyphRuns(from, to - from);
+ Q_FOREACH(QGlyphRun glyphRun, runs)
+ drawQtGlyphRun(ctx, glyphRun, adjustedPoint, line.ascent());
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
return 0;
if (run.length() == 1 && treatAsSpace(run[0]))
- return QFontMetrics(font()).width(space) + run.expansion();
-
+ return primaryFont()->spaceWidth() + run.expansion();
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
- int w = QFontMetrics(font()).width(string);
- // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
- if (treatAsSpace(run[0]))
- w -= m_wordSpacing;
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
+ QTextLine line = setupLayout(&layout, run);
+ float x1 = line.cursorToX(0);
+ float x2 = line.cursorToX(run.length());
+ const float width = qAbs(x2 - x1);
- return w + run.expansion();
+ return width + run.expansion();
}
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
- QTextLayout layout(string, font());
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
QTextLine line = setupLayout(&layout, run);
return line.xToCursor(position);
}
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
QString string = fromRawDataWithoutRef(sanitized);
- QTextLayout layout(string, font());
+ QTextLayout layout(string);
+ layout.setRawFont(rawFont());
+ initFormatForTextLayout(&layout);
QTextLine line = setupLayout(&layout, run);
float x1 = line.cursorToX(from);
return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
}
+void Font::initFormatForTextLayout(QTextLayout* layout) const
+{
+ QTextLayout::FormatRange range;
+ range.start = 0;
+ range.length = layout->text().length();
+ if (m_wordSpacing)
+ range.format.setFontWordSpacing(m_wordSpacing);
+ if (m_letterSpacing)
+ range.format.setFontLetterSpacing(m_letterSpacing);
+ if (typesettingFeatures() & Kerning)
+ range.format.setFontKerning(true);
+ if (isSmallCaps())
+ range.format.setFontCapitalization(QFont::SmallCaps);
+
+ if (range.format.propertyCount())
+ layout->setAdditionalFormats(QList<QTextLayout::FormatRange>() << range);
+}
+
bool Font::canReturnFallbackFontsForComplexText()
{
return false;
notImplemented();
}
-#if HAVE(QRAWFONT)
void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
{
if (context->paintingDisabled())
bool shouldFill = context->textDrawingMode() & TextModeFill;
bool shouldStroke = context->textDrawingMode() & TextModeStroke;
- // Stroking text should always take the complex path.
- ASSERT(!shouldStroke);
-
if (!shouldFill && !shouldStroke)
return;
glyphIndexes.reserve(numGlyphs);
positions.reserve(numGlyphs);
+ const QRawFont& font(fontData->getQtRawFont());
float width = 0;
width += advance;
}
- QRawFont rawFont(fontData->platformData().rawFont());
-
QGlyphRun qtGlyphs;
qtGlyphs.setGlyphIndexes(glyphIndexes);
qtGlyphs.setPositions(positions);
- qtGlyphs.setRawFont(rawFont);
-
- QPainter* painter = context->platformContext();
-
- ShadowBlur* shadow = context->shadowBlur();
- switch (shadow->type()) {
- case ShadowBlur::SolidShadow: {
- QPen previousPen = painter->pen();
- painter->setPen(context->state().shadowColor);
- const QPointF shadowOffset(context->state().shadowOffset.width(), context->state().shadowOffset.height());
- painter->translate(shadowOffset);
- painter->drawGlyphRun(point, qtGlyphs);
- painter->translate(-shadowOffset);
- painter->setPen(previousPen);
- break;
- }
- case ShadowBlur::BlurShadow: {
- qreal height = rawFont.ascent() + rawFont.descent() + 1;
- QRectF boundingRect(point.x(), point.y() - rawFont.ascent(), width, height);
- GraphicsContext* shadowContext = shadow->beginShadowLayer(context, boundingRect);
- if (shadowContext) {
- QPainter* shadowPainter = shadowContext->platformContext();
- shadowPainter->setPen(context->state().shadowColor);
- shadowPainter->drawGlyphRun(point, qtGlyphs);
- shadow->endShadowLayer(context);
- }
- break;
- }
- case ShadowBlur::NoShadow:
- break;
- default:
- ASSERT_NOT_REACHED();
- break;
- }
-
- QPen previousPen = painter->pen();
- painter->setPen(fillPenForContext(context));
- painter->drawGlyphRun(point, qtGlyphs);
- painter->setPen(previousPen);
-}
-
-bool Font::canExpandAroundIdeographsInComplexText()
-{
- return false;
-}
-
-#else // !HAVE(QRAWFONT)
-
-void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
- drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false);
-}
-
-int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
-{
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString string = fromRawDataWithoutRef(sanitized);
-
- QFontMetrics fm(font());
- float delta = position;
- int curPos = 0;
- do {
- float charWidth = fm.width(string[curPos]);
- delta -= charWidth;
- if (includePartialGlyphs) {
- if (delta + charWidth / 2 <= 0)
- break;
- } else {
- if (delta + charWidth <= 0)
- break;
- }
- } while (++curPos < string.size());
+ qtGlyphs.setRawFont(font);
- return curPos;
+ drawQtGlyphRun(context, qtGlyphs, point, /* baselineOffset = */0);
}
-float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
-{
- if (!primaryFont()->platformData().size())
- return 0;
-
- if (!run.length())
- return 0;
-
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString string = fromRawDataWithoutRef(sanitized);
-
- int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);
-
- // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
- if (treatAsSpace(run[0]))
- w -= m_wordSpacing;
-
- return w + run.expansion();
-}
-
-
-FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
-{
- String sanitized = Font::normalizeSpaces(run.characters(), run.length());
- QString wholeText = fromRawDataWithoutRef(sanitized);
- QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));
-
- int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping);
- int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);
-
- return FloatRect(pt.x() + startX, pt.y(), width, h);
-}
-
bool Font::canExpandAroundIdeographsInComplexText()
{
return false;
}
-bool Font::primaryFontHasGlyphForCharacter(UChar32) const
-{
- notImplemented();
- return true;
-}
-
-int Font::emphasisMarkAscent(const AtomicString&) const
+QFont Font::syntheticFont() const
{
- notImplemented();
- return 0;
-}
-
-int Font::emphasisMarkDescent(const AtomicString&) const
-{
- notImplemented();
- return 0;
-}
-
-int Font::emphasisMarkHeight(const AtomicString&) const
-{
- notImplemented();
- return 0;
-}
-
-void Font::drawEmphasisMarksForSimpleText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
-{
- notImplemented();
-}
-#endif // HAVE(QRAWFONT)
-
-QFont Font::font() const
-{
- QFont f = primaryFont()->getQtFont();
- if (m_letterSpacing != 0)
+ QRawFont rawFont(primaryFont()->getQtRawFont());
+ QFont f(rawFont.familyName());
+ if (rawFont.pixelSize())
+ f.setPixelSize(rawFont.pixelSize());
+ f.setWeight(rawFont.weight());
+ f.setStyle(rawFont.style());
+ if (m_letterSpacing)
f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
- if (m_wordSpacing != 0)
+ if (m_wordSpacing)
f.setWordSpacing(m_wordSpacing);
return f;
}
+QRawFont Font::rawFont() const
+{
+ return primaryFont()->getQtRawFont();
}
+}
--- /dev/null
+/*
+ Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ Copyright (C) 2008, 2010 Holger Hans Peter Freyther
+ Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "Font.h"
+
+#include "AffineTransform.h"
+#include "FontDescription.h"
+#include "FontFallbackList.h"
+#include "FontSelector.h"
+#include "GlyphBuffer.h"
+#include "Gradient.h"
+#include "GraphicsContext.h"
+#include "NotImplemented.h"
+#include "Pattern.h"
+#include "ShadowBlur.h"
+#include "TextRun.h"
+
+#include <QBrush>
+#include <QFontInfo>
+#include <QFontMetrics>
+#include <QPainter>
+#include <QPainterPath>
+#include <QPen>
+#include <QTextLayout>
+#include <limits.h>
+#include <qalgorithms.h>
+#include <qdebug.h>
+
+
+namespace WebCore {
+
+static const QString fromRawDataWithoutRef(const String& string, int start = 0, int len = -1)
+{
+ if (len < 0)
+ len = string.length() - start;
+ Q_ASSERT(start + len <= string.length());
+
+ // We don't detach. This assumes the WebCore string data will stay valid for the
+ // lifetime of the QString we pass back, since we don't ref the WebCore string.
+ return QString::fromRawData(reinterpret_cast<const QChar*>(string.characters() + start), len);
+}
+
+static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
+{
+ int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
+ if (style.expansion())
+ flags |= Qt::TextJustificationForced;
+ layout->setFlags(flags);
+ layout->beginLayout();
+ QTextLine line = layout->createLine();
+ line.setLineWidth(INT_MAX / 256);
+ if (style.expansion())
+ line.setLineWidth(line.naturalTextWidth() + style.expansion());
+ layout->endLayout();
+ return line;
+}
+
+static QPen fillPenForContext(GraphicsContext* ctx)
+{
+ if (ctx->fillGradient()) {
+ QBrush brush(*ctx->fillGradient()->platformGradient());
+ brush.setTransform(ctx->fillGradient()->gradientSpaceTransform());
+ return QPen(brush, 0);
+ }
+
+ if (ctx->fillPattern()) {
+ AffineTransform affine;
+ return QPen(QBrush(ctx->fillPattern()->createPlatformPattern(affine)), 0);
+ }
+
+ return QPen(QColor(ctx->fillColor()));
+}
+
+static QPen strokePenForContext(GraphicsContext* ctx)
+{
+ if (ctx->strokeGradient()) {
+ QBrush brush(*ctx->strokeGradient()->platformGradient());
+ brush.setTransform(ctx->strokeGradient()->gradientSpaceTransform());
+ return QPen(brush, ctx->strokeThickness());
+ }
+
+ if (ctx->strokePattern()) {
+ AffineTransform affine;
+ QBrush brush(ctx->strokePattern()->createPlatformPattern(affine));
+ return QPen(brush, ctx->strokeThickness());
+ }
+
+ return QPen(QColor(ctx->strokeColor()), ctx->strokeThickness());
+}
+
+static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
+{
+ if (to < 0)
+ to = run.length();
+
+ QPainter* p = ctx->platformContext();
+
+ QPen textFillPen;
+ if (ctx->textDrawingMode() & TextModeFill)
+ textFillPen = fillPenForContext(ctx);
+
+ QPen textStrokePen;
+ if (ctx->textDrawingMode() & TextModeStroke)
+ textStrokePen = strokePenForContext(ctx);
+
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+ QPointF pt(point.x(), point.y());
+
+ if (from > 0 || to < run.length()) {
+ if (isComplexText) {
+ 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(font);
+ int ascent = fm.ascent();
+ QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
+ QRectF clip = boundingRect;
+
+ ShadowBlur* ctxShadow = ctx->shadowBlur();
+ if (ctxShadow->type() != ShadowBlur::NoShadow) {
+ const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
+ qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
+ if (shadowOffset.x() > 0)
+ dx2 = shadowOffset.x();
+ else
+ dx1 = -shadowOffset.x();
+ if (shadowOffset.y() > 0)
+ dy2 = shadowOffset.y();
+ else
+ dy1 = -shadowOffset.y();
+ // expand the clip rect to include the text shadow as well
+ const float blurDistance = ctx->state().shadowBlur;
+ clip.adjust(dx1, dx2, dy1, dy2);
+ clip.adjust(-blurDistance, -blurDistance, blurDistance, blurDistance);
+ }
+ p->save();
+ p->setClipRect(clip.toRect(), Qt::IntersectClip);
+ pt.setY(pt.y() - ascent);
+
+ if (ctxShadow->type() != ShadowBlur::NoShadow) {
+ ShadowBlur* ctxShadow = ctx->shadowBlur();
+ if (ctxShadow->type() != ShadowBlur::BlurShadow
+ && (!ctxShadow->shadowsIgnoreTransforms() || ctx->getCTM().isIdentity())) {
+ p->save();
+ p->setPen(ctx->state().shadowColor);
+ p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
+ line.draw(p, pt);
+ p->restore();
+ } else {
+ GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->setPen(ctx->state().shadowColor);
+ line.draw(shadowPainter, pt);
+ ctxShadow->endShadowLayer(ctx);
+ }
+ }
+ }
+ p->setPen(textFillPen);
+ line.draw(p, pt);
+ p->restore();
+ return;
+ }
+ int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
+ pt.setX(pt.x() + skipWidth);
+ string = fromRawDataWithoutRef(sanitized, from, to - from);
+ }
+
+ p->setFont(font);
+
+ int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
+ if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
+ flags |= Qt::TextBypassShaping;
+
+ QPainterPath textStrokePath;
+ if (ctx->textDrawingMode() & TextModeStroke)
+ textStrokePath.addText(pt, font, string);
+
+ ShadowBlur* ctxShadow = ctx->shadowBlur();
+ if (ctx->hasShadow() && ctxShadow->type() != ShadowBlur::NoShadow) {
+ if (ctx->textDrawingMode() & TextModeFill) {
+ if (ctxShadow->type() != ShadowBlur::BlurShadow) {
+ p->save();
+ p->setPen(ctx->state().shadowColor);
+ p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
+ p->drawText(pt, string, flags, run.expansion());
+ p->restore();
+ } else {
+ QFontMetrics fm(font);
+ QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
+ GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->setPen(ctx->state().shadowColor);
+ shadowPainter->drawText(pt, string, flags, run.expansion());
+ ctxShadow->endShadowLayer(ctx);
+ }
+ }
+ } else if (ctx->textDrawingMode() & TextModeStroke) {
+ if (ctxShadow->type() != ShadowBlur::BlurShadow) {
+ const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
+ p->translate(shadowOffset);
+ p->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
+ p->translate(-shadowOffset);
+ } else {
+ QFontMetrics fm(font);
+ QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
+ GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+ if (shadowContext) {
+ QPainter* shadowPainter = shadowContext->platformContext();
+ // Since it will be blurred anyway, we don't care about render hints.
+ shadowPainter->setFont(p->font());
+ shadowPainter->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
+ ctxShadow->endShadowLayer(ctx);
+ }
+ }
+ }
+ }
+
+ if (ctx->textDrawingMode() & TextModeStroke)
+ p->strokePath(textStrokePath, textStrokePen);
+
+ if (ctx->textDrawingMode() & TextModeFill) {
+ QPen previousPen = p->pen();
+ p->setPen(textFillPen);
+ p->drawText(pt, string, flags, run.expansion());
+ p->setPen(previousPen);
+ }
+}
+
+void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */true);
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
+{
+ if (!primaryFont()->platformData().size())
+ return 0;
+
+ if (!run.length())
+ return 0;
+
+ if (run.length() == 1 && treatAsSpace(run[0]))
+ return QFontMetrics(font()).width(space) + run.expansion();
+
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ int w = QFontMetrics(font()).width(string);
+ // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
+ if (treatAsSpace(run[0]))
+ w -= m_wordSpacing;
+
+ return w + run.expansion();
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ QTextLayout layout(string, font());
+ QTextLine line = setupLayout(&layout, run);
+ return line.xToCursor(position);
+}
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ 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);
+
+ return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
+}
+
+bool Font::canReturnFallbackFontsForComplexText()
+{
+ return false;
+}
+
+void Font::drawEmphasisMarksForComplexText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+void Font::drawSimpleText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
+{
+ drawTextCommon(ctx, run, point, from, to, font(), /* isComplexText = */false);
+}
+
+int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ QFontMetrics fm(font());
+ float delta = position;
+ int curPos = 0;
+ do {
+ float charWidth = fm.width(string[curPos]);
+ delta -= charWidth;
+ if (includePartialGlyphs) {
+ if (delta + charWidth / 2 <= 0)
+ break;
+ } else {
+ if (delta + charWidth <= 0)
+ break;
+ }
+ } while (++curPos < string.size());
+
+ return curPos;
+}
+
+
+float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+ if (!primaryFont()->platformData().size())
+ return 0;
+
+ if (!run.length())
+ return 0;
+
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString string = fromRawDataWithoutRef(sanitized);
+
+ int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);
+
+ // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
+ if (treatAsSpace(run[0]))
+ w -= m_wordSpacing;
+
+ return w + run.expansion();
+}
+
+
+FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
+{
+ String sanitized = Font::normalizeSpaces(run.characters(), run.length());
+ QString wholeText = fromRawDataWithoutRef(sanitized);
+ QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));
+
+ int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping);
+ int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);
+
+ return FloatRect(pt.x() + startX, pt.y(), width, h);
+}
+
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+ return false;
+}
+
+bool Font::primaryFontHasGlyphForCharacter(UChar32) const
+{
+ notImplemented();
+ return true;
+}
+
+int Font::emphasisMarkAscent(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::emphasisMarkDescent(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+int Font::emphasisMarkHeight(const AtomicString&) const
+{
+ notImplemented();
+ return 0;
+}
+
+void Font::drawEmphasisMarksForSimpleText(GraphicsContext* /* context */, const TextRun& /* run */, const AtomicString& /* mark */, const FloatPoint& /* point */, int /* from */, int /* to */) const
+{
+ notImplemented();
+}
+
+QFont Font::font() const
+{
+ QFont f = primaryFont()->getQtFont();
+ if (m_letterSpacing)
+ f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
+ if (m_wordSpacing)
+ f.setWordSpacing(m_wordSpacing);
+ return f;
+}
+
+QFont Font::syntheticFont() const
+{
+ return font();
+}
+
+}
+
float descent = rawFont.descent();
float ascent = rawFont.ascent();
float xHeight = rawFont.xHeight();
- float lineSpacing = ascent + descent + rawFont.leading() + 1;
+ float lineSpacing = ascent + descent + rawFont.leading();
QVector<quint32> indexes = rawFont.glyphIndexesForString(QLatin1String(" "));
QVector<QPointF> advances = rawFont.advancesForGlyphIndexes(indexes);
float lineGap = lineSpacing - ascent - descent;
m_fontMetrics.setAscent(ascent);
- m_fontMetrics.setDescent(descent);
+ // WebKit expects the descent to be positive.
+ m_fontMetrics.setDescent(qAbs(descent));
m_fontMetrics.setLineSpacing(lineSpacing);
m_fontMetrics.setXHeight(xHeight);
m_fontMetrics.setLineGap(lineGap);
string = fileButtonNoFileSelectedLabel();
else if (fileList->length() == 1) {
String fname = fileList->item(0)->path();
- QFontMetrics fm(font.font());
+ QFontMetrics fm(font.syntheticFont());
string = fm.elidedText(fname, Qt::ElideLeft, width);
} else {
int n = fileList->length();
#include <QColor>
#include <QFile>
-#include <QFontMetrics>
#include <QPainter>
#include <QPixmapCache>
void RenderThemeQtMobile::computeSizeBasedOnStyle(RenderStyle* renderStyle) const
{
QSize size(0, 0);
- const QFontMetrics fm(renderStyle->font().font());
switch (renderStyle->appearance()) {
case TextAreaPart:
case DefaultButtonPart:
case ButtonPart:
case MenulistPart: {
- const int height = fm.height() * buttonHeightRatio * renderStyle->effectiveZoom();
+ const int height = renderStyle->fontMetrics().height() * buttonHeightRatio * renderStyle->effectiveZoom();
size = QSize(renderStyle->width().value(), height);
break;
}
case Qt::ImFont: {
if (renderTextControl) {
RenderStyle* renderStyle = renderTextControl->style();
- return QVariant(QFont(renderStyle->font().font()));
+ return QVariant(QFont(renderStyle->font().syntheticFont()));
}
return QVariant(QFont());
}
+2012-03-05 Pierre Rossi <pierre.rossi@gmail.com>
+
+ [Qt] Use QRawFont when building with Qt 5
+ https://bugs.webkit.org/show_bug.cgi?id=78001
+
+ Since QFont is not used internally, we now need
+ to query for a QFont that should be a good
+ enough match.
+
+ Reviewed by Simon Hausmann.
+
+ * Api/qwebpage.cpp:
+ (QWebPage::inputMethodQuery):
+ * WebCoreSupport/PopupMenuQt.cpp:
+ (WebCore::PopupMenuQt::show):
+ * WebCoreSupport/RenderThemeQStyle.cpp:
+ (WebCore::RenderThemeQStyle::computeSizeBasedOnStyle):
+
2012-04-06 Levi Weintraub <leviw@chromium.org>
Correct LayoutUnit usgae in RenderThemeQt and RenderThemeQStyle
QRect geometry(rect);
geometry.moveTopLeft(view->contentsToWindow(rect.location()));
m_popup->setGeometry(geometry);
- m_popup->setFont(m_popupClient->menuStyle().font().font());
+ m_popup->setFont(m_popupClient->menuStyle().font().syntheticFont());
m_selectData = adoptPtr(new SelectData(m_popupClient));
m_popup->show(*m_selectData.get());
void RenderThemeQStyle::computeSizeBasedOnStyle(RenderStyle* renderStyle) const
{
QSize size(0, 0);
- const QFontMetrics fm(renderStyle->font().font());
+ const QFontMetrics fm(renderStyle->font().syntheticFont());
QStyle* style = qStyle();
switch (renderStyle->appearance()) {
+2012-03-05 Pierre Rossi <pierre.rossi@gmail.com>
+
+ [Qt] Use QRawFont when building with Qt 5
+ https://bugs.webkit.org/show_bug.cgi?id=78001
+
+ Flip the QRawFont switch for Qt 5.
+
+ Reviewed by Simon Hausmann.
+
+ * qmake/mkspecs/features/features.prf:
+
2012-04-11 Vivek Galatage <vivekgalatage@gmail.com>
Web Inspector: Disabling Inspector causes build failure on Windows
DEFINES -= WTF_USE_ICU_UNICODE
}
+# Use of QRawFont in Qt 5:
+haveQt(5): DEFINES += HAVE_QRAWFONT=1
+
isEmpty(HAVE_QRAWFONT) {
# We have to disable SVG Fonts, which rely on the fast path.
DEFINES -= ENABLE_SVG_FONTS=1
DEFINES -= ENABLE_JAVASCRIPT_DEBUGGER=1
DEFINES += ENABLE_JAVASCRIPT_DEBUGGER=0
}
-
haveQt(4) {
haveQtModule(declarative): DEFINES += HAVE_QQUICK1=1
}