diff options
Diffstat (limited to 'src/gui/text')
53 files changed, 88 insertions, 20095 deletions
diff --git a/src/gui/text/qabstractfontengine_qws.cpp b/src/gui/text/qabstractfontengine_qws.cpp deleted file mode 100644 index 7cb868f655..0000000000 --- a/src/gui/text/qabstractfontengine_qws.cpp +++ /dev/null @@ -1,776 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qabstractfontengine_qws.h" -#include "qabstractfontengine_p.h" - -#include <private/qtextengine_p.h> -#include <private/qpaintengine_raster_p.h> - -#include <qmath.h> - -QT_BEGIN_NAMESPACE - -class QFontEngineInfoPrivate -{ -public: - inline QFontEngineInfoPrivate() - : pixelSize(0), weight(QFont::Normal), style(QFont::StyleNormal) - {} - - QString family; - qreal pixelSize; - int weight; - QFont::Style style; - QList<QFontDatabase::WritingSystem> writingSystems; -}; - -/*! - \class QFontEngineInfo - \preliminary - \brief The QFontEngineInfo class describes a specific font provided by a font engine plugin. - \since 4.3 - \ingroup qws - - \tableofcontents - - QFontEngineInfo is used to describe a request of a font to a font engine plugin as well as to - describe the actual fonts a plugin provides. - - \sa QAbstractFontEngine, QFontEnginePlugin -*/ - -/*! - Constructs a new empty QFontEngineInfo. -*/ -QFontEngineInfo::QFontEngineInfo() -{ - d = new QFontEngineInfoPrivate; -} - -/*! - Constructs a new QFontEngineInfo with the specified \a family. - The resulting object represents a freely scalable font with normal - weight and style. -*/ -QFontEngineInfo::QFontEngineInfo(const QString &family) -{ - d = new QFontEngineInfoPrivate; - d->family = family; -} - -/*! - Creates a new font engine info object with the same attributes as \a other. -*/ -QFontEngineInfo::QFontEngineInfo(const QFontEngineInfo &other) - : d(new QFontEngineInfoPrivate(*other.d)) -{ -} - -/*! - Assigns \a other to this font engine info object, and returns a reference - to this. -*/ -QFontEngineInfo &QFontEngineInfo::operator=(const QFontEngineInfo &other) -{ - *d = *other.d; - return *this; -} - -/*! - Destroys this QFontEngineInfo object. -*/ -QFontEngineInfo::~QFontEngineInfo() -{ - delete d; -} - -/*! - \property QFontEngineInfo::family - the family name of the font -*/ - -void QFontEngineInfo::setFamily(const QString &family) -{ - d->family = family; -} - -QString QFontEngineInfo::family() const -{ - return d->family; -} - -/*! - \property QFontEngineInfo::pixelSize - the pixel size of the font - - A pixel size of 0 represents a freely scalable font. -*/ - -void QFontEngineInfo::setPixelSize(qreal size) -{ - d->pixelSize = size; -} - -qreal QFontEngineInfo::pixelSize() const -{ - return d->pixelSize; -} - -/*! - \property QFontEngineInfo::weight - the weight of the font - - The value should be from the \l{QFont::Weight} enumeration. -*/ - -void QFontEngineInfo::setWeight(int weight) -{ - d->weight = weight; -} - -int QFontEngineInfo::weight() const -{ - return d->weight; -} - -/*! - \property QFontEngineInfo::style - the style of the font -*/ - -void QFontEngineInfo::setStyle(QFont::Style style) -{ - d->style = style; -} - -QFont::Style QFontEngineInfo::style() const -{ - return d->style; -} - -/*! - \property QFontEngineInfo::writingSystems - the writing systems supported by the font - - An empty list means that any writing system is supported. -*/ - -QList<QFontDatabase::WritingSystem> QFontEngineInfo::writingSystems() const -{ - return d->writingSystems; -} - -void QFontEngineInfo::setWritingSystems(const QList<QFontDatabase::WritingSystem> &writingSystems) -{ - d->writingSystems = writingSystems; -} - -class QFontEnginePluginPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QFontEnginePlugin) - - QString foundry; -}; - -/*! - \class QFontEnginePlugin - \preliminary - \brief The QFontEnginePlugin class is the base class for font engine factory plugins in Qt for Embedded Linux. - \since 4.3 - \ingroup qws - \ingroup plugins - - \tableofcontents - - QFontEnginePlugin is provided by font engine plugins to create - instances of subclasses of QAbstractFontEngine. - - The member functions create() and availableFontEngines() must be - implemented. - - \sa QAbstractFontEngine, QFontEngineInfo -*/ - -/*! - Creates a font engine plugin that creates font engines with the - specified \a foundry and \a parent. -*/ -QFontEnginePlugin::QFontEnginePlugin(const QString &foundry, QObject *parent) - : QObject(*new QFontEnginePluginPrivate, parent) -{ - Q_D(QFontEnginePlugin); - d->foundry = foundry; -} - -/*! - Destroys this font engine plugin. -*/ -QFontEnginePlugin::~QFontEnginePlugin() -{ -} - -/*! - Returns a list of foundries the font engine plugin provides. - The default implementation returns the foundry specified with the constructor. -*/ -QStringList QFontEnginePlugin::keys() const -{ - Q_D(const QFontEnginePlugin); - return QStringList(d->foundry); -} - -/*! - \fn QAbstractFontEngine *QFontEnginePlugin::create(const QFontEngineInfo &info) - - Implemented in subclasses to create a new font engine that provides a font that - matches \a info. -*/ - -/*! - \fn QList<QFontEngineInfo> QFontEnginePlugin::availableFontEngines() const - - Implemented in subclasses to return a list of QFontEngineInfo objects that represents all font - engines the plugin can create. -*/ - -class QAbstractFontEnginePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QAbstractFontEngine) -public: -}; - -//The <classname> class is|provides|contains|specifies... -/*! - \class QAbstractFontEngine - \preliminary - \brief The QAbstractFontEngine class is the base class for font engine plugins in Qt for Embedded Linux. - \since 4.3 - \ingroup qws - - \tableofcontents - - QAbstractFontEngine is implemented by font engine plugins through QFontEnginePlugin. - - \sa QFontEnginePlugin, QFontEngineInfo -*/ - -/*! - \enum QAbstractFontEngine::Capability - - This enum describes the capabilities of a font engine. - - \value CanRenderGlyphs_Gray The font engine can render individual glyphs into 8 bpp images. - \value CanRenderGlyphs_Mono The font engine can render individual glyphs into 1 bpp images. - \value CanRenderGlyphs The font engine can render individual glyphs into images. - \value CanOutlineGlyphs The font engine can convert glyphs to painter paths. -*/ - -/*! - \enum QAbstractFontEngine::FontProperty - - This enum describes the properties of a font provided by a font engine. - - \value Ascent The ascent of the font, specified as a 26.6 fixed point value. - \value Descent The descent of the font, specified as a 26.6 fixed point value. - \value Leading The leading of the font, specified as a 26.6 fixed point value. - \value XHeight The 'x' height of the font, specified as a 26.6 fixed point value. - \value AverageCharWidth The average character width of the font, specified as a 26.6 fixed point value. - \value LineThickness The thickness of the underline and strikeout lines for the font, specified as a 26.6 fixed point value. - \value UnderlinePosition The distance from the base line to the underline position for the font, specified as a 26.6 fixed point value. - \value MaxCharWidth The width of the widest character in the font, specified as a 26.6 fixed point value. - \value MinLeftBearing The minimum left bearing of the font, specified as a 26.6 fixed point value. - \value MinRightBearing The maximum right bearing of the font, specified as a 26.6 fixed point value. - \value GlyphCount The number of glyphs in the font, specified as an integer value. - \value CacheGlyphsHint A boolean value specifying whether rendered glyphs should be cached by Qt. - \value OutlineGlyphsHint A boolean value specifying whether the font engine prefers outline drawing over image rendering for uncached glyphs. -*/ - -/*! - \enum QAbstractFontEngine::TextShapingFlag - - This enum describes flags controlling conversion of characters to glyphs and their metrics. - - \value RightToLeft The text is used in a right-to-left context. - \value ReturnDesignMetrics Return font design metrics instead of pixel metrics. -*/ - -/*! - \typedef QAbstractFontEngine::Fixed - - This type is \c int, interpreted as a 26.6 fixed point value. -*/ - -/*! - \class QAbstractFontEngine::GlyphMetrics - \brief QAbstractFontEngine::GlyphMetrics defines the metrics of a single glyph. - \preliminary - \since 4.3 -*/ - -/*! - \variable QAbstractFontEngine::GlyphMetrics::x - - The horizontal offset from the origin. -*/ - -/*! - \fn QAbstractFontEngine::GlyphMetrics::GlyphMetrics() - - Constructs an empty glyph metrics object with all values - set to zero. -*/ - -/*! - \variable QAbstractFontEngine::GlyphMetrics::y - - The vertical offset from the origin (baseline). -*/ - -/*! - \variable QAbstractFontEngine::GlyphMetrics::width - - The width of the glyph. -*/ - -/*! - \variable QAbstractFontEngine::GlyphMetrics::height - - The height of the glyph. -*/ - -/*! - \variable QAbstractFontEngine::GlyphMetrics::advance - - The advance of the glyph. -*/ - -/*! - \class QAbstractFontEngine::FixedPoint - \brief QAbstractFontEngine::FixedPoint defines a point in the place using 26.6 fixed point precision. - \preliminary - \since 4.3 -*/ - -/*! - \variable QAbstractFontEngine::FixedPoint::x - - The x coordinate of this point. -*/ - -/*! - \variable QAbstractFontEngine::FixedPoint::y - - The y coordinate of this point. -*/ - -/*! - Constructs a new QAbstractFontEngine with the given \a parent. -*/ -QAbstractFontEngine::QAbstractFontEngine(QObject *parent) - : QObject(*new QAbstractFontEnginePrivate, parent) -{ -} - -/*! - Destroys this QAbstractFontEngine object. -*/ -QAbstractFontEngine::~QAbstractFontEngine() -{ -} - -/*! - \fn QAbstractFontEngine::Capabilities QAbstractFontEngine::capabilities() const - - Implemented in subclasses to specify the font engine's capabilities. The return value - may be cached by the caller and is expected not to change during the lifetime of the - font engine. -*/ - -/*! - \fn QVariant QAbstractFontEngine::fontProperty(FontProperty property) const - - Implemented in subclasses to return the value of the font attribute \a property. The return - value may be cached by the caller and is expected not to change during the lifetime of the font - engine. -*/ - -/*! - \fn bool QAbstractFontEngine::convertStringToGlyphIndices(const QChar *string, int length, uint *glyphs, int *numGlyphs, TextShapingFlags flags) const - - Implemented in subclasses to convert the characters specified by \a string and \a length to - glyph indicies, using \a flags. The glyph indicies should be returned in the \a glyphs array - provided by the caller. The maximum size of \a glyphs is specified by the value pointed to by \a - numGlyphs. If successful, the subclass implementation sets the value pointed to by \a numGlyphs - to the actual number of glyph indices generated, and returns true. Otherwise, e.g. if there is - not enough space in the provided \a glyphs array, it should set \a numGlyphs to the number of - glyphs needed for the conversion and return false. -*/ - -/*! - \fn void QAbstractFontEngine::getGlyphAdvances(const uint *glyphs, int numGlyphs, Fixed *advances, TextShapingFlags flags) const - - Implemented in subclasses to retrieve the advances of the array specified by \a glyphs and \a - numGlyphs, using \a flags. The result is returned in \a advances, which is allocated by the - caller and contains \a numGlyphs elements. -*/ - -/*! - \fn QAbstractFontEngine::GlyphMetrics QAbstractFontEngine::glyphMetrics(uint glyph) const - - Implemented in subclass to return the metrics for \a glyph. -*/ - -/*! - Implemented in subclasses to render the specified \a glyph into a \a buffer with the given \a depth , - \a bytesPerLine and \a height. - - Returns true if rendering succeeded, false otherwise. -*/ -bool QAbstractFontEngine::renderGlyph(uint glyph, int depth, int bytesPerLine, int height, uchar *buffer) -{ - Q_UNUSED(glyph) - Q_UNUSED(depth) - Q_UNUSED(bytesPerLine) - Q_UNUSED(height) - Q_UNUSED(buffer) - qWarning("QAbstractFontEngine: renderGlyph is not implemented in font plugin!"); - return false; -} - -/*! - Implemented in subclasses to add the outline of the glyphs specified by \a glyphs and \a - numGlyphs at the specified \a positions to the painter path \a path. -*/ -void QAbstractFontEngine::addGlyphOutlinesToPath(uint *glyphs, int numGlyphs, FixedPoint *positions, QPainterPath *path) -{ - Q_UNUSED(glyphs) - Q_UNUSED(numGlyphs) - Q_UNUSED(positions) - Q_UNUSED(path) - qWarning("QAbstractFontEngine: addGlyphOutlinesToPath is not implemented in font plugin!"); -} - -/* -bool QAbstractFontEngine::supportsExtension(Extension extension) const -{ - Q_UNUSED(extension) - return false; -} - -QVariant QAbstractFontEngine::extension(Extension extension, const QVariant &argument) -{ - Q_UNUSED(argument) - Q_UNUSED(extension) - return QVariant(); -} -*/ - -QProxyFontEngine::QProxyFontEngine(QAbstractFontEngine *customEngine, const QFontDef &def) - : engine(customEngine) -{ - fontDef = def; - engineCapabilities = engine->capabilities(); -} - -QProxyFontEngine::~QProxyFontEngine() -{ - delete engine; -} - -bool QProxyFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - QVarLengthArray<uint> glyphIndicies(*nglyphs); - if (!engine->convertStringToGlyphIndices(str, len, glyphIndicies.data(), nglyphs, QAbstractFontEngine::TextShapingFlags(int(flags)))) - return false; - - // ### use memcopy instead - for (int i = 0; i < *nglyphs; ++i) { - glyphs->glyphs[i] = glyphIndicies[i]; - } - glyphs->numGlyphs = *nglyphs; - - recalcAdvances(glyphs, flags); - return true; -} - -void QProxyFontEngine::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - const int nglyphs = glyphs->numGlyphs; - - QVarLengthArray<QAbstractFontEngine::Fixed> advances(nglyphs); - engine->getGlyphAdvances(glyphs->glyphs, nglyphs, advances.data(), QAbstractFontEngine::TextShapingFlags(int(flags))); - - - // ### use memcopy instead - for (int i = 0; i < nglyphs; ++i) { - glyphs->advances_x[i] = QFixed::fromFixed(advances[i]); - glyphs->advances_y[i] = 0; - } -} - - -static QImage alphaMapFromPath(QFontEngine *fe, glyph_t glyph) -{ - glyph_metrics_t gm = fe->boundingBox(glyph); - int glyph_x = qFloor(gm.x.toReal()); - int glyph_y = qFloor(gm.y.toReal()); - int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x; - int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y; - - if (glyph_width <= 0 || glyph_height <= 0) - return QImage(); - QFixedPoint pt; - pt.x = 0; - pt.y = -glyph_y; // the baseline - QPainterPath path; - QImage im(glyph_width + qAbs(glyph_x) + 4, glyph_height, QImage::Format_ARGB32_Premultiplied); - im.fill(Qt::transparent); - QPainter p(&im); - p.setRenderHint(QPainter::Antialiasing); - fe->addGlyphsToPath(&glyph, &pt, 1, &path, 0); - p.setPen(Qt::NoPen); - p.setBrush(Qt::black); - p.drawPath(path); - p.end(); - - QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - for (int y=0; y<im.height(); ++y) { - uchar *dst = (uchar *) indexed.scanLine(y); - uint *src = (uint *) im.scanLine(y); - for (int x=0; x<im.width(); ++x) - dst[x] = qAlpha(src[x]); - } - - return indexed; -} - - -QImage QProxyFontEngine::alphaMapForGlyph(glyph_t glyph) -{ - if (!(engineCapabilities & QAbstractFontEngine::CanRenderGlyphs_Gray)) - return alphaMapFromPath(this, glyph); - - QAbstractFontEngine::GlyphMetrics metrics = engine->glyphMetrics(glyph); - if (metrics.width <= 0 || metrics.height <= 0) - return QImage(); - - QImage img(metrics.width >> 6, metrics.height >> 6, QImage::Format_Indexed8); - - // ### we should have QImage::Format_GrayScale8 - static QVector<QRgb> colorMap; - if (colorMap.isEmpty()) { - colorMap.resize(256); - for (int i=0; i<256; ++i) - colorMap[i] = qRgba(0, 0, 0, i); - } - - img.setColorTable(colorMap); - - engine->renderGlyph(glyph, /*depth*/8, img.bytesPerLine(), img.height(), img.bits()); - - return img; -} - -void QProxyFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, QPainterPath *path, QTextItem::RenderFlags flags) -{ - if (engineCapabilities & QAbstractFontEngine::CanOutlineGlyphs) - engine->addGlyphOutlinesToPath(glyphs, nglyphs, reinterpret_cast<QAbstractFontEngine::FixedPoint *>(positions), path); - else - QFontEngine::addGlyphsToPath(glyphs, positions, nglyphs, path, flags); -} - -glyph_metrics_t QProxyFontEngine::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -ascent(), w, ascent() + descent(), w, 0); -} - -glyph_metrics_t QProxyFontEngine::boundingBox(glyph_t glyph) -{ - glyph_metrics_t m; - - QAbstractFontEngine::GlyphMetrics metrics = engine->glyphMetrics(glyph); - m.x = QFixed::fromFixed(metrics.x); - m.y = QFixed::fromFixed(metrics.y); - m.width = QFixed::fromFixed(metrics.width); - m.height = QFixed::fromFixed(metrics.height); - m.xoff = QFixed::fromFixed(metrics.advance); - - return m; -} - -QFixed QProxyFontEngine::ascent() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::Ascent).toInt()); -} - -QFixed QProxyFontEngine::descent() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::Descent).toInt()); -} - -QFixed QProxyFontEngine::leading() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::Leading).toInt()); -} - -QFixed QProxyFontEngine::xHeight() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::XHeight).toInt()); -} - -QFixed QProxyFontEngine::averageCharWidth() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::AverageCharWidth).toInt()); -} - -QFixed QProxyFontEngine::lineThickness() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::LineThickness).toInt()); -} - -QFixed QProxyFontEngine::underlinePosition() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::UnderlinePosition).toInt()); -} - -qreal QProxyFontEngine::maxCharWidth() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::MaxCharWidth).toInt()).toReal(); -} - -qreal QProxyFontEngine::minLeftBearing() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::MinLeftBearing).toInt()).toReal(); -} - -qreal QProxyFontEngine::minRightBearing() const -{ - return QFixed::fromFixed(engine->fontProperty(QAbstractFontEngine::MinRightBearing).toInt()).toReal(); -} - -int QProxyFontEngine::glyphCount() const -{ - return engine->fontProperty(QAbstractFontEngine::GlyphCount).toInt(); -} - -bool QProxyFontEngine::canRender(const QChar *string, int len) -{ - QVarLengthArray<uint> glyphs(len); - int numGlyphs = len; - - if (!engine->convertStringToGlyphIndices(string, len, glyphs.data(), &numGlyphs, /*flags*/0)) - return false; - - for (int i = 0; i < numGlyphs; ++i) - if (!glyphs[i]) - return false; - - return true; -} - -void QProxyFontEngine::draw(QPaintEngine *p, qreal _x, qreal _y, const QTextItemInt &si) -{ - QPaintEngineState *pState = p->state; - QRasterPaintEngine *paintEngine = static_cast<QRasterPaintEngine*>(p); - - QTransform matrix = pState->transform(); - matrix.translate(_x, _y); - QFixed x = QFixed::fromReal(matrix.dx()); - QFixed y = QFixed::fromReal(matrix.dy()); - - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - getGlyphPositions(si.glyphs, matrix, si.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - for(int i = 0; i < glyphs.size(); i++) { - QImage glyph = alphaMapForGlyph(glyphs[i]); - if (glyph.isNull()) - continue; - - if (glyph.format() != QImage::Format_Indexed8 - && glyph.format() != QImage::Format_Mono) - continue; - - QAbstractFontEngine::GlyphMetrics metrics = engine->glyphMetrics(glyphs[i]); - - int depth = glyph.format() == QImage::Format_Mono ? 1 : 8; - paintEngine->alphaPenBlt(glyph.bits(), glyph.bytesPerLine(), depth, - qRound(positions[i].x + QFixed::fromFixed(metrics.x)), - qRound(positions[i].y + QFixed::fromFixed(metrics.y)), - glyph.width(), glyph.height()); - } -} - -/* - * This is only called when we use the proxy fontengine directly (without sharing the rendered - * glyphs). So we prefer outline rendering over rendering of unshared glyphs. That decision is - * done in qfontdatabase_qws.cpp by looking at the ShareGlyphsHint and the pixel size of the font. - */ -bool QProxyFontEngine::drawAsOutline() const -{ - if (!(engineCapabilities & QAbstractFontEngine::CanOutlineGlyphs)) - return false; - - QVariant outlineHint = engine->fontProperty(QAbstractFontEngine::OutlineGlyphsHint); - return !outlineHint.isValid() || outlineHint.toBool(); -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qabstractfontengine_qws.h b/src/gui/text/qabstractfontengine_qws.h deleted file mode 100644 index dfc15dcf5d..0000000000 --- a/src/gui/text/qabstractfontengine_qws.h +++ /dev/null @@ -1,221 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QABSTRACTFONTENGINE_QWS_H -#define QABSTRACTFONTENGINE_QWS_H - -#include <QtCore/qobject.h> -#include <QtCore/qhash.h> -#include <QtCore/qvariant.h> -#include <QtCore/qfactoryinterface.h> -#include <QtGui/qpaintengine.h> -#include <QtGui/qfontdatabase.h> - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QFontEngineInfoPrivate; - -class Q_GUI_EXPORT QFontEngineInfo -{ -public: - QDOC_PROPERTY(QString family READ family WRITE setFamily) - QDOC_PROPERTY(qreal pixelSize READ pixelSize WRITE setPixelSize) - QDOC_PROPERTY(int weight READ weight WRITE setWeight) - QDOC_PROPERTY(QFont::Style style READ style WRITE setStyle) - QDOC_PROPERTY(QList<QFontDatabase::WritingSystem> writingSystems READ writingSystems WRITE setWritingSystems) - - QFontEngineInfo(); - explicit QFontEngineInfo(const QString &family); - QFontEngineInfo(const QFontEngineInfo &other); - QFontEngineInfo &operator=(const QFontEngineInfo &other); - ~QFontEngineInfo(); - - void setFamily(const QString &name); - QString family() const; - - void setPixelSize(qreal size); - qreal pixelSize() const; - - void setWeight(int weight); - int weight() const; - - void setStyle(QFont::Style style); - QFont::Style style() const; - - QList<QFontDatabase::WritingSystem> writingSystems() const; - void setWritingSystems(const QList<QFontDatabase::WritingSystem> &writingSystems); - -private: - QFontEngineInfoPrivate *d; -}; - -class QAbstractFontEngine; - -struct Q_GUI_EXPORT QFontEngineFactoryInterface : public QFactoryInterface -{ - virtual QAbstractFontEngine *create(const QFontEngineInfo &info) = 0; - virtual QList<QFontEngineInfo> availableFontEngines() const = 0; -}; - -#define QFontEngineFactoryInterface_iid "com.trolltech.Qt.QFontEngineFactoryInterface" -Q_DECLARE_INTERFACE(QFontEngineFactoryInterface, QFontEngineFactoryInterface_iid) - -class QFontEnginePluginPrivate; - -class Q_GUI_EXPORT QFontEnginePlugin : public QObject, public QFontEngineFactoryInterface -{ - Q_OBJECT - Q_INTERFACES(QFontEngineFactoryInterface:QFactoryInterface) -public: - QFontEnginePlugin(const QString &foundry, QObject *parent = 0); - ~QFontEnginePlugin(); - - virtual QStringList keys() const; - - virtual QAbstractFontEngine *create(const QFontEngineInfo &info) = 0; - virtual QList<QFontEngineInfo> availableFontEngines() const = 0; - -private: - Q_DECLARE_PRIVATE(QFontEnginePlugin) - Q_DISABLE_COPY(QFontEnginePlugin) -}; - -class QAbstractFontEnginePrivate; - -class Q_GUI_EXPORT QAbstractFontEngine : public QObject -{ - Q_OBJECT -public: - enum Capability { - CanOutlineGlyphs = 1, - CanRenderGlyphs_Mono = 2, - CanRenderGlyphs_Gray = 4, - CanRenderGlyphs = CanRenderGlyphs_Mono | CanRenderGlyphs_Gray - }; - Q_DECLARE_FLAGS(Capabilities, Capability) - - explicit QAbstractFontEngine(QObject *parent = 0); - ~QAbstractFontEngine(); - - typedef int Fixed; // 26.6 - - struct FixedPoint - { - Fixed x; - Fixed y; - }; - - struct GlyphMetrics - { - inline GlyphMetrics() - : x(0), y(0), width(0), height(0), - advance(0) {} - Fixed x; - Fixed y; - Fixed width; - Fixed height; - Fixed advance; - }; - - enum FontProperty { - Ascent, - Descent, - Leading, - XHeight, - AverageCharWidth, - LineThickness, - UnderlinePosition, - MaxCharWidth, - MinLeftBearing, - MinRightBearing, - GlyphCount, - - // hints - CacheGlyphsHint, - OutlineGlyphsHint - }; - - // keep in sync with QTextEngine::ShaperFlag!! - enum TextShapingFlag { - RightToLeft = 0x0001, - ReturnDesignMetrics = 0x0002 - }; - Q_DECLARE_FLAGS(TextShapingFlags, TextShapingFlag) - - virtual Capabilities capabilities() const = 0; - virtual QVariant fontProperty(FontProperty property) const = 0; - - virtual bool convertStringToGlyphIndices(const QChar *string, int length, uint *glyphs, int *numGlyphs, TextShapingFlags flags) const = 0; - - virtual void getGlyphAdvances(const uint *glyphs, int numGlyphs, Fixed *advances, TextShapingFlags flags) const = 0; - - virtual GlyphMetrics glyphMetrics(uint glyph) const = 0; - - virtual bool renderGlyph(uint glyph, int depth, int bytesPerLine, int height, uchar *buffer); - - virtual void addGlyphOutlinesToPath(uint *glyphs, int numGlyphs, FixedPoint *positions, QPainterPath *path); - - /* - enum Extension { - GetTrueTypeTable - }; - - virtual bool supportsExtension(Extension extension) const; - virtual QVariant extension(Extension extension, const QVariant &argument = QVariant()); - */ - -private: - Q_DECLARE_PRIVATE(QAbstractFontEngine) - Q_DISABLE_COPY(QAbstractFontEngine) -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFontEngine::Capabilities) -Q_DECLARE_OPERATORS_FOR_FLAGS(QAbstractFontEngine::TextShapingFlags) - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 052dc72b63..8eb68be207 100644 --- a/src/gui/text/qcssparser.cpp +++ b/src/gui/text/qcssparser.cpp @@ -1275,6 +1275,8 @@ void ValueExtractor::extractFont() bool ValueExtractor::extractImage(QIcon *icon, Qt::Alignment *a, QSize *size) { bool hit = false; +#if 0 + // ### Qt5 for (int i = 0; i < declarations.count(); ++i) { const Declaration &decl = declarations.at(i); switch (decl.d->propertyId) { @@ -1295,6 +1297,7 @@ bool ValueExtractor::extractImage(QIcon *icon, Qt::Alignment *a, QSize *size) } hit = true; } +#endif return hit; } @@ -1643,6 +1646,8 @@ void Declaration::borderImageValue(QString *image, int *cuts, *h = *v; } +#if 0 +// ### Qt 5 QIcon Declaration::iconValue() const { if (d->parsed.isValid()) @@ -1689,6 +1694,7 @@ QIcon Declaration::iconValue() const d->parsed = QVariant::fromValue<QIcon>(icon); return icon; } +#endif /////////////////////////////////////////////////////////////////////////////// // Selector diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h index 86bafc9215..4fc720fcef 100644 --- a/src/gui/text/qcssparser_p.h +++ b/src/gui/text/qcssparser_p.h @@ -61,9 +61,9 @@ #include <QtCore/QMultiHash> #include <QtGui/QFont> #include <QtGui/QPalette> -#include <QtGui/QIcon> #include <QtCore/QSharedData> +class QIcon; #ifndef QT_NO_CSSPARSER @@ -453,7 +453,7 @@ struct Q_AUTOTEST_EXPORT Declaration QSize sizeValue() const; QRect rectValue() const; QString uriValue() const; - QIcon iconValue() const; +// QIcon iconValue() const; void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const; }; @@ -633,7 +633,7 @@ enum StyleSheetOrigin { StyleSheetOrigin_Inline }; -struct StyleSheet +struct Q_GUI_EXPORT StyleSheet { StyleSheet() : origin(StyleSheetOrigin_Unspecified), depth(0) { } QVector<StyleRule> styleRules; //only contains rules that are not indexed diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index b8cfb1f902..503263345c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -48,7 +48,7 @@ #include "qpainter.h" #include "qhash.h" #include "qdatastream.h" -#include "qapplication.h" +#include "qguiapplication.h" #include "qstringlist.h" #include "qthread.h" @@ -65,19 +65,12 @@ #include "qx11info_x11.h" #include <private/qt_x11_p.h> #endif -#ifdef Q_WS_QWS -#include "qscreen_qws.h" -#if !defined(QT_NO_QWS_QPF2) -#include <qfile.h> -#include "qfontengine_qpf_p.h" -#endif -#endif #ifdef Q_OS_SYMBIAN #include <private/qt_s60_p.h> #endif #ifdef Q_WS_QPA #include <QtGui/qplatformscreen_qpa.h> -#include <QtGui/private/qapplication_p.h> +#include <QtGui/private/qguiapplication_p.h> #endif #include <QMutexLocker> @@ -171,18 +164,10 @@ Q_GUI_EXPORT int qt_defaultDpiX() #elif defined(Q_WS_MAC) extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp dpi = qt_mac_defaultDpi_x(); -#elif defined(Q_WS_QWS) - if (!qt_screen) - return 72; - QScreen *screen = qt_screen; - const QList<QScreen*> subScreens = qt_screen->subScreens(); - if (!subScreens.isEmpty()) - screen = subScreens.at(0); - dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4))); #elif defined(Q_WS_QPA) - QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); if (pi) { - QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + QPlatformScreen *screen = pi->screens().at(0); const QSize screenSize = screen->geometry().size(); const QSize physicalSize = screen->physicalSize(); dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4))); @@ -210,18 +195,10 @@ Q_GUI_EXPORT int qt_defaultDpiY() #elif defined(Q_WS_MAC) extern float qt_mac_defaultDpi_y(); //qpaintdevice_mac.cpp dpi = qt_mac_defaultDpi_y(); -#elif defined(Q_WS_QWS) - if (!qt_screen) - return 72; - QScreen *screen = qt_screen; - const QList<QScreen*> subScreens = qt_screen->subScreens(); - if (!subScreens.isEmpty()) - screen = subScreens.at(0); - dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4))); #elif defined(Q_WS_QPA) - QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); if (pi) { - QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + QPlatformScreen *screen = pi->screens().at(0); const QSize screenSize = screen->geometry().size(); const QSize physicalSize = screen->physicalSize(); dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4))); @@ -448,9 +425,9 @@ QFontEngineData::~QFontEngineData() Use QFontMetrics to get measurements, e.g. the pixel length of a string using QFontMetrics::width(). - Note that a QApplication instance must exist before a QFont can be + Note that a QGuiApplication instance must exist before a QFont can be used. You can set the application's default font with - QApplication::setFont(). + QGuiApplication::setFont(). If a chosen font does not include all the characters that need to be displayed, QFont will try to find the characters in the @@ -781,10 +758,10 @@ void QFont::detach() /*! Constructs a font object that uses the application's default font. - \sa QApplication::setFont(), QApplication::font() + \sa QGuiApplication::setFont(), QGuiApplication::font() */ QFont::QFont() - : d(QApplication::font().d.data()), resolve_mask(0) + : d(QGuiApplication::font().d.data()), resolve_mask(0) { } @@ -804,7 +781,7 @@ QFont::QFont() algorithm. \sa Weight, setFamily(), setPointSize(), setWeight(), setItalic(), - setStyleHint() QApplication::font() + setStyleHint() QGuiApplication::font() */ QFont::QFont(const QString &family, int pointSize, int weight, bool italic) : d(new QFontPrivate()), resolve_mask(QFont::FamilyResolved) @@ -1096,18 +1073,6 @@ int QFont::pixelSize() const return d->request.pixelSize; } -#ifdef QT3_SUPPORT -/*! \obsolete - - Sets the logical pixel height of font characters when shown on - the screen to \a pixelSize. -*/ -void QFont::setPixelSizeFloat(qreal pixelSize) -{ - setPixelSize((int)pixelSize); -} -#endif - /*! \fn bool QFont::italic() const @@ -1875,43 +1840,6 @@ QFont QFont::resolve(const QFont &other) const \internal */ -#ifdef QT3_SUPPORT - -/*! \obsolete - - Please use QApplication::font() instead. -*/ -QFont QFont::defaultFont() -{ - return QApplication::font(); -} - -/*! \obsolete - - Please use QApplication::setFont() instead. -*/ -void QFont::setDefaultFont(const QFont &f) -{ - QApplication::setFont(f); -} - -/*! - \fn qreal QFont::pointSizeFloat() const - \compat - - Use pointSizeF() instead. -*/ - -/*! - \fn void QFont::setPointSizeFloat(qreal size) - \compat - - Use setPointSizeF() instead. -*/ -#endif - - - /***************************************************************************** QFont substitution management diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h index 0c7b6f8de8..194e3ad34a 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -283,14 +283,6 @@ public: inline uint resolve() const { return resolve_mask; } inline void resolve(uint mask) { resolve_mask = mask; } -#ifdef QT3_SUPPORT - static QT3_SUPPORT QFont defaultFont(); - static QT3_SUPPORT void setDefaultFont(const QFont &); - QT3_SUPPORT void setPixelSizeFloat(qreal); - QT3_SUPPORT qreal pointSizeFloat() const { return pointSizeF(); } - QT3_SUPPORT void setPointSizeFloat(qreal size) { setPointSizeF(size); } -#endif - private: QFont(QFontPrivate *); diff --git a/src/gui/text/qfont_mac.cpp b/src/gui/text/qfont_mac.cpp deleted file mode 100644 index 044fd84a8b..0000000000 --- a/src/gui/text/qfont_mac.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfont.h" -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qfontengine_mac_p.h" -#include "qfontengine_coretext_p.h" -#include "qfontinfo.h" -#include "qfontmetrics.h" -#include "qpaintdevice.h" -#include "qstring.h" -#include <private/qt_mac_p.h> -#include <private/qtextengine_p.h> -#include <private/qunicodetables_p.h> -#include <qapplication.h> -#include "qfontdatabase.h" -#include <qpainter.h> -#include "qtextengine_p.h" -#include <stdlib.h> - -QT_BEGIN_NAMESPACE - -extern float qt_mac_defaultDpi_x(); //qpaintdevice_mac.cpp - -int qt_mac_pixelsize(const QFontDef &def, int dpi) -{ - float ret; - if(def.pixelSize == -1) - ret = def.pointSize * dpi / qt_mac_defaultDpi_x(); - else - ret = def.pixelSize; - return qRound(ret); -} -int qt_mac_pointsize(const QFontDef &def, int dpi) -{ - float ret; - if(def.pointSize < 0) - ret = def.pixelSize * qt_mac_defaultDpi_x() / float(dpi); - else - ret = def.pointSize; - return qRound(ret); -} - -QString QFont::rawName() const -{ - return family(); -} - -void QFont::setRawName(const QString &name) -{ - setFamily(name); -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - -/*! - Returns an ATSUFontID -*/ -quint32 QFont::macFontID() const // ### need 64-bit version -{ -#ifdef QT_MAC_USE_COCOA - return 0; -#elif 1 - QFontEngine *fe = d->engineForScript(QUnicodeTables::Common); - if (fe && fe->type() == QFontEngine::Multi) - return static_cast<QFontEngineMacMulti*>(fe)->macFontID(); -#else - Str255 name; - if(FMGetFontFamilyName((FMFontFamily)((UInt32)handle()), name) == noErr) { - short fnum; - GetFNum(name, &fnum); - return fnum; - } -#endif - return 0; -} - -// Returns an ATSUFonFamilyRef -Qt::HANDLE QFont::handle() const -{ -#ifdef QT_MAC_USE_COCOA - QFontEngine *fe = d->engineForScript(QUnicodeTables::Common); - if (fe && fe->type() == QFontEngine::Multi) - return (Qt::HANDLE)static_cast<QCoreTextFontEngineMulti*>(fe)->macFontID(); -#endif - return 0; -} - -void QFont::initialize() -{ } - -QString QFont::defaultFamily() const -{ - switch(d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("Times New Roman"); - case QFont::Courier: - return QString::fromLatin1("Courier New"); - case QFont::Monospace: - return QString::fromLatin1("Courier"); - case QFont::Decorative: - return QString::fromLatin1("Bookman Old Style"); - case QFont::Cursive: - return QString::fromLatin1("Apple Chancery"); - case QFont::Fantasy: - return QString::fromLatin1("Papyrus"); - case QFont::Helvetica: - case QFont::System: - default: - return QString::fromLatin1("Helvetica"); - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("Helvetica"); -} - -QString QFont::lastResortFont() const -{ - return QString::fromLatin1("Geneva"); -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp index ff12da8d97..981c313201 100644 --- a/src/gui/text/qfont_qpa.cpp +++ b/src/gui/text/qfont_qpa.cpp @@ -39,14 +39,14 @@ ** ****************************************************************************/ -#include <QtGui/private/qapplication_p.h> +#include <QtGui/private/qguiapplication_p.h> #include <QtGui/QPlatformFontDatabase> QT_BEGIN_NAMESPACE void QFont::initialize() { - QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); } void QFont::cleanup() @@ -90,7 +90,7 @@ QString QFont::defaultFamily() const familyName = QString::fromLatin1("helvetica"); } - QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QFont::StyleHint(d->request.styleHint),QUnicodeTables::Common); + QStringList list = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QFont::StyleHint(d->request.styleHint),QUnicodeTables::Common); if (list.size()) { familyName = list.at(0); } diff --git a/src/gui/text/qfont_qws.cpp b/src/gui/text/qfont_qws.cpp deleted file mode 100644 index ea2a944432..0000000000 --- a/src/gui/text/qfont_qws.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qwidget.h" -#include "qpainter.h" -#include "qfont_p.h" -#include <private/qunicodetables_p.h> -#include "qfontdatabase.h" -#include "qtextcodec.h" -#include "qapplication.h" -#include "qfile.h" -#include "qtextstream.h" -#include "qmap.h" -//#include "qmemorymanager_qws.h" -#include "qtextengine_p.h" -#include "qfontengine_p.h" -#if !defined(QT_NO_FREETYPE) -#include "qfontengine_ft_p.h" -#endif - -QT_BEGIN_NAMESPACE - -void QFont::initialize() -{ } - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - - -/***************************************************************************** - QFont member functions - *****************************************************************************/ - -Qt::HANDLE QFont::handle() const -{ -#ifndef QT_NO_FREETYPE - return freetypeFace(); -#endif - return 0; -} - -FT_Face QFont::freetypeFace() const -{ -#ifndef QT_NO_FREETYPE - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); - if (engine->type() == QFontEngine::Freetype) { - const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine); - return ft->non_locked_face(); - } -#endif - return 0; -} - -QString QFont::rawName() const -{ - return QLatin1String("unknown"); -} - -void QFont::setRawName(const QString &) -{ -} - -QString QFont::defaultFamily() const -{ - switch(d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("times"); - case QFont::Courier: - case QFont::Monospace: - return QString::fromLatin1("courier"); - case QFont::Decorative: - return QString::fromLatin1("old english"); - case QFont::Helvetica: - case QFont::System: - default: - return QString::fromLatin1("helvetica"); - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("helvetica"); -} - -QString QFont::lastResortFont() const -{ - qFatal("QFont::lastResortFont: Cannot find any reasonable font"); - // Shut compiler up - return QString(); -} - - -QT_END_NAMESPACE diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp deleted file mode 100644 index 114191d765..0000000000 --- a/src/gui/text/qfont_s60.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfont.h" -#include "qfont_p.h" -#include <private/qt_s60_p.h> -#include <private/qpixmap_s60_p.h> -#include "qmutex.h" - -QT_BEGIN_NAMESPACE - -#ifdef QT_NO_FREETYPE -Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex); -#endif // QT_NO_FREETYPE - -extern QStringList qt_symbian_fontFamiliesOnFontServer(); // qfontdatabase_s60.cpp -Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, fontFamiliesOnFontServer, { - // We are only interested in the initial font families. No Application fonts. - // Therefore, we are allowed to cache the list. - x->append(qt_symbian_fontFamiliesOnFontServer()); -}); - -QString QFont::lastResortFont() const -{ - // Symbian's font Api does not distinguish between font and family. - // Therefore we try to get a "Family" first, then fall back to "Sans". - static QString font = lastResortFamily(); - if (font.isEmpty()) - font = QLatin1String("Sans"); - return font; -} - -QString QFont::lastResortFamily() const -{ -#ifdef QT_NO_FREETYPE - QMutexLocker locker(lastResortFamilyMutex()); - static QString family; - if (family.isEmpty()) { - - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - CFont *font; - const TInt err = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec()); - Q_ASSERT(err == KErrNone); - const TFontSpec spec = font->FontSpecInTwips(); - family = QString((const QChar *)spec.iTypeface.iName.Ptr(), spec.iTypeface.iName.Length()); - S60->screenDevice()->ReleaseFont(font); - - lock.relock(); - } - return family; -#else // QT_NO_FREETYPE - // For the FreeType case we just hard code the face name, since otherwise on - // East Asian systems we may get a name for a stroke based (non-ttf) font. - - // TODO: Get the type face name in a proper way - - const bool isJapaneseOrChineseSystem = - User::Language() == ELangJapanese || User::Language() == ELangPrcChinese; - - static QString family; - if (family.isEmpty()) { - QStringList families = qt_symbian_fontFamiliesOnFontServer(); - const char* const preferredFamilies[] = {"Nokia Sans S60", "Series 60 Sans"}; - for (int i = 0; i < sizeof preferredFamilies / sizeof preferredFamilies[0]; ++i) { - const QString preferredFamily = QLatin1String(preferredFamilies[i]); - if (families.contains(preferredFamily)) { - family = preferredFamily; - break; - } - } - } - - return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":family.toLatin1()); -#endif // QT_NO_FREETYPE -} - -QString QFont::defaultFamily() const -{ -#ifdef QT_NO_FREETYPE - switch(d->request.styleHint) { - case QFont::SansSerif: { - static const char* const preferredSansSerif[] = {"Nokia Sans S60", "Series 60 Sans"}; - for (int i = 0; i < sizeof preferredSansSerif / sizeof preferredSansSerif[0]; ++i) { - const QString sansSerif = QLatin1String(preferredSansSerif[i]); - if (fontFamiliesOnFontServer()->contains(sansSerif)) - return sansSerif; - } - } - // No break. Intentional fall through. - default: - return lastResortFamily(); - } -#endif // QT_NO_FREETYPE - return lastResortFamily(); -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfont_win.cpp b/src/gui/text/qfont_win.cpp deleted file mode 100644 index 3ef761bfa5..0000000000 --- a/src/gui/text/qfont_win.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfont.h" -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qtextengine_p.h" -#include "qfontmetrics.h" -#include "qfontinfo.h" - -#include "qwidget.h" -#include "qpainter.h" -#include <limits.h> -#include "qt_windows.h" -#include <private/qapplication_p.h> -#include "qapplication.h" -#include <private/qunicodetables_p.h> -#include <qfontdatabase.h> - -QT_BEGIN_NAMESPACE - -extern HDC shared_dc(); // common dc for all fonts -extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp - -// ### maybe move to qapplication_win -QFont qt_LOGFONTtoQFont(LOGFONT& lf, bool /*scale*/) -{ - QString family = QString::fromWCharArray(lf.lfFaceName); - QFont qf(family); - qf.setItalic(lf.lfItalic); - if (lf.lfWeight != FW_DONTCARE) - qf.setWeight(weightFromInteger(lf.lfWeight)); - int lfh = qAbs(lf.lfHeight); - qf.setPointSizeF(lfh * 72.0 / GetDeviceCaps(shared_dc(),LOGPIXELSY)); - qf.setUnderline(false); - qf.setOverline(false); - qf.setStrikeOut(false); - return qf; -} - - -static inline float pixelSize(const QFontDef &request, int dpi) -{ - float pSize; - if (request.pointSize != -1) - pSize = request.pointSize * dpi/ 72.; - else - pSize = request.pixelSize; - return pSize; -} - -static inline float pointSize(const QFontDef &fd, int dpi) -{ - float pSize; - if (fd.pointSize < 0) - pSize = fd.pixelSize * 72. / ((float)dpi); - else - pSize = fd.pointSize; - return pSize; -} - -/***************************************************************************** - QFont member functions - *****************************************************************************/ - -void QFont::initialize() -{ -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - -HFONT QFont::handle() const -{ - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - Q_ASSERT(engine != 0); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); - if (engine->type() == QFontEngine::Win) - return static_cast<QFontEngineWin *>(engine)->hfont; - return 0; -} - -QString QFont::rawName() const -{ - return family(); -} - -void QFont::setRawName(const QString &name) -{ - setFamily(name); -} - -QString QFont::defaultFamily() const -{ - switch(d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("Times New Roman"); - case QFont::Courier: - case QFont::Monospace: - return QString::fromLatin1("Courier New"); - case QFont::Decorative: - return QString::fromLatin1("Bookman Old Style"); - case QFont::Cursive: - return QString::fromLatin1("Comic Sans MS"); - case QFont::Fantasy: - return QString::fromLatin1("Impact"); - case QFont::Helvetica: - return QString::fromLatin1("Arial"); - case QFont::System: - default: - return QString::fromLatin1("MS Sans Serif"); - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("helvetica"); -} - -QString QFont::lastResortFont() const -{ - return QString::fromLatin1("arial"); -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfont_x11.cpp b/src/gui/text/qfont_x11.cpp deleted file mode 100644 index c72a5fade5..0000000000 --- a/src/gui/text/qfont_x11.cpp +++ /dev/null @@ -1,368 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#define QT_FATAL_ASSERT - -#include "qplatformdefs.h" - -#include "qfont.h" -#include "qapplication.h" -#include "qfontinfo.h" -#include "qfontdatabase.h" -#include "qfontmetrics.h" -#include "qpaintdevice.h" -#include "qtextcodec.h" -#include "qiodevice.h" -#include "qhash.h" - -#include <private/qunicodetables_p.h> -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qfontengine_x11_p.h" -#include "qtextengine_p.h" - -#include <private/qt_x11_p.h> -#include "qx11info_x11.h" - -#include <time.h> -#include <stdlib.h> -#include <ctype.h> - -#define QFONTLOADER_DEBUG -#define QFONTLOADER_DEBUG_VERBOSE - -QT_BEGIN_NAMESPACE - -double qt_pixelSize(double pointSize, int dpi) -{ - if (pointSize < 0) - return -1.; - if (dpi == 75) // the stupid 75 dpi setting on X11 - dpi = 72; - return (pointSize * dpi) /72.; -} - -double qt_pointSize(double pixelSize, int dpi) -{ - if (pixelSize < 0) - return -1.; - if (dpi == 75) // the stupid 75 dpi setting on X11 - dpi = 72; - return pixelSize * 72. / ((double) dpi); -} - -/* - Removes wildcards from an XLFD. - - Returns \a xlfd with all wildcards removed if a match for \a xlfd is - found, otherwise it returns \a xlfd. -*/ -static QByteArray qt_fixXLFD(const QByteArray &xlfd) -{ - QByteArray ret = xlfd; - int count = 0; - char **fontNames = - XListFonts(QX11Info::display(), xlfd, 32768, &count); - if (count > 0) - ret = fontNames[0]; - XFreeFontNames(fontNames); - return ret ; -} - -typedef QHash<int, QString> FallBackHash; -Q_GLOBAL_STATIC(FallBackHash, fallBackHash) - -// Returns the user-configured fallback family for the specified script. -QString qt_fallback_font_family(int script) -{ - FallBackHash *hash = fallBackHash(); - return hash->value(script); -} - -// Sets the fallback family for the specified script. -Q_GUI_EXPORT void qt_x11_set_fallback_font_family(int script, const QString &family) -{ - FallBackHash *hash = fallBackHash(); - if (!family.isEmpty()) - hash->insert(script, family); - else - hash->remove(script); -} - -int QFontPrivate::defaultEncodingID = -1; - -void QFont::initialize() -{ - extern int qt_encoding_id_for_mib(int mib); // from qfontdatabase_x11.cpp - QTextCodec *codec = QTextCodec::codecForLocale(); - // determine the default encoding id using the locale, otherwise - // fallback to latin1 (mib == 4) - int mib = codec ? codec->mibEnum() : 4; - - // for asian locales, use the mib for the font codec instead of the locale codec - switch (mib) { - case 38: // eucKR - mib = 36; - break; - - case 2025: // GB2312 - mib = 57; - break; - - case 113: // GBK - mib = -113; - break; - - case 114: // GB18030 - mib = -114; - break; - - case 2026: // Big5 - mib = -2026; - break; - - case 2101: // Big5-HKSCS - mib = -2101; - break; - - case 16: // JIS7 - mib = 15; - break; - - case 17: // SJIS - case 18: // eucJP - mib = 63; - break; - } - - // get the default encoding id for the locale encoding... - QFontPrivate::defaultEncodingID = qt_encoding_id_for_mib(mib); -} - -void QFont::cleanup() -{ - QFontCache::cleanup(); -} - -/*! - \internal - X11 Only: Returns the screen with which this font is associated. -*/ -int QFont::x11Screen() const -{ - return d->screen; -} - -/*! \internal - X11 Only: Associate the font with the specified \a screen. -*/ -void QFont::x11SetScreen(int screen) -{ - if (screen < 0) // assume default - screen = QX11Info::appScreen(); - - if (screen == d->screen) - return; // nothing to do - - detach(); - d->screen = screen; -} - -Qt::HANDLE QFont::handle() const -{ - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - Q_ASSERT(engine != 0); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); - if (engine->type() == QFontEngine::XLFD) - return static_cast<QFontEngineXLFD *>(engine)->fontStruct()->fid; - return 0; -} - - -FT_Face QFont::freetypeFace() const -{ -#ifndef QT_NO_FREETYPE - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); -#ifndef QT_NO_FONTCONFIG - if (engine->type() == QFontEngine::Freetype) { - const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine); - return ft->non_locked_face(); - } else -#endif - if (engine->type() == QFontEngine::XLFD) { - const QFontEngineXLFD *xlfd = static_cast<const QFontEngineXLFD *>(engine); - return xlfd->non_locked_face(); - } -#endif - return 0; -} - -QString QFont::rawName() const -{ - QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); - Q_ASSERT(engine != 0); - if (engine->type() == QFontEngine::Multi) - engine = static_cast<QFontEngineMulti *>(engine)->engine(0); - if (engine->type() == QFontEngine::XLFD) - return QString::fromLatin1(engine->name()); - return QString(); -} -struct QtFontDesc; - -void QFont::setRawName(const QString &name) -{ - detach(); - - // from qfontdatabase_x11.cpp - extern bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *desc); - - if (!qt_fillFontDef(qt_fixXLFD(name.toLatin1()), &d->request, d->dpi, 0)) { - qWarning("QFont::setRawName: Invalid XLFD: \"%s\"", name.toLatin1().constData()); - - setFamily(name); - setRawMode(true); - } else { - resolve_mask = QFont::AllPropertiesResolved; - } -} - -QString QFont::lastResortFamily() const -{ - return QString::fromLatin1("Helvetica"); -} - -QString QFont::defaultFamily() const -{ - switch (d->request.styleHint) { - case QFont::Times: - return QString::fromLatin1("Times"); - - case QFont::Courier: - return QString::fromLatin1("Courier"); - - case QFont::Monospace: - return QString::fromLatin1("Courier New"); - - case QFont::Cursive: - return QString::fromLatin1("Comic Sans MS"); - - case QFont::Fantasy: - return QString::fromLatin1("Impact"); - - case QFont::Decorative: - return QString::fromLatin1("Old English"); - - case QFont::Helvetica: - case QFont::System: - default: - return QString::fromLatin1("Helvetica"); - } -} - -/* - Returns a last resort raw font name for the font matching algorithm. - This is used if even the last resort family is not available. It - returns \e something, almost no matter what. The current - implementation tries a wide variety of common fonts, returning the - first one it finds. The implementation may change at any time. -*/ -static const char * const tryFonts[] = { - "-*-helvetica-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-courier-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-times-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-lucida-medium-r-*-*-*-120-*-*-*-*-*-*", - "-*-helvetica-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-courier-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-times-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-lucida-*-*-*-*-*-120-*-*-*-*-*-*", - "-*-helvetica-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-courier-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-times-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-lucida-*-*-*-*-*-*-*-*-*-*-*-*", - "-*-fixed-*-*-*-*-*-*-*-*-*-*-*-*", - "6x13", - "7x13", - "8x13", - "9x15", - "fixed", - 0 -}; - -// Returns true if the font exists, false otherwise -static bool fontExists(const QString &fontName) -{ - int count; - char **fontNames = XListFonts(QX11Info::display(), (char*)fontName.toLatin1().constData(), 32768, &count); - if (fontNames) XFreeFontNames(fontNames); - - return count != 0; -} - -QString QFont::lastResortFont() const -{ - static QString last; - - // already found - if (! last.isNull()) - return last; - - int i = 0; - const char* f; - - while ((f = tryFonts[i])) { - last = QString::fromLatin1(f); - - if (fontExists(last)) - return last; - - i++; - } - -#if defined(CHECK_NULL) - qFatal("QFontPrivate::lastResortFont: Cannot find any reasonable font"); -#endif - return last; -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 36b0ea9b68..0381286f10 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -43,7 +43,7 @@ #include "qfontdatabase.h" #include "qdebug.h" #include "qalgorithms.h" -#include "qapplication.h" +#include "qguiapplication.h" #include "qvarlengtharray.h" // here or earlier - workaround for VC++6 #include "qthread.h" #include "qmutex.h" @@ -51,7 +51,7 @@ #include "qfontengine_p.h" #ifdef Q_WS_QPA -#include <QtGui/private/qapplication_p.h> +#include <QtGui/private/qguiapplication_p.h> #include <QtGui/qplatformfontdatabase_qpa.h> #include "qabstractfileengine.h" #endif @@ -103,34 +103,34 @@ static int getFontWeight(const QString &weightString) // Test in decreasing order of commonness if (s == QLatin1String("medium") || s == QLatin1String("normal") - || s.compare(QApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0) return QFont::Normal; if (s == QLatin1String("bold") - || s.compare(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0) return QFont::Bold; if (s == QLatin1String("demibold") || s == QLatin1String("demi bold") - || s.compare(QApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0) return QFont::DemiBold; if (s == QLatin1String("black") - || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0) return QFont::Black; if (s == QLatin1String("light")) return QFont::Light; if (s.contains(QLatin1String("bold")) - || s.contains(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) { + || s.contains(QCoreApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) { if (s.contains(QLatin1String("demi")) - || s.compare(QApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0) return (int) QFont::DemiBold; return (int) QFont::Bold; } if (s.contains(QLatin1String("light")) - || s.compare(QApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0) return (int) QFont::Light; if (s.contains(QLatin1String("black")) - || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0) + || s.compare(QCoreApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0) return (int) QFont::Black; return (int) QFont::Normal; @@ -264,7 +264,7 @@ struct QtFontStyle pixelSizes[count].fileName.~QByteArray(); #endif #if defined (Q_WS_QPA) - QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); + QPlatformIntegration *integration = QGuiApplicationPrivate::platformIntegration(); if (integration) { //on shut down there will be some that we don't release. integration->fontDatabase()->releaseHandle(pixelSizes[count].handle); } @@ -297,10 +297,10 @@ QtFontStyle::Key::Key(const QString &styleString) weight = getFontWeight(styleString); if (styleString.contains(QLatin1String("Italic")) - || styleString.contains(QApplication::translate("QFontDatabase", "Italic"))) + || styleString.contains(QCoreApplication::translate("QFontDatabase", "Italic"))) style = QFont::StyleItalic; else if (styleString.contains(QLatin1String("Oblique")) - || styleString.contains(QApplication::translate("QFontDatabase", "Oblique"))) + || styleString.contains(QCoreApplication::translate("QFontDatabase", "Oblique"))) style = QFont::StyleOblique; } @@ -748,7 +748,7 @@ void QFontDatabasePrivate::invalidate() { QFontCache::instance()->clear(); free(); - emit static_cast<QApplication *>(QApplication::instance())->fontDatabaseChanged(); + emit static_cast<QGuiApplication *>(QCoreApplication::instance())->fontDatabaseChanged(); } QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) @@ -1506,21 +1506,21 @@ static QString styleStringHelper(int weight, QFont::Style style) { QString result; if (weight >= QFont::Black) - result = QApplication::translate("QFontDatabase", "Black"); + result = QCoreApplication::translate("QFontDatabase", "Black"); else if (weight >= QFont::Bold) - result = QApplication::translate("QFontDatabase", "Bold"); + result = QCoreApplication::translate("QFontDatabase", "Bold"); else if (weight >= QFont::DemiBold) - result = QApplication::translate("QFontDatabase", "Demi Bold"); + result = QCoreApplication::translate("QFontDatabase", "Demi Bold"); else if (weight < QFont::Normal) - result = QApplication::translate("QFontDatabase", "Light"); + result = QCoreApplication::translate("QFontDatabase", "Light"); if (style == QFont::StyleItalic) - result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Italic"); + result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Italic"); else if (style == QFont::StyleOblique) - result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Oblique"); + result += QLatin1Char(' ') + QCoreApplication::translate("QFontDatabase", "Oblique"); if (result.isEmpty()) - result = QApplication::translate("QFontDatabase", "Normal"); + result = QCoreApplication::translate("QFontDatabase", "Normal"); return result.simplified(); } @@ -2002,7 +2002,7 @@ QFont QFontDatabase::font(const QString &family, const QString &style, QtFontFoundry allStyles(foundryName); QtFontFamily *f = d->family(familyName); - if (!f) return QApplication::font(); + if (!f) return QGuiApplication::font(); for (int j = 0; j < f->count; j++) { QtFontFoundry *foundry = f->foundries[j]; @@ -2016,7 +2016,7 @@ QFont QFontDatabase::font(const QString &family, const QString &style, QtFontStyle *s = bestStyle(&allStyles, styleKey); if (!s) // no styles found? - return QApplication::font(); + return QGuiApplication::font(); QFont fnt(family, pointSize, s->key.weight); fnt.setStyle((QFont::Style)s->key.style); return fnt; @@ -2326,7 +2326,7 @@ QString QFontDatabase::writingSystemName(WritingSystem writingSystem) Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter"); break; } - return QApplication::translate("QFontDatabase", name); + return QCoreApplication::translate("QFontDatabase", name); } diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index ae1130eadc..c9ca5dcb60 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -45,10 +45,6 @@ #include <QtGui/qwindowdefs.h> #include <QtCore/qstring.h> #include <QtGui/qfont.h> -#ifdef QT3_SUPPORT -#include <QtCore/qstringlist.h> -#include <QtCore/qlist.h> -#endif QT_BEGIN_HEADER diff --git a/src/gui/text/qfontdatabase_mac.cpp b/src/gui/text/qfontdatabase_mac.cpp deleted file mode 100644 index 5ba236b5f7..0000000000 --- a/src/gui/text/qfontdatabase_mac.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qt_mac_p.h> -#include "qfontengine_p.h" -#include <qfile.h> -#include <qabstractfileengine.h> -#include <stdlib.h> -#include <qendian.h> -#include <private/qfontengine_coretext_p.h> -#include <private/qfontengine_mac_p.h> - -QT_BEGIN_NAMESPACE - -int qt_mac_pixelsize(const QFontDef &def, int dpi); //qfont_mac.cpp -int qt_mac_pointsize(const QFontDef &def, int dpi); //qfont_mac.cpp - -#ifndef QT_MAC_USE_COCOA -static void initWritingSystems(QtFontFamily *family, ATSFontRef atsFont) -{ - ByteCount length = 0; - if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, 0, 0, &length) != noErr) - return; - QVarLengthArray<uchar> os2Table(length); - if (length < 86 - || ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 0, length, os2Table.data(), &length) != noErr) - return; - - // See also qfontdatabase_win.cpp, offsets taken from OS/2 table in the TrueType spec - quint32 unicodeRange[4] = { - qFromBigEndian<quint32>(os2Table.data() + 42), - qFromBigEndian<quint32>(os2Table.data() + 46), - qFromBigEndian<quint32>(os2Table.data() + 50), - qFromBigEndian<quint32>(os2Table.data() + 54) - }; - quint32 codePageRange[2] = { qFromBigEndian<quint32>(os2Table.data() + 78), qFromBigEndian<quint32>(os2Table.data() + 82) }; - QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); -#if 0 - QCFString name; - ATSFontGetName(atsFont, kATSOptionFlagsDefault, &name); - qDebug() << systems.count() << "writing systems for" << QString(name); -qDebug() << "first char" << hex << unicodeRange[0]; - for (int i = 0; i < systems.count(); ++i) - qDebug() << QFontDatabase::writingSystemName(systems.at(i)); -#endif - for (int i = 0; i < systems.count(); ++i) - family->writingSystems[systems.at(i)] = QtFontFamily::Supported; -} -#endif - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if(!db || db->count) - return; - -#if defined(QT_MAC_USE_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 -if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - QCFType<CTFontCollectionRef> collection = CTFontCollectionCreateFromAvailableFonts(0); - if(!collection) - return; - QCFType<CFArrayRef> fonts = CTFontCollectionCreateMatchingFontDescriptors(collection); - if(!fonts) - return; - QString foundry_name = "CoreText"; - const int numFonts = CFArrayGetCount(fonts); - for(int i = 0; i < numFonts; ++i) { - CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fonts, i); - - QCFString family_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); - QtFontFamily *family = db->family(family_name, true); - for(int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) - family->writingSystems[ws] = QtFontFamily::Supported; - QtFontFoundry *foundry = family->foundry(foundry_name, true); - - QtFontStyle::Key styleKey; - if(QCFType<CFDictionaryRef> styles = (CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute)) { - if(CFNumberRef weight = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontWeightTrait)) { - Q_ASSERT(CFNumberIsFloatType(weight)); - double d; - if(CFNumberGetValue(weight, kCFNumberDoubleType, &d)) { - //qDebug() << "BOLD" << (QString)family_name << d; - styleKey.weight = (d > 0.0) ? QFont::Bold : QFont::Normal; - } - } - if(CFNumberRef italic = (CFNumberRef)CFDictionaryGetValue(styles, kCTFontSlantTrait)) { - Q_ASSERT(CFNumberIsFloatType(italic)); - double d; - if(CFNumberGetValue(italic, kCFNumberDoubleType, &d)) { - //qDebug() << "ITALIC" << (QString)family_name << d; - if (d > 0.0) - styleKey.style = QFont::StyleItalic; - } - } - } - - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = true; - if(QCFType<CFNumberRef> size = (CFNumberRef)CTFontDescriptorCopyAttribute(font, kCTFontSizeAttribute)) { - //qDebug() << "WHEE"; - int pixel_size=0; - if(CFNumberIsFloatType(size)) { - double d; - CFNumberGetValue(size, kCFNumberDoubleType, &d); - pixel_size = d; - } else { - CFNumberGetValue(size, kCFNumberIntType, &pixel_size); - } - //qDebug() << "SIZE" << (QString)family_name << pixel_size; - if(pixel_size) - style->pixelSize(pixel_size, true); - } else { - //qDebug() << "WTF?"; - } - } -} else -#endif - { -#ifndef QT_MAC_USE_COCOA - FMFontIterator it; - if (!FMCreateFontIterator(0, 0, kFMUseGlobalScopeOption, &it)) { - while (true) { - FMFont fmFont; - if (FMGetNextFont(&it, &fmFont) != noErr) - break; - - FMFontFamily fmFamily; - FMFontStyle fmStyle; - QString familyName; - - QtFontStyle::Key styleKey; - - ATSFontRef atsFont = FMGetATSFontRefFromFont(fmFont); - - if (!FMGetFontFamilyInstanceFromFont(fmFont, &fmFamily, &fmStyle)) { - { //sanity check the font, and see if we can use it at all! --Sam - ATSUFontID fontID; - if(ATSUFONDtoFontID(fmFamily, 0, &fontID) != noErr) - continue; - } - - if (fmStyle & ::italic) - styleKey.style = QFont::StyleItalic; - if (fmStyle & ::bold) - styleKey.weight = QFont::Bold; - - ATSFontFamilyRef familyRef = FMGetATSFontFamilyRefFromFontFamily(fmFamily); - QCFString cfFamilyName;; - ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &cfFamilyName); - familyName = cfFamilyName; - } else { - QCFString cfFontName; - ATSFontGetName(atsFont, kATSOptionFlagsDefault, &cfFontName); - familyName = cfFontName; - quint16 macStyle = 0; - { - uchar data[4]; - ByteCount len = 4; - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr) - macStyle = qFromBigEndian<quint16>(data); - } - if (macStyle & 1) - styleKey.weight = QFont::Bold; - if (macStyle & 2) - styleKey.style = QFont::StyleItalic; - } - - QtFontFamily *family = db->family(familyName, true); - QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); - style->pixelSize(0, true); - style->smoothScalable = true; - - initWritingSystems(family, atsFont); - } - FMDisposeFontIterator(&it); - } -#endif - } - -} - -static inline void load(const QString & = QString(), int = -1) -{ - initializeDb(); -} - -static const char *styleHint(const QFontDef &request) -{ - const char *stylehint = 0; - switch (request.styleHint) { - case QFont::SansSerif: - stylehint = "Arial"; - break; - case QFont::Serif: - stylehint = "Times New Roman"; - break; - case QFont::TypeWriter: - stylehint = "Courier New"; - break; - default: - if (request.fixedPitch) - stylehint = "Courier New"; - break; - } - return stylehint; -} - -static inline float weightToFloat(unsigned int weight) -{ - return (weight - 50) / 100.0; -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - // sanity checks - if(!qApp) - qWarning("QFont: Must construct a QApplication before a QFont"); - - Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); - Q_UNUSED(script); - - QFontDef req = d->request; - req.pixelSize = qt_mac_pixelsize(req, d->dpi); - - // set the point size to 0 to get better caching - req.pointSize = 0; - QFontCache::Key key = QFontCache::Key(req, QUnicodeTables::Common, d->screen); - - if(!(d->engineData = QFontCache::instance()->findEngineData(key))) { - d->engineData = new QFontEngineData; - QFontCache::instance()->insertEngineData(key, d->engineData); - } else { - d->engineData->ref.ref(); - } - if(d->engineData->engine) // already loaded - return; - - // set it to the actual pointsize, so QFontInfo will do the right thing - req.pointSize = qRound(qt_mac_pointsize(d->request, d->dpi)); - - QFontEngine *e = QFontCache::instance()->findEngine(key); - if(!e && qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - e = new QTestFontEngine(req.pixelSize); - e->fontDef = req; - } - - if(e) { - e->ref.ref(); - d->engineData->engine = e; - return; // the font info and fontdef should already be filled - } - - //find the font - QStringList family_list = familyList(req); - - const char *stylehint = styleHint(req); - if (stylehint) - family_list << QLatin1String(stylehint); - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - family_list << QApplication::font().defaultFamily(); - -#if defined(QT_MAC_USE_COCOA) - QCFString fontName = NULL, familyName = NULL; -#else - ATSFontFamilyRef familyRef = 0; - ATSFontRef fontRef = 0; -#endif - - QMutexLocker locker(fontDatabaseMutex()); - QFontDatabasePrivate *db = privateDb(); - if (!db->count) - initializeDb(); - for(int i = 0; i < family_list.size(); ++i) { - for (int k = 0; k < db->count; ++k) { - if (db->families[k]->name.compare(family_list.at(i), Qt::CaseInsensitive) == 0) { - QByteArray family_name = db->families[k]->name.toUtf8(); -#if defined(QT_MAC_USE_COCOA) - QCFType<CTFontRef> ctFont = CTFontCreateWithName(QCFString(db->families[k]->name), 12, NULL); - if (ctFont) { - fontName = CTFontCopyFullName(ctFont); - familyName = CTFontCopyFamilyName(ctFont); - goto FamilyFound; - } -#else - familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); - if (familyRef) { - fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); - goto FamilyFound; - } -#endif - } - } - } -FamilyFound: - //fill in the engine's font definition - QFontDef fontDef = d->request; //copy.. - if(fontDef.pointSize < 0) - fontDef.pointSize = qt_mac_pointsize(fontDef, d->dpi); - else - fontDef.pixelSize = qt_mac_pixelsize(fontDef, d->dpi); - -#ifdef QT_MAC_USE_COCOA - fontDef.family = familyName; - QFontEngine *engine = new QCoreTextFontEngineMulti(fontName, fontDef, d->kerning); -#else - QCFString actualName; - if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) - fontDef.family = actualName; - QFontEngine *engine = new QFontEngineMacMulti(familyRef, fontRef, fontDef, d->kerning); -#endif - d->engineData->engine = engine; - engine->ref.ref(); //a ref for the engineData->engine - QFontCache::instance()->insertEngine(key, engine); -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - ATSFontContainerRef handle; - OSStatus e = noErr; - - if(fnt->data.isEmpty()) { -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - extern OSErr qt_mac_create_fsref(const QString &, FSRef *); // qglobal.cpp - FSRef ref; - if(qt_mac_create_fsref(fnt->fileName, &ref) != noErr) - return; - - ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); - } else -#endif - { -#ifndef Q_WS_MAC64 - extern Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &, FSSpec *); // global.cpp - FSSpec spec; - if(qt_mac_create_fsspec(fnt->fileName, &spec) != noErr) - return; - - e = ATSFontActivateFromFileSpecification(&spec, kATSFontContextLocal, kATSFontFormatUnspecified, - 0, kATSOptionFlagsDefault, &handle); -#endif - } - } else { - e = ATSFontActivateFromMemory((void *)fnt->data.constData(), fnt->data.size(), kATSFontContextLocal, - kATSFontFormatUnspecified, 0, kATSOptionFlagsDefault, &handle); - - fnt->data = QByteArray(); - } - - if(e != noErr) - return; - - ItemCount fontCount = 0; - e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, 0, 0, &fontCount); - if(e != noErr) - return; - - QVarLengthArray<ATSFontRef> containedFonts(fontCount); - e = ATSFontFindFromContainer(handle, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount); - if(e != noErr) - return; - - fnt->families.clear(); -#if defined(QT_MAC_USE_COCOA) - // Make sure that the family name set on the font matches what - // kCTFontFamilyNameAttribute returns in initializeDb(). - // So far the best solution seems find the installed font - // using CoreText and get the family name from it. - // (ATSFontFamilyGetName appears to be the correct API, but also - // returns the font display name.) - for(int i = 0; i < containedFonts.size(); ++i) { - QCFString fontPostScriptName; - ATSFontGetPostScriptName(containedFonts[i], kATSOptionFlagsDefault, &fontPostScriptName); - QCFType<CTFontDescriptorRef> font = CTFontDescriptorCreateWithNameAndSize(fontPostScriptName, 14); - QCFString familyName = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute); - fnt->families.append(familyName); - } -#else - for(int i = 0; i < containedFonts.size(); ++i) { - QCFString family; - ATSFontGetName(containedFonts[i], kATSOptionFlagsDefault, &family); - fnt->families.append(family); - } -#endif - - fnt->handle = handle; -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if(handle < 0 || handle >= db->applicationFonts.count()) - return false; - - OSStatus e = ATSFontDeactivate(db->applicationFonts.at(handle).handle, - /*iRefCon=*/0, kATSOptionFlagsDefault); - if(e != noErr) - return false; - - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - - db->invalidate(); - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - for(int i = 0; i < db->applicationFonts.count(); ++i) { - if(!removeApplicationFont(i)) - return false; - } - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return true; -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp index 7bcce56ac8..fcf87f6379 100644 --- a/src/gui/text/qfontdatabase_qpa.cpp +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -45,7 +45,7 @@ #include "qfontengine_qpa_p.h" #include "qplatformdefs.h" -#include <QtGui/private/qapplication_p.h> +#include <QtGui/private/qguiapplication_p.h> #include <QtGui/qplatformfontdatabase_qpa.h> #include <QtCore/qmath.h> @@ -82,7 +82,7 @@ Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &fou static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) { - QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script); + QStringList retList = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script); QFontDatabasePrivate *db = privateDb(); QStringList::iterator i; @@ -109,28 +109,11 @@ static void initializeDb() if (!initialized) { //init by asking for the platformfontdb for the first time :) - QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); initialized = true; } } -#ifndef QT_NO_SETTINGS -// called from qapplication_qws.cpp -void qt_applyFontDatabaseSettings(const QSettings &settings) -{ - initializeDb(); - QFontDatabasePrivate *db = privateDb(); - for (int i = 0; i < db->count; ++i) { - QtFontFamily *family = db->families[i]; - if (settings.contains(family->name)) - family->fallbackFamilies = settings.value(family->name).toStringList(); - } - - if (settings.contains(QLatin1String("Global Fallbacks"))) - db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList(); -} -#endif // QT_NO_SETTINGS - static inline void load(const QString & = QString(), int = -1) { initializeDb(); @@ -155,7 +138,7 @@ QFontEngine *loadSingleEngine(int script, QFontCache::Key key(def,script); QFontEngine *engine = QFontCache::instance()->findEngine(key); if (!engine) { - QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase(); + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle); if (engine) { QFontCache::Key key(def,script); @@ -200,7 +183,7 @@ static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) { QFontDatabasePrivate *db = privateDb(); - fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName); + fnt->families = QGuiApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName); db->reregisterAppFonts = true; } @@ -360,7 +343,7 @@ void QFontDatabase::load(const QFontPrivate *d, int script) family_list = familyList(req); // add the default family - QString defaultFamily = QApplication::font().family(); + QString defaultFamily = QGuiApplication::font().family(); if (! family_list.contains(defaultFamily)) family_list << defaultFamily; diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp deleted file mode 100644 index d076de05d3..0000000000 --- a/src/gui/text/qfontdatabase_qws.cpp +++ /dev/null @@ -1,975 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qdir.h" -#if defined(Q_WS_QWS) -#include "qscreen_qws.h" //so we can check for rotation -#include "qwindowsystem_qws.h" -#endif -#include "qlibraryinfo.h" -#include "qabstractfileengine.h" -#include <QtCore/qsettings.h> -#if !defined(QT_NO_FREETYPE) -#include "qfontengine_ft_p.h" - -#include <ft2build.h> -#include FT_FREETYPE_H - -#endif -#include "qfontengine_qpf_p.h" -#include "private/qfactoryloader_p.h" -#include "private/qcore_unix_p.h" // overrides QT_OPEN -#include "qabstractfontengine_qws.h" -#include "qabstractfontengine_p.h" -#include <qdatetime.h> -#include "qplatformdefs.h" - -// for mmap -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <errno.h> - -#ifdef QT_FONTS_ARE_RESOURCES -#include <qresource.h> -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_LIBRARY -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, - (QFontEngineFactoryInterface_iid, QLatin1String("/fontengines"), Qt::CaseInsensitive)) -#endif - -const quint8 DatabaseVersion = 4; - -// QFontDatabasePrivate::addFont() went into qfontdatabase.cpp - -#ifndef QT_NO_QWS_QPF2 -void QFontDatabasePrivate::addQPF2File(const QByteArray &file) -{ -#ifndef QT_FONTS_ARE_RESOURCES - struct stat st; - if (stat(file.constData(), &st)) - return; - int f = QT_OPEN(file, O_RDONLY, 0); - if (f < 0) - return; - const uchar *data = (const uchar *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, f, 0); - const int dataSize = st.st_size; -#else - QResource res(QLatin1String(file.constData())); - const uchar *data = res.data(); - const int dataSize = res.size(); - //qDebug() << "addQPF2File" << file << data; -#endif - if (data && data != (const uchar *)MAP_FAILED) { - if (QFontEngineQPF::verifyHeader(data, dataSize)) { - QString fontName = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_FontName).toString(); - int pixelSize = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_PixelSize).toInt(); - QVariant weight = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_Weight); - QVariant style = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_Style); - QByteArray writingSystemBits = QFontEngineQPF::extractHeaderField(data, QFontEngineQPF::Tag_WritingSystems).toByteArray(); - - if (!fontName.isEmpty() && pixelSize) { - int fontWeight = 50; - if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt) - fontWeight = weight.toInt(); - - bool italic = static_cast<QFont::Style>(style.toInt()) & QFont::StyleItalic; - - QList<QFontDatabase::WritingSystem> writingSystems; - for (int i = 0; i < writingSystemBits.count(); ++i) { - uchar currentByte = writingSystemBits.at(i); - for (int j = 0; j < 8; ++j) { - if (currentByte & 1) - writingSystems << QFontDatabase::WritingSystem(i * 8 + j); - currentByte >>= 1; - } - } - - addFont(fontName, /*foundry*/ "prerendered", fontWeight, italic, - pixelSize, file, /*fileIndex*/ 0, - /*antialiased*/ true, writingSystems); - } - } else { - qDebug() << "header verification of QPF2 font" << file << "failed. maybe it is corrupt?"; - } -#ifndef QT_FONTS_ARE_RESOURCES - munmap((void *)data, st.st_size); -#endif - } -#ifndef QT_FONTS_ARE_RESOURCES - QT_CLOSE(f); -#endif -} -#endif // QT_NO_QWS_QPF2 - -// QFontDatabasePrivate::addTTFile() went into qfontdatabase.cpp - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt); - -extern QString qws_fontCacheDir(); - -#ifndef QT_FONTS_ARE_RESOURCES -bool QFontDatabasePrivate::loadFromCache(const QString &fontPath) -{ -#ifdef Q_WS_QWS - const bool weAreTheServer = QWSServer::instance(); -#else - const bool weAreTheServer = true; // assume single-process -#endif - - QString fontDirFile = fontPath + QLatin1String("/fontdir"); - - QFile binaryDb(qws_fontCacheDir() + QLatin1String("/fontdb")); - - if (weAreTheServer) { - QDateTime dbTimeStamp = QFileInfo(binaryDb.fileName()).lastModified(); - - QDateTime fontPathTimeStamp = QFileInfo(fontPath).lastModified(); - if (dbTimeStamp < fontPathTimeStamp) - return false; // let the caller create the cache - - if (QFile::exists(fontDirFile)) { - QDateTime fontDirTimeStamp = QFileInfo(fontDirFile).lastModified(); - if (dbTimeStamp < fontDirTimeStamp) - return false; - } - } - - if (!binaryDb.open(QIODevice::ReadOnly)) { - if (weAreTheServer) - return false; // let the caller create the cache - qFatal("QFontDatabase::loadFromCache: Could not open font database cache!"); - } - - QDataStream stream(&binaryDb); - quint8 version = 0; - quint8 dataStreamVersion = 0; - stream >> version >> dataStreamVersion; - if (version != DatabaseVersion || dataStreamVersion != stream.version()) { - if (weAreTheServer) - return false; // let the caller create the cache - qFatal("QFontDatabase::loadFromCache: Wrong version of the font database cache detected. Found %d/%d expected %d/%d", - version, dataStreamVersion, DatabaseVersion, stream.version()); - } - - QString originalFontPath; - stream >> originalFontPath; - if (originalFontPath != fontPath) { - if (weAreTheServer) - return false; // let the caller create the cache - qFatal("QFontDatabase::loadFromCache: Font path doesn't match. Found %s in database, expected %s", qPrintable(originalFontPath), qPrintable(fontPath)); - } - - QString familyname; - stream >> familyname; - //qDebug() << "populating database from" << binaryDb.fileName(); - while (!familyname.isEmpty() && !stream.atEnd()) { - QString foundryname; - int weight; - quint8 italic; - int pixelSize; - QByteArray file; - int fileIndex; - quint8 antialiased; - quint8 writingSystemCount; - - QList<QFontDatabase::WritingSystem> writingSystems; - - stream >> foundryname >> weight >> italic >> pixelSize - >> file >> fileIndex >> antialiased >> writingSystemCount; - - for (quint8 i = 0; i < writingSystemCount; ++i) { - quint8 ws; - stream >> ws; - writingSystems.append(QFontDatabase::WritingSystem(ws)); - } - - addFont(familyname, foundryname.toLatin1().constData(), weight, italic, pixelSize, file, fileIndex, antialiased, - writingSystems); - - stream >> familyname; - } - - stream >> fallbackFamilies; - //qDebug() << "fallback families from cache:" << fallbackFamilies; - return true; -} -#endif // QT_FONTS_ARE_RESOURCES - -/*! - \internal -*/ - -static QString qwsFontPath() -{ - QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QWS_FONTDIR")); - if (fontpath.isEmpty()) { -#ifdef QT_FONTS_ARE_RESOURCES - fontpath = QLatin1String(":/qt/fonts"); -#else -#ifndef QT_NO_SETTINGS - fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath); - fontpath += QLatin1String("/fonts"); -#else - fontpath = QLatin1String("/lib/fonts"); -#endif -#endif //QT_FONTS_ARE_RESOURCES - } - - return fontpath; -} - -#if defined(QFONTDATABASE_DEBUG) && defined(QT_FONTS_ARE_RESOURCES) -class FriendlyResource : public QResource -{ -public: - bool isDir () const { return QResource::isDir(); } - bool isFile () const { return QResource::isFile(); } - QStringList children () const { return QResource::children(); } -}; -#endif -/*! - \internal -*/ -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db || db->count) - return; - - QString fontpath = qwsFontPath(); -#ifndef QT_FONTS_ARE_RESOURCES - QString fontDirFile = fontpath + QLatin1String("/fontdir"); - - if(!QFile::exists(fontpath)) { - qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", - fontpath.toLocal8Bit().constData()); - } - - const bool loaded = db->loadFromCache(fontpath); - - if (db->reregisterAppFonts) { - db->reregisterAppFonts = false; - for (int i = 0; i < db->applicationFonts.count(); ++i) - if (!db->applicationFonts.at(i).families.isEmpty()) { - registerFont(&db->applicationFonts[i]); - } - } - - if (loaded) - return; - - QString dbFileName = qws_fontCacheDir() + QLatin1String("/fontdb"); - - QFile binaryDb(dbFileName + QLatin1String(".tmp")); - binaryDb.open(QIODevice::WriteOnly | QIODevice::Truncate); - db->stream = new QDataStream(&binaryDb); - *db->stream << DatabaseVersion << quint8(db->stream->version()) << fontpath; -// qDebug() << "creating binary database at" << binaryDb.fileName(); - - // Load in font definition file - FILE* fontdef=fopen(fontDirFile.toLocal8Bit().constData(),"r"); - if (fontdef) { - char buf[200]=""; - char name[200]=""; - char render[200]=""; - char file[200]=""; - char isitalic[10]=""; - char flags[10]=""; - do { - fgets(buf,200,fontdef); - if (buf[0] != '#') { - int weight=50; - int size=0; - sscanf(buf,"%s %s %s %s %d %d %s",name,file,render,isitalic,&weight,&size,flags); - QString filename; - if (file[0] != '/') - filename.append(fontpath).append(QLatin1Char('/')); - filename += QLatin1String(file); - bool italic = isitalic[0] == 'y'; - bool smooth = QByteArray(flags).contains('s'); - if (file[0] && QFile::exists(filename)) - db->addFont(QString::fromUtf8(name), /*foundry*/"", weight, italic, size/10, QFile::encodeName(filename), /*fileIndex*/ 0, smooth); - } - } while (!feof(fontdef)); - fclose(fontdef); - } - - - QDir dir(fontpath, QLatin1String("*.qpf")); - for (int i=0; i<int(dir.count()); i++) { - int u0 = dir[i].indexOf(QLatin1Char('_')); - int u1 = dir[i].indexOf(QLatin1Char('_'), u0+1); - int u2 = dir[i].indexOf(QLatin1Char('_'), u1+1); - int u3 = dir[i].indexOf(QLatin1Char('.'), u1+1); - if (u2 < 0) u2 = u3; - - QString familyname = dir[i].left(u0); - int pixelSize = dir[i].mid(u0+1,u1-u0-1).toInt()/10; - bool italic = dir[i].mid(u2-1,1) == QLatin1String("i"); - int weight = dir[i].mid(u1+1,u2-u1-1-(italic?1:0)).toInt(); - - db->addFont(familyname, /*foundry*/ "qt", weight, italic, pixelSize, QFile::encodeName(dir.absoluteFilePath(dir[i])), - /*fileIndex*/ 0, /*antialiased*/ true); - } - -#ifndef QT_NO_FREETYPE - dir.setNameFilters(QStringList() << QLatin1String("*.ttf") - << QLatin1String("*.ttc") << QLatin1String("*.pfa") - << QLatin1String("*.pfb")); - dir.refresh(); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); -// qDebug() << "looking at" << file; - db->addTTFile(file); - } -#endif - -#ifndef QT_NO_QWS_QPF2 - dir.setNameFilters(QStringList() << QLatin1String("*.qpf2")); - dir.refresh(); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); -// qDebug() << "looking at" << file; - db->addQPF2File(file); - } -#endif - -#else //QT_FONTS_ARE_RESOURCES -#ifdef QFONTDATABASE_DEBUG - { - QResource fontdir(fontpath); - FriendlyResource *fr = static_cast<FriendlyResource*>(&fontdir); - qDebug() << "fontdir" << fr->isValid() << fr->isDir() << fr->children(); - - } -#endif -#ifndef QT_NO_QWS_QPF2 - QDir dir(fontpath, QLatin1String("*.qpf2")); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); - //qDebug() << "looking at" << file; - db->addQPF2File(file); - } -#endif -#endif //QT_FONTS_ARE_RESOURCES - - -#ifdef QFONTDATABASE_DEBUG - // print the database - for (int f = 0; f < db->count; f++) { - QtFontFamily *family = db->families[f]; - FD_DEBUG("'%s' %s", qPrintable(family->name), (family->fixedPitch ? "fixed" : "")); -#if 0 - for (int i = 0; i < QFont::LastPrivateScript; ++i) { - FD_DEBUG("\t%s: %s", qPrintable(QFontDatabase::scriptName((QFont::Script) i)), - ((family->scripts[i] & QtFontFamily::Supported) ? "Supported" : - (family->scripts[i] & QtFontFamily::UnSupported) == QtFontFamily::UnSupported ? - "UnSupported" : "Unknown")); - } -#endif - - for (int fd = 0; fd < family->count; fd++) { - QtFontFoundry *foundry = family->foundries[fd]; - FD_DEBUG("\t\t'%s'", qPrintable(foundry->name)); - for (int s = 0; s < foundry->count; s++) { - QtFontStyle *style = foundry->styles[s]; - FD_DEBUG("\t\t\tstyle: style=%d weight=%d\n" - "\t\t\tstretch=%d", - style->key.style, style->key.weight, - style->key.stretch); - if (style->smoothScalable) - FD_DEBUG("\t\t\t\tsmooth scalable"); - else if (style->bitmapScalable) - FD_DEBUG("\t\t\t\tbitmap scalable"); - if (style->pixelSizes) { - FD_DEBUG("\t\t\t\t%d pixel sizes", style->count); - for (int z = 0; z < style->count; ++z) { - QtFontSize *size = style->pixelSizes + z; - FD_DEBUG("\t\t\t\t size %5d", - size->pixelSize); - } - } - } - } - } -#endif // QFONTDATABASE_DEBUG - -#ifndef QT_NO_LIBRARY - QStringList pluginFoundries = loader()->keys(); -// qDebug() << "plugin foundries:" << pluginFoundries; - for (int i = 0; i < pluginFoundries.count(); ++i) { - const QString foundry(pluginFoundries.at(i)); - - QFontEngineFactoryInterface *factory = qobject_cast<QFontEngineFactoryInterface *>(loader()->instance(foundry)); - if (!factory) { - qDebug() << "Could not load plugin for foundry" << foundry; - continue; - } - - QList<QFontEngineInfo> fonts = factory->availableFontEngines(); - for (int i = 0; i < fonts.count(); ++i) { - QFontEngineInfo info = fonts.at(i); - - int weight = info.weight(); - if (weight <= 0) - weight = QFont::Normal; - - db->addFont(info.family(), foundry.toLatin1().constData(), - weight, info.style() != QFont::StyleNormal, - qRound(info.pixelSize()), /*file*/QByteArray(), - /*fileIndex*/0, /*antiAliased*/true, - info.writingSystems()); - } - } -#endif - -#ifndef QT_FONTS_ARE_RESOURCES - // the empty string/familyname signifies the end of the font list. - *db->stream << QString(); -#endif - { - bool coveredWritingSystems[QFontDatabase::WritingSystemsCount] = { 0 }; - - db->fallbackFamilies.clear(); - - for (int i = 0; i < db->count; ++i) { - QtFontFamily *family = db->families[i]; - bool add = false; - if (family->count == 0) - continue; - if (family->bogusWritingSystems) - continue; - for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { - if (coveredWritingSystems[ws]) - continue; - if (family->writingSystems[ws] & QtFontFamily::Supported) { - coveredWritingSystems[ws] = true; - add = true; - } - } - if (add) - db->fallbackFamilies << family->name; - } - //qDebug() << "fallbacks on the server:" << db->fallbackFamilies; -#ifndef QT_FONTS_ARE_RESOURCES - *db->stream << db->fallbackFamilies; -#endif - } -#ifndef QT_FONTS_ARE_RESOURCES - delete db->stream; - db->stream = 0; - QFile::remove(dbFileName); - binaryDb.rename(dbFileName); -#endif -} - -// called from qwindowsystem_qws.cpp -void qt_qws_init_fontdb() -{ - initializeDb(); -} - -#ifndef QT_NO_SETTINGS -// called from qapplication_qws.cpp -void qt_applyFontDatabaseSettings(const QSettings &settings) -{ - initializeDb(); - QFontDatabasePrivate *db = privateDb(); - for (int i = 0; i < db->count; ++i) { - QtFontFamily *family = db->families[i]; - if (settings.contains(family->name)) - family->fallbackFamilies = settings.value(family->name).toStringList(); - } - - if (settings.contains(QLatin1String("Global Fallbacks"))) - db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList(); -} -#endif // QT_NO_SETTINGS - -static inline void load(const QString & = QString(), int = -1) -{ - initializeDb(); -} - -#ifndef QT_NO_FREETYPE - -#if (FREETYPE_MAJOR*10000+FREETYPE_MINOR*100+FREETYPE_PATCH) >= 20105 -#define X_SIZE(face,i) ((face)->available_sizes[i].x_ppem) -#define Y_SIZE(face,i) ((face)->available_sizes[i].y_ppem) -#else -#define X_SIZE(face,i) ((face)->available_sizes[i].width << 6) -#define Y_SIZE(face,i) ((face)->available_sizes[i].height << 6) -#endif - -#endif // QT_NO_FREETYPE - -static -QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp, - const QFontDef &request, - QtFontFamily *family, QtFontFoundry *foundry, - QtFontStyle *style, QtFontSize *size) -{ - Q_UNUSED(script); - Q_UNUSED(fp); -#ifdef QT_NO_FREETYPE - Q_UNUSED(foundry); -#endif -#ifdef QT_NO_QWS_QPF - Q_UNUSED(family); -#endif - Q_ASSERT(size); - - int pixelSize = size->pixelSize; - if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE)) - pixelSize = request.pixelSize; - -#ifndef QT_NO_QWS_QPF2 - if (foundry->name == QLatin1String("prerendered")) { -#ifdef QT_FONTS_ARE_RESOURCES - QResource res(QLatin1String(size->fileName.constData())); - if (res.isValid()) { - QFontEngineQPF *fe = new QFontEngineQPF(request, res.data(), res.size()); - if (fe->isValid()) - return fe; - delete fe; - qDebug() << "fontengine is not valid! " << size->fileName; - } else { - qDebug() << "Resource not valid" << size->fileName; - } -#else - int f = ::open(size->fileName, O_RDONLY, 0); - if (f >= 0) { - QFontEngineQPF *fe = new QFontEngineQPF(request, f); - if (fe->isValid()) - return fe; - delete fe; // will close f - qDebug() << "fontengine is not valid!"; - } -#endif - } else -#endif - if ( foundry->name != QLatin1String("qt") ) { ///#### is this the best way???? - QString file = QFile::decodeName(size->fileName); - - QFontDef def = request; - def.pixelSize = pixelSize; - -#ifdef QT_NO_QWS_SHARE_FONTS - bool shareFonts = false; -#else - static bool dontShareFonts = !qgetenv("QWS_NO_SHARE_FONTS").isEmpty(); - bool shareFonts = !dontShareFonts; -#endif - - QScopedPointer<QFontEngine> engine; - -#ifndef QT_NO_LIBRARY - QFontEngineFactoryInterface *factory = qobject_cast<QFontEngineFactoryInterface *>(loader()->instance(foundry->name)); - if (factory) { - QFontEngineInfo info; - info.setFamily(request.family); - info.setPixelSize(request.pixelSize); - info.setStyle(QFont::Style(request.style)); - info.setWeight(request.weight); - // #### antialiased - - QAbstractFontEngine *customEngine = factory->create(info); - if (customEngine) { - engine.reset(new QProxyFontEngine(customEngine, def)); - - if (shareFonts) { - QVariant hint = customEngine->fontProperty(QAbstractFontEngine::CacheGlyphsHint); - if (hint.isValid()) - shareFonts = hint.toBool(); - else - shareFonts = (pixelSize < 64); - } - } - } -#endif // QT_NO_LIBRARY - if ((engine.isNull() && !file.isEmpty() && QFile::exists(file)) || privateDb()->isApplicationFont(file)) { - QFontEngine::FaceId faceId; - faceId.filename = file.toLocal8Bit(); - faceId.index = size->fileIndex; - -#ifndef QT_NO_FREETYPE - - QScopedPointer<QFontEngineFT> fte(new QFontEngineFT(def)); - bool antialias = style->antialiased && !(request.styleStrategy & QFont::NoAntialias); - if (fte->init(faceId, antialias, - antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono)) { -#ifdef QT_NO_QWS_QPF2 - return fte.take(); -#else - // try to distinguish between bdf and ttf fonts we can pre-render - // and don't try to share outline fonts - shareFonts = shareFonts - && !fte->defaultGlyphs()->outline_drawing - && !fte->getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')).isEmpty(); - engine.reset(fte.take()); -#endif - } -#endif // QT_NO_FREETYPE - } - if (!engine.isNull()) { -#if !defined(QT_NO_QWS_QPF2) && !defined(QT_FONTS_ARE_RESOURCES) - if (shareFonts) { - QScopedPointer<QFontEngineQPF> fe(new QFontEngineQPF(def, -1, engine.data())); - engine.take(); - if (fe->isValid()) - return fe.take(); - qWarning("Initializing QFontEngineQPF failed for %s", qPrintable(file)); - engine.reset(fe->takeRenderingEngine()); - } -#endif - return engine.take(); - } - } else - { -#ifndef QT_NO_QWS_QPF - QString fn = qwsFontPath(); - fn += QLatin1Char('/'); - fn += family->name.toLower() - + QLatin1Char('_') + QString::number(pixelSize*10) - + QLatin1Char('_') + QString::number(style->key.weight) - + (style->key.style == QFont::StyleItalic ? - QLatin1String("i.qpf") : QLatin1String(".qpf")); - //###rotation ### - - QFontEngine *fe = new QFontEngineQPF1(request, fn); - return fe; -#endif // QT_NO_QWS_QPF - } - return new QFontEngineBox(pixelSize); -} - -static -QFontEngine *loadEngine(int script, const QFontPrivate *fp, - const QFontDef &request, - QtFontFamily *family, QtFontFoundry *foundry, - QtFontStyle *style, QtFontSize *size) -{ - QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry, - style, size)); -#ifndef QT_NO_QWS_QPF - if (!engine.isNull() - && script == QUnicodeTables::Common - && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { - - QStringList fallbacks = privateDb()->fallbackFamilies; - - if (family && !family->fallbackFamilies.isEmpty()) - fallbacks = family->fallbackFamilies; - - QFontEngine *fe = new QFontEngineMultiQWS(engine.data(), script, fallbacks); - engine.take(); - engine.reset(fe); - } -#endif - return engine.take(); -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - QFontDatabasePrivate *db = privateDb(); -#ifdef QT_NO_FREETYPE - Q_UNUSED(fnt); -#else - fnt->families = db->addTTFile(QFile::encodeName(fnt->fileName), fnt->data); - db->fallbackFamilies += fnt->families; -#endif - db->reregisterAppFonts = true; -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (handle < 0 || handle >= db->applicationFonts.count()) - return false; - - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - - db->reregisterAppFonts = true; - db->invalidate(); - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (db->applicationFonts.isEmpty()) - return false; - - db->applicationFonts.clear(); - db->invalidate(); - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return true; -} - -/*! - \internal -*/ -QFontEngine * -QFontDatabase::findFont(int script, const QFontPrivate *fp, - const QFontDef &request) -{ - QMutexLocker locker(fontDatabaseMutex()); - - const int force_encoding_id = -1; - - if (!privateDb()->count) - initializeDb(); - - QScopedPointer<QFontEngine> fe; - if (fp) { - if (fp->rawMode) { - fe.reset(loadEngine(script, fp, request, 0, 0, 0, 0)); - - // if we fail to load the rawmode font, use a 12pixel box engine instead - if (fe.isNull()) - fe.reset(new QFontEngineBox(12)); - return fe.take(); - } - - QFontCache::Key key(request, script); - fe.reset(QFontCache::instance()->findEngine(key)); - if (! fe.isNull()) - return fe.take(); - } - - QString family_name, foundry_name; - QtFontStyle::Key styleKey; - styleKey.style = request.style; - styleKey.weight = request.weight; - styleKey.stretch = request.stretch; - char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p'; - - parseFontName(request.family, foundry_name, family_name); - - FM_DEBUG("QFontDatabase::findFont\n" - " request:\n" - " family: %s [%s], script: %d\n" - " weight: %d, style: %d\n" - " stretch: %d\n" - " pixelSize: %g\n" - " pitch: %c", - family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(), - foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(), - script, request.weight, request.style, request.stretch, request.pixelSize, pitch); - - if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) { - fe.reset(new QTestFontEngine(request.pixelSize)); - fe->fontDef = request; - } - - if (fe.isNull()) - { - QtFontDesc desc; - match(script, request, family_name, foundry_name, force_encoding_id, &desc); - - if (desc.family != 0 && desc.foundry != 0 && desc.style != 0 - ) { - FM_DEBUG(" BEST:\n" - " family: %s [%s]\n" - " weight: %d, style: %d\n" - " stretch: %d\n" - " pixelSize: %d\n" - " pitch: %c\n" - " encoding: %d\n", - desc.family->name.toLatin1().constData(), - desc.foundry->name.isEmpty() ? "-- none --" : desc.foundry->name.toLatin1().constData(), - desc.style->key.weight, desc.style->key.style, - desc.style->key.stretch, desc.size ? desc.size->pixelSize : 0xffff, - 'p', 0 - ); - - fe.reset(loadEngine(script, fp, request, desc.family, desc.foundry, desc.style, desc.size - )); - } else { - FM_DEBUG(" NO MATCH FOUND\n"); - } - if (! fe.isNull()) - initFontDef(desc, request, &fe->fontDef); - } - -#ifndef QT_NO_FREETYPE - if (! fe.isNull()) { - if (scriptRequiresOpenType(script) && fe->type() == QFontEngine::Freetype) { - HB_Face hbFace = static_cast<QFontEngineFT *>(fe.data())->harfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { - FM_DEBUG(" OpenType support missing for script\n"); - fe.reset(0); - } - } - } -#endif - - if (! fe.isNull()) { - if (fp) { - QFontDef def = request; - if (def.family.isEmpty()) { - def.family = fp->request.family; - def.family = def.family.left(def.family.indexOf(QLatin1Char(','))); - } - QFontCache::Key key(def, script); - QFontCache::instance()->insertEngine(key, fe.data()); - } - } - - if (fe.isNull()) { - if (!request.family.isEmpty()) - return 0; - - FM_DEBUG("returning box engine"); - - fe.reset(new QFontEngineBox(request.pixelSize)); - - if (fp) { - QFontCache::Key key(request, script); - QFontCache::instance()->insertEngine(key, fe.data()); - } - } - - if (fp && fp->dpi > 0) { - fe->fontDef.pointSize = qreal(double((fe->fontDef.pixelSize * 72) / fp->dpi)); - } else { - fe->fontDef.pointSize = request.pointSize; - } - - return fe.take(); -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - QFontDef req = d->request; - - if (req.pixelSize == -1) - req.pixelSize = qRound(req.pointSize*d->dpi/72); - if (req.pointSize < 0) - req.pointSize = req.pixelSize*72.0/d->dpi; - - if (!d->engineData) { - QFontCache::Key key(req, script); - - // look for the requested font in the engine data cache - d->engineData = QFontCache::instance()->findEngineData(key); - - if (!d->engineData) { - // create a new one - d->engineData = new QFontEngineData; - QT_TRY { - QFontCache::instance()->insertEngineData(key, d->engineData); - } QT_CATCH(...) { - delete d->engineData; - d->engineData = 0; - QT_RETHROW; - } - } else { - d->engineData->ref.ref(); - } - } - - // the cached engineData could have already loaded the engine we want - if (d->engineData->engines[script]) return; - - // double scale = 1.0; // ### TODO: fix the scale calculations - - // list of families to try - QStringList family_list; - - if (!req.family.isEmpty()) { - family_list = req.family.split(QLatin1Char(',')); - - // append the substitute list for each family in family_list - QStringList subs_list; - QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); - for (; it != end; ++it) - subs_list += QFont::substitutes(*it); - family_list += subs_list; - - // append the default fallback font for the specified script - // family_list << ... ; ########### - - // add the default family - QString defaultFamily = QApplication::font().family(); - if (! family_list.contains(defaultFamily)) - family_list << defaultFamily; - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - family_list << QApplication::font().defaultFamily(); - } - - // null family means find the first font matching the specified script - family_list << QString(); - - // load the font - QFontEngine *engine = 0; - QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); - for (; !engine && it != end; ++it) { - req.family = *it; - - engine = QFontDatabase::findFont(script, d, req); - if (engine && (engine->type()==QFontEngine::Box) && !req.family.isEmpty()) - engine = 0; - } - - engine->ref.ref(); - d->engineData->engines[script] = engine; -} - - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp deleted file mode 100644 index 3ab1ac8850..0000000000 --- a/src/gui/text/qfontdatabase_s60.cpp +++ /dev/null @@ -1,1099 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qapplication_p.h> -#include "qdir.h" -#include "qfont_p.h" -#include "qfontengine_s60_p.h" -#include "qabstractfileengine.h" -#include "qdesktopservices.h" -#include "qtemporaryfile.h" -#include "qtextcodec.h" -#include <private/qpixmap_s60_p.h> -#include <private/qt_s60_p.h> -#include "qendian.h" -#include <private/qcore_symbian_p.h> -#ifdef QT_NO_FREETYPE -#include <openfont.h> -#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS -#include <graphics/openfontrasterizer.h> // COpenFontRasterizer has moved to a new header file -#endif // SYMBIAN_ENABLE_SPLIT_HEADERS -#endif // QT_NO_FREETYPE - -QT_BEGIN_NAMESPACE - -QStringList qt_symbian_fontFamiliesOnFontServer() // Also used in qfont_s60.cpp -{ - QStringList result; - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const int numTypeFaces = S60->screenDevice()->NumTypefaces(); - for (int i = 0; i < numTypeFaces; i++) { - TTypefaceSupport typefaceSupport; - S60->screenDevice()->TypefaceSupport(typefaceSupport, i); - const QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); - result.append(familyName); - } - lock.relock(); - return result; -} - -QFileInfoList alternativeFilePaths(const QString &path, const QStringList &nameFilters, - QDir::Filters filters = QDir::NoFilter, QDir::SortFlags sort = QDir::NoSort, - bool uniqueFileNames = true) -{ - QFileInfoList result; - - // Prepare a 'soft to hard' drive list: W:, X: ... A:, Z: - QStringList driveStrings; - foreach (const QFileInfo &drive, QDir::drives()) - driveStrings.append(drive.absolutePath()); - driveStrings.sort(); - const QString zDriveString(QLatin1String("Z:/")); - driveStrings.removeAll(zDriveString); - driveStrings.prepend(zDriveString); - - QStringList uniqueFileNameList; - for (int i = driveStrings.count() - 1; i >= 0; --i) { - const QDir dirOnDrive(driveStrings.at(i) + path); - const QFileInfoList entriesOnDrive = dirOnDrive.entryInfoList(nameFilters, filters, sort); - if (uniqueFileNames) { - foreach(const QFileInfo &entry, entriesOnDrive) { - if (!uniqueFileNameList.contains(entry.fileName())) { - uniqueFileNameList.append(entry.fileName()); - result.append(entry); - } - } - } else { - result.append(entriesOnDrive); - } - } - return result; -} - -#ifdef QT_NO_FREETYPE -class QSymbianFontDatabaseExtrasImplementation : public QSymbianFontDatabaseExtras -{ -public: - QSymbianFontDatabaseExtrasImplementation(); - ~QSymbianFontDatabaseExtrasImplementation(); - - const QSymbianTypeFaceExtras *extras(const QString &typeface, bool bold, bool italic) const; - void removeAppFontData(QFontDatabasePrivate::ApplicationFont *fnt); - static inline bool appFontLimitReached(); - TUid addFontFileToFontStore(const QFileInfo &fontFileInfo); - static void clear(); - - static inline QString tempAppFontFolder(); - static const QString appFontMarkerPrefix; - static QString appFontMarker(); // 'qaf<shortUid[+shortPid]>' - - struct CFontFromFontStoreReleaser { - static inline void cleanup(CFont *font) - { - if (!font) - return; - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(privateDb()->symbianExtras); - dbExtras->m_store->ReleaseFont(font); - } - }; - - struct CFontFromScreenDeviceReleaser { - static inline void cleanup(CFont *font) - { - if (!font) - return; - S60->screenDevice()->ReleaseFont(font); - } - }; - -// m_heap, m_store, m_rasterizer and m_extras are used if Symbian -// does not provide the Font Table API - RHeap* m_heap; - CFontStore *m_store; - COpenFontRasterizer *m_rasterizer; - mutable QList<const QSymbianTypeFaceExtras *> m_extras; - - mutable QSet<QString> m_applicationFontFamilies; -}; - -const QString QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix = - QLatin1String("Q"); - -inline QString QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() -{ - return QDir::toNativeSeparators(QDir::tempPath()) + QLatin1Char('\\'); -} - -QString QSymbianFontDatabaseExtrasImplementation::appFontMarker() -{ - static QString result; - if (result.isEmpty()) { - quint16 id = 0; - if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - // We are allowed to load app fonts even from previous, crashed runs - // of this application, since we can access the font tables. - const quint32 uid = RProcess().Type().MostDerived().iUid; - id = static_cast<quint16>(uid + (uid >> 16)); - } else { - // If no font table Api is available, we must not even load a font - // from a previous (crashed) run of this application. Reason: we - // won't get the font tables, they are not in the CFontStore. - // So, we use the pid, for more uniqueness. - id = static_cast<quint16>(RProcess().Id().Id()); - } - result = appFontMarkerPrefix + QString::fromLatin1("%1").arg(id & 0x7fff, 3, 32, QLatin1Char('0')); - Q_ASSERT(appFontMarkerPrefix.length() == 1 && result.length() == 4); - } - return result; -} - -static inline bool qt_symbian_fontNameHasAppFontMarker(const QString &fontName) -{ - const int idLength = 3; // Keep in sync with id length in appFontMarker(). - const QString &prefix = QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix; - if (fontName.length() < prefix.length() + idLength - || fontName.mid(fontName.length() - idLength - prefix.length(), prefix.length()) != prefix) - return false; - // Testing if the the id is base32 data - for (int i = fontName.length() - idLength; i < fontName.length(); ++i) { - const QChar &c = fontName.at(i); - if (!(c >= QLatin1Char('0') && c <= QLatin1Char('9') - || c >= QLatin1Char('a') && c <= QLatin1Char('v'))) - return false; - } - return true; -} - -// If fontName is an application font of this app, prepend the app font marker -QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName) -{ - QFontDatabasePrivate *db = privateDb(); - Q_ASSERT(db); - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - return dbExtras->m_applicationFontFamilies.contains(fontName) ? - fontName + QSymbianFontDatabaseExtrasImplementation::appFontMarker() - : fontName; -} - -static inline QString qt_symbian_appFontNameWithoutMarker(const QString &markedFontName) -{ - return markedFontName.left(markedFontName.length() - - QSymbianFontDatabaseExtrasImplementation::appFontMarker().length()); -} - -QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation() -{ - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - QStringList filters; - filters.append(QLatin1String("*.ttf")); - filters.append(QLatin1String("*.ccc")); - filters.append(QLatin1String("*.ltt")); - const QFileInfoList fontFiles = alternativeFilePaths(QLatin1String("resource\\Fonts"), filters); - - const TInt heapMinLength = 0x1000; - const TInt heapMaxLength = qMax(0x20000 * fontFiles.count(), heapMinLength); - m_heap = User::ChunkHeap(NULL, heapMinLength, heapMaxLength); - QT_TRAP_THROWING( - m_store = CFontStore::NewL(m_heap); - m_rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); - CleanupStack::PushL(m_rasterizer); - m_store->InstallRasterizerL(m_rasterizer); - CleanupStack::Pop(m_rasterizer);); - - foreach (const QFileInfo &fontFileInfo, fontFiles) - addFontFileToFontStore(fontFileInfo); - } -} - -void QSymbianFontDatabaseExtrasImplementation::clear() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db) - return; - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - if (!dbExtras) - return; // initializeDb() has never been called - QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData(); - if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - qDeleteAll(extrasHash); - } else { - typedef QList<const QSymbianTypeFaceExtras *>::iterator iterator; - for (iterator p = dbExtras->m_extras.begin(); p != dbExtras->m_extras.end(); ++p) { - dbExtras->m_store->ReleaseFont((*p)->fontOwner()); - delete *p; - } - dbExtras->m_extras.clear(); - } - extrasHash.clear(); -} - -void qt_cleanup_symbianFontDatabase() -{ - static bool cleanupDone = false; - if (cleanupDone) - return; - cleanupDone = true; - - QFontDatabasePrivate *db = privateDb(); - if (!db) - return; - - QSymbianFontDatabaseExtrasImplementation::clear(); - - if (!db->applicationFonts.isEmpty()) { - QFontDatabase::removeAllApplicationFonts(); - // We remove the left over temporary font files of Qt application. - // Active fonts are undeletable since the font server holds a handle - // on them, so we do not need to worry to delete other running - // applications' fonts. - const QDir dir(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()); - const QStringList filter( - QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix + QLatin1String("*.ttf")); - foreach (const QFileInfo &ttfFile, dir.entryInfoList(filter)) - QFile(ttfFile.absoluteFilePath()).remove(); - db->applicationFonts.clear(); - } -} - -QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation() -{ - qt_cleanup_symbianFontDatabase(); - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - delete m_store; - m_heap->Close(); - } -} - -#ifndef FNTSTORE_H_INLINES_SUPPORT_FMM -/* - Workaround: fntstore.h has an inlined function 'COpenFont* CBitmapFont::OpenFont()' - that returns a private data member. The header will change between SDKs. But Qt has - to build on any SDK version and run on other versions of Symbian OS. - This function performs the needed pointer arithmetic to get the right COpenFont* -*/ -COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont) -{ - const TInt offsetIOpenFont = 92; // '_FOFF(CBitmapFont, iOpenFont)' ..if iOpenFont weren't private - const TUint valueIOpenFont = *(TUint*)PtrAdd(aBitmapFont, offsetIOpenFont); - return (valueIOpenFont & 1) ? - (COpenFont*)PtrAdd(aBitmapFont, valueIOpenFont & ~1) : // New behavior: iOpenFont is offset - (COpenFont*)valueIOpenFont; // Old behavior: iOpenFont is pointer -} -#endif // FNTSTORE_H_INLINES_SUPPORT_FMM - -const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface, - bool bold, bool italic) const -{ - QSymbianTypeFaceExtrasHash &extrasHash = S60->fontData(); - if (extrasHash.isEmpty() && QThread::currentThread() != QApplication::instance()->thread()) - S60->addThreadLocalReleaseFunc(clear); - const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface); - const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic)); - if (!extrasHash.contains(searchKey)) { - TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1); - if (bold) - searchSpec.iFontStyle.SetStrokeWeight(EStrokeWeightBold); - if (italic) - searchSpec.iFontStyle.SetPosture(EPostureItalic); - - CFont* font = NULL; - if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { - const TInt err = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(font, searchSpec); - Q_ASSERT(err == KErrNone && font); - QScopedPointer<CFont, CFontFromScreenDeviceReleaser> sFont(font); - QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font); - sFont.take(); - extrasHash.insert(searchKey, extras); - } else { - const TInt err = m_store->GetNearestFontToDesignHeightInPixels(font, searchSpec); - Q_ASSERT(err == KErrNone && font); - const CBitmapFont *bitmapFont = static_cast<CBitmapFont*>(font); - COpenFont *openFont = -#ifdef FNTSTORE_H_INLINES_SUPPORT_FMM - bitmapFont->OpenFont(); -#else // FNTSTORE_H_INLINES_SUPPORT_FMM - OpenFontFromBitmapFont(bitmapFont); -#endif // FNTSTORE_H_INLINES_SUPPORT_FMM - const TOpenFontFaceAttrib* const attrib = openFont->FaceAttrib(); - const QString foundKey = - QString((const QChar*)attrib->FullName().Ptr(), attrib->FullName().Length()); - if (!extrasHash.contains(foundKey)) { - QScopedPointer<CFont, CFontFromFontStoreReleaser> sFont(font); - QSymbianTypeFaceExtras *extras = new QSymbianTypeFaceExtras(font, openFont); - sFont.take(); - m_extras.append(extras); - extrasHash.insert(searchKey, extras); - extrasHash.insert(foundKey, extras); - } else { - m_store->ReleaseFont(font); - extrasHash.insert(searchKey, extrasHash.value(foundKey)); - } - } - } - return extrasHash.value(searchKey); -} - -void QSymbianFontDatabaseExtrasImplementation::removeAppFontData( - QFontDatabasePrivate::ApplicationFont *fnt) -{ - clear(); - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable() - && fnt->fontStoreFontFileUid.iUid != 0) - m_store->RemoveFile(fnt->fontStoreFontFileUid); - if (!fnt->families.isEmpty()) - m_applicationFontFamilies.remove(fnt->families.first()); - if (fnt->screenDeviceFontFileId != 0) - S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); - QFile::remove(fnt->temporaryFileName); - *fnt = QFontDatabasePrivate::ApplicationFont(); -} - -bool QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db) - return false; - const int maxAppFonts = 5; - int registeredAppFonts = 0; - foreach (const QFontDatabasePrivate::ApplicationFont &appFont, db->applicationFonts) - if (!appFont.families.isEmpty() && ++registeredAppFonts == maxAppFonts) - return true; - return false; -} - -TUid QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo) -{ - Q_ASSERT(!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()); - const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath()); - const TPtrC fontFilePtr(qt_QString2TPtrC(fontFile)); - TUid fontUid = {0}; - TRAP_IGNORE(fontUid = m_store->AddFileL(fontFilePtr)); - return fontUid; -} - -#else // QT_NO_FREETYPE -class QFontEngineFTS60 : public QFontEngineFT -{ -public: - QFontEngineFTS60(const QFontDef &fd); -}; - -QFontEngineFTS60::QFontEngineFTS60(const QFontDef &fd) - : QFontEngineFT(fd) -{ - default_hint_style = HintFull; -} -#endif // QT_NO_FREETYPE - -/* - QFontEngineS60::pixelsToPoints, QFontEngineS60::pointsToPixels, QFontEngineMultiS60::QFontEngineMultiS60 - and QFontEngineMultiS60::QFontEngineMultiS60 should be in qfontengine_s60.cpp. But since also the - Freetype based font rendering need them, they are here. -*/ -qreal QFontEngineS60::pixelsToPoints(qreal pixels, Qt::Orientation orientation) -{ - CWsScreenDevice* device = S60->screenDevice(); - return (orientation == Qt::Horizontal? - device->HorizontalPixelsToTwips(pixels) - :device->VerticalPixelsToTwips(pixels)) / KTwipsPerPoint; -} - -qreal QFontEngineS60::pointsToPixels(qreal points, Qt::Orientation orientation) -{ - CWsScreenDevice* device = S60->screenDevice(); - const int twips = points * KTwipsPerPoint; - return orientation == Qt::Horizontal? - device->HorizontalTwipsToPixels(twips) - :device->VerticalTwipsToPixels(twips); -} - -QFontEngineMultiS60::QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies) - : QFontEngineMulti(fallbackFamilies.size() + 1) - , m_script(script) - , m_fallbackFamilies(fallbackFamilies) -{ - engines[0] = first; - first->ref.ref(); - fontDef = engines[0]->fontDef; -} - -void QFontEngineMultiS60::loadEngine(int at) -{ - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - QFontDef request = fontDef; - request.styleStrategy |= QFont::NoFontMerging; - request.family = m_fallbackFamilies.at(at-1); - engines[at] = QFontDatabase::findFont(m_script, - /*fontprivate*/0, - request); - Q_ASSERT(engines[at]); -} - -#ifdef QT_NO_FREETYPE -static bool registerScreenDeviceFont(int screenDeviceFontIndex, - const QSymbianFontDatabaseExtrasImplementation *dbExtras) -{ - TTypefaceSupport typefaceSupport; - S60->screenDevice()->TypefaceSupport(typefaceSupport, screenDeviceFontIndex); - - QString familyName((const QChar*)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); - if (qt_symbian_fontNameHasAppFontMarker(familyName)) { - const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); - if (familyName.endsWith(marker)) { - familyName = qt_symbian_appFontNameWithoutMarker(familyName); - dbExtras->m_applicationFontFamilies.insert(familyName); - } else { - return false; // This was somebody else's application font. Skip it. - } - } - - CFont *font; // We have to get a font instance in order to know all the details - TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); - if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) - return false; - QScopedPointer<CFont, QSymbianFontDatabaseExtrasImplementation::CFontFromScreenDeviceReleaser> sFont(font); - if (font->TypeUid() != KCFbsFontUid) - return false; - TOpenFontFaceAttrib faceAttrib; - const CFbsFont *cfbsFont = static_cast<const CFbsFont *>(font); - cfbsFont->GetFaceAttrib(faceAttrib); - - QtFontStyle::Key styleKey; - styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal; - styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal; - - QtFontFamily *family = privateDb()->family(familyName, true); - family->fixedPitch = faceAttrib.IsMonoWidth(); - QtFontFoundry *foundry = family->foundry(QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = typefaceSupport.iIsScalable; - style->pixelSize(0, true); - - const QSymbianTypeFaceExtras *typeFaceExtras = - dbExtras->extras(familyName, faceAttrib.IsBold(), faceAttrib.IsItalic()); - const QByteArray os2Table = typeFaceExtras->getSfntTable(MAKE_TAG('O', 'S', '/', '2')); - const unsigned char* data = reinterpret_cast<const unsigned char*>(os2Table.constData()); - const unsigned char* ulUnicodeRange = data + 42; - quint32 unicodeRange[4] = { - qFromBigEndian<quint32>(ulUnicodeRange), - qFromBigEndian<quint32>(ulUnicodeRange + 4), - qFromBigEndian<quint32>(ulUnicodeRange + 8), - qFromBigEndian<quint32>(ulUnicodeRange + 12) - }; - const unsigned char* ulCodePageRange = data + 78; - quint32 codePageRange[2] = { - qFromBigEndian<quint32>(ulCodePageRange), - qFromBigEndian<quint32>(ulCodePageRange + 4) - }; - const QList<QFontDatabase::WritingSystem> writingSystems = - qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); - foreach (const QFontDatabase::WritingSystem system, writingSystems) - family->writingSystems[system] = QtFontFamily::Supported; - return true; -} -#endif - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if(!db || db->count) - return; - -#ifdef QT_NO_FREETYPE - if (!db->symbianExtras) - db->symbianExtras = new QSymbianFontDatabaseExtrasImplementation; - - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - const int numTypeFaces = S60->screenDevice()->NumTypefaces(); - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - for (int i = 0; i < numTypeFaces; i++) - registerScreenDeviceFont(i, dbExtras); - - // We have to clear/release all CFonts, here, in case one of the fonts is - // an application font of another running Qt app. Otherwise the other Qt app - // cannot remove it's application font, anymore -> "Zombie Font". - QSymbianFontDatabaseExtrasImplementation::clear(); - - lock.relock(); - -#else // QT_NO_FREETYPE - QDir dir(QDesktopServices::storageLocation(QDesktopServices::FontsLocation)); - dir.setNameFilters(QStringList() << QLatin1String("*.ttf") - << QLatin1String("*.ttc") << QLatin1String("*.pfa") - << QLatin1String("*.pfb")); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); - db->addTTFile(file); - } -#endif // QT_NO_FREETYPE -} - -static inline void load(const QString &family = QString(), int script = -1) -{ - Q_UNUSED(family) - Q_UNUSED(script) - initializeDb(); -} - -struct OffsetTable { - quint32 sfntVersion; - quint16 numTables, searchRange, entrySelector, rangeShift; -}; - -struct TableRecord { - quint32 tag, checkSum, offset, length; -}; - -struct NameTableHead { - quint16 format, count, stringOffset; -}; - -struct NameRecord { - quint16 platformID, encodingID, languageID, nameID, length, offset; -}; - -static quint32 ttfCalcChecksum(const char *data, quint32 bytesCount) -{ - quint32 result = 0; - const quint32 *ptr = reinterpret_cast<const quint32*>(data); - const quint32 *endPtr = - ptr + (bytesCount + sizeof(quint32) - 1) / sizeof(quint32); - while (ptr < endPtr) { - const quint32 unit32Value = *ptr++; - result += qFromBigEndian(unit32Value); - } - return result; -} - -static inline quint32 toDWordBoundary(quint32 value) -{ - return (value + 3) & ~3; -} - -static inline quint32 dWordPadding(quint32 value) -{ - return (4 - (value & 3)) & 3; -} - -static inline bool ttfMarkNameTable(QByteArray &table, const QString &marker) -{ - const quint32 tableLength = static_cast<quint32>(table.size()); - - if (tableLength > 50000 // hard limit - || tableLength < sizeof(NameTableHead)) // corrupt name table - return false; - - const NameTableHead *head = reinterpret_cast<const NameTableHead*>(table.constData()); - const quint16 count = qFromBigEndian(head->count); - const quint16 stringOffset = qFromBigEndian(head->stringOffset); - if (count > 200 // hard limit - || stringOffset >= tableLength // corrupt name table - || sizeof(NameTableHead) + count * sizeof(NameRecord) >= tableLength) // corrupt name table - return false; - - QTextEncoder encoder(QTextCodec::codecForName("UTF-16BE"), QTextCodec::IgnoreHeader); - const QByteArray markerUtf16BE = encoder.fromUnicode(marker); - const QByteArray markerAscii = marker.toAscii(); - - QByteArray markedTable; - markedTable.reserve(tableLength + marker.length() * 20); // Original size plus some extra - markedTable.append(table, stringOffset); - QByteArray markedStrings; - quint32 stringDataCount = stringOffset; - for (quint16 i = 0; i < count; ++i) { - const quint32 nameRecordOffset = sizeof(NameTableHead) + sizeof(NameRecord) * i; - NameRecord *nameRecord = - reinterpret_cast<NameRecord*>(markedTable.data() + nameRecordOffset); - const quint16 nameID = qFromBigEndian(nameRecord->nameID); - const quint16 platformID = qFromBigEndian(nameRecord->platformID); - const quint16 encodingID = qFromBigEndian(nameRecord->encodingID); - const quint16 offset = qFromBigEndian(nameRecord->offset); - const quint16 length = qFromBigEndian(nameRecord->length); - stringDataCount += length; - if (stringDataCount > 80000 // hard limit. String data may be > name table size. Multiple records can reference the same string. - || static_cast<quint32>(stringOffset + offset + length) > tableLength) // String outside bounds - return false; - const bool needsMarker = - nameID == 1 || nameID == 3 || nameID == 4 || nameID == 16 || nameID == 21; - const bool isUnicode = - platformID == 0 || platformID == 3 && encodingID == 1; - const QByteArray originalString = - QByteArray::fromRawData(table.constData() + stringOffset + offset, length); - QByteArray markedString; - if (needsMarker) { - const int maxBytesLength = (KMaxTypefaceNameLength - marker.length()) * (isUnicode ? 2 : 1); - markedString = originalString.left(maxBytesLength) + (isUnicode ? markerUtf16BE : markerAscii); - } else { - markedString = originalString; - } - nameRecord->offset = qToBigEndian(static_cast<quint16>(markedStrings.length())); - nameRecord->length = qToBigEndian(static_cast<quint16>(markedString.length())); - markedStrings.append(markedString); - } - markedTable.append(markedStrings); - table = markedTable; - return true; -} - -const quint32 ttfMaxFileSize = 3500000; - -static inline bool ttfMarkAppFont(QByteArray &ttf, const QString &marker) -{ - const quint32 ttfChecksumNumber = 0xb1b0afba; - const quint32 alignment = 4; - const quint32 ttfLength = static_cast<quint32>(ttf.size()); - if (ttfLength > ttfMaxFileSize // hard limit - || ttfLength % alignment != 0 // ttf sizes are always factors of 4 - || ttfLength <= sizeof(OffsetTable) // ttf too short - || ttfCalcChecksum(ttf.constData(), ttf.size()) != ttfChecksumNumber) // ttf checksum is invalid - return false; - - const OffsetTable *offsetTable = reinterpret_cast<const OffsetTable*>(ttf.constData()); - const quint16 numTables = qFromBigEndian(offsetTable->numTables); - const quint32 recordsLength = - toDWordBoundary(sizeof(OffsetTable) + numTables * sizeof(TableRecord)); - if (numTables > 30 // hard limit - || recordsLength + numTables * alignment > ttfLength) // Corrupt ttf. Tables would not fit, even if empty. - return false; - - QByteArray markedTtf; - markedTtf.reserve(ttfLength + marker.length() * 20); // Original size plus some extra - markedTtf.append(ttf.constData(), recordsLength); - - const quint32 ttfCheckSumAdjustmentOffset = 8; // Offset from the start of 'head' - int indexOfHeadTable = -1; - quint32 ttfDataSize = recordsLength; - typedef QPair<quint32, quint32> Range; - QList<Range> memoryRanges; - memoryRanges.reserve(numTables); - for (int i = 0; i < numTables; ++i) { - TableRecord *tableRecord = - reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); - const quint32 offset = qFromBigEndian(tableRecord->offset); - const quint32 length = qFromBigEndian(tableRecord->length); - const quint32 lengthAligned = toDWordBoundary(length); - ttfDataSize += lengthAligned; - if (offset < recordsLength // must not intersect ttf header/records - || offset % alignment != 0 // must be aligned - || offset > ttfLength - alignment // table out of bounds - || offset + lengthAligned > ttfLength // table out of bounds - || ttfDataSize > ttfLength) // tables would not fit into the ttf - return false; - - foreach (const Range &range, memoryRanges) - if (offset < range.first + range.second && offset + lengthAligned > range.first) - return false; // Overlaps with another table - memoryRanges.append(Range(offset, lengthAligned)); - - quint32 checkSum = qFromBigEndian(tableRecord->checkSum); - if (tableRecord->tag == qToBigEndian(static_cast<quint32>('head'))) { - if (length < ttfCheckSumAdjustmentOffset + sizeof(quint32)) - return false; // Invalid 'head' table - const quint32 *checkSumAdjustmentTag = - reinterpret_cast<const quint32*>(ttf.constData() + offset + ttfCheckSumAdjustmentOffset); - const quint32 checkSumAdjustment = qFromBigEndian(*checkSumAdjustmentTag); - checkSum += checkSumAdjustment; - indexOfHeadTable = i; // For the ttf checksum re-calculation, later - } - if (checkSum != ttfCalcChecksum(ttf.constData() + offset, length)) - return false; // Table checksum is invalid - - bool updateTableChecksum = false; - QByteArray table; - if (tableRecord->tag == qToBigEndian(static_cast<quint32>('name'))) { - table = QByteArray(ttf.constData() + offset, length); - if (!ttfMarkNameTable(table, marker)) - return false; // Name table was not markable. - updateTableChecksum = true; - } else { - table = QByteArray::fromRawData(ttf.constData() + offset, length); - } - - tableRecord->offset = qToBigEndian(markedTtf.size()); - tableRecord->length = qToBigEndian(table.size()); - markedTtf.append(table); - markedTtf.append(QByteArray(dWordPadding(table.size()), 0)); // 0-padding - if (updateTableChecksum) { - TableRecord *tableRecord = // Need to recalculate, since markedTtf changed - reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); - const quint32 offset = qFromBigEndian(tableRecord->offset); - const quint32 length = qFromBigEndian(tableRecord->length); - tableRecord->checkSum = qToBigEndian(ttfCalcChecksum(markedTtf.constData() + offset, length)); - } - } - if (indexOfHeadTable == -1 // 'head' table is mandatory - || ttfDataSize != ttfLength) // We do not allow ttf data "holes". Neither does Symbian. - return false; - TableRecord *headRecord = - reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + indexOfHeadTable * sizeof(TableRecord)); - quint32 *checkSumAdjustmentTag = - reinterpret_cast<quint32*>(markedTtf.data() + qFromBigEndian(headRecord->offset) + ttfCheckSumAdjustmentOffset); - *checkSumAdjustmentTag = 0; - const quint32 ttfChecksum = ttfCalcChecksum(markedTtf.constData(), markedTtf.count()); - *checkSumAdjustmentTag = qToBigEndian(ttfChecksumNumber - ttfChecksum); - ttf = markedTtf; - return true; -} - -static inline bool ttfCanSymbianLoadFont(const QByteArray &data, const QString &fileName) -{ - bool result = false; - QString ttfFileName; - QFile tempFileGuard; - QFileInfo info(fileName); - if (!data.isEmpty()) { - QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() - + QSymbianFontDatabaseExtrasImplementation::appFontMarker() - + QLatin1String("XXXXXX.ttf")); - if (!tempfile.open() || tempfile.write(data) == -1) - return false; - ttfFileName = QDir::toNativeSeparators(QFileInfo(tempfile).canonicalFilePath()); - tempfile.setAutoRemove(false); - tempfile.close(); - tempFileGuard.setFileName(ttfFileName); - if (!tempFileGuard.open(QIODevice::ReadOnly)) - return false; - } else if (info.isFile()) { - ttfFileName = QDir::toNativeSeparators(info.canonicalFilePath()); - } else { - return false; - } - - CFontStore *store = 0; - RHeap* heap = User::ChunkHeap(NULL, 0x1000, 0x20000); - if (heap) { - QT_TRAP_THROWING( - CleanupClosePushL(*heap); - store = CFontStore::NewL(heap); - CleanupStack::PushL(store); - COpenFontRasterizer *rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); - CleanupStack::PushL(rasterizer); - store->InstallRasterizerL(rasterizer); - CleanupStack::Pop(rasterizer); - TUid fontUid = {-1}; - TRAP_IGNORE(fontUid = store->AddFileL(qt_QString2TPtrC(ttfFileName))); - if (fontUid.iUid != -1) - result = true; - CleanupStack::PopAndDestroy(2, heap); // heap, store - ); - } - - if (tempFileGuard.isOpen()) - tempFileGuard.remove(); - - return result; -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - if (QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() - || fnt->data.size() > ttfMaxFileSize // hard limit - || fnt->data.isEmpty() && (!fnt->fileName.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive) // Only buffer or .ttf - || QFileInfo(fnt->fileName).size() > ttfMaxFileSize)) // hard limit - return; - -// Using ttfCanSymbianLoadFont() causes crashes on app destruction (Symbian^3|PR1 and lower). -// Therefore, not using it for now, but eventually in a later version. -// if (!ttfCanSymbianLoadFont(fnt->data, fnt->fileName)) -// return; - - QFontDatabasePrivate *db = privateDb(); - if (!db) - return; - - if (!db->count) - initializeDb(); - - QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - if (!dbExtras) - return; - - const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); - - // The QTemporaryFile object being used in the following section must be - // destructed before letting Symbian load the TTF file. Symbian would not - // load it otherwise, because QTemporaryFile will still keep some handle - // on it. The scope is used to reduce the life time of the QTemporaryFile. - // In order to prevent other processes from modifying the file between the - // moment where the QTemporaryFile is destructed and the file is loaded by - // Symbian, we have a QFile "tempFileGuard" outside the scope which opens - // the file in ReadOnly mode while the QTemporaryFile is still alive. - QFile tempFileGuard; - { - QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() - + marker + QLatin1String("XXXXXX.ttf")); - if (!tempfile.open()) - return; - const QString tempFileName = QFileInfo(tempfile).canonicalFilePath(); - if (fnt->data.isEmpty()) { - QFile sourceFile(fnt->fileName); - if (!sourceFile.open(QIODevice::ReadOnly)) - return; - fnt->data = sourceFile.readAll(); - } - if (!ttfMarkAppFont(fnt->data, marker) || tempfile.write(fnt->data) == -1) - return; - tempfile.setAutoRemove(false); - tempfile.close(); // Tempfile still keeps a file handle, forbidding write access - fnt->data.clear(); // The TTF data was marked and saved. Not needed in memory, anymore. - tempFileGuard.setFileName(tempFileName); - if (!tempFileGuard.open(QIODevice::ReadOnly)) - return; - fnt->temporaryFileName = tempFileName; - } - - const QString fullFileName = QDir::toNativeSeparators(fnt->temporaryFileName); - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - const QStringList fontsOnServerBefore = qt_symbian_fontFamiliesOnFontServer(); - const TInt err = - S60->screenDevice()->AddFile(qt_QString2TPtrC(fullFileName), fnt->screenDeviceFontFileId); - tempFileGuard.close(); // Did its job - const QStringList fontsOnServerAfter = qt_symbian_fontFamiliesOnFontServer(); - if (err == KErrNone && fontsOnServerBefore.count() < fontsOnServerAfter.count()) { // Added to screen device? - int fontOnServerIndex = fontsOnServerAfter.count() - 1; - for (int i = 0; i < fontsOnServerBefore.count(); i++) { - if (fontsOnServerBefore.at(i) != fontsOnServerAfter.at(i)) { - fontOnServerIndex = i; - break; - } - } - - // Must remove all font engines with their CFonts, first. - QFontCache::instance()->clear(); - db->free(); - QSymbianFontDatabaseExtrasImplementation::clear(); - - if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) - fnt->fontStoreFontFileUid = dbExtras->addFontFileToFontStore(QFileInfo(fullFileName)); - - const QString &appFontName = fontsOnServerAfter.at(fontOnServerIndex); - fnt->families.append(qt_symbian_appFontNameWithoutMarker(appFontName)); - if (!qt_symbian_fontNameHasAppFontMarker(appFontName) - || !registerScreenDeviceFont(fontOnServerIndex, dbExtras)) - dbExtras->removeAppFontData(fnt); - } else { - if (fnt->screenDeviceFontFileId > 0) - S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); // May still have the file open! - QFile::remove(fnt->temporaryFileName); - *fnt = QFontDatabasePrivate::ApplicationFont(); - } - lock.relock(); -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (!db || handle < 0 || handle >= db->applicationFonts.count()) - return false; - QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - if (!dbExtras) - return false; - - QFontDatabasePrivate::ApplicationFont *fnt = &db->applicationFonts[handle]; - if (fnt->families.isEmpty()) - return true; // Nothing to remove. Return peacefully. - - // Must remove all font engines with their CFonts, first - QFontCache::instance()->clear(); - db->free(); - dbExtras->removeAppFontData(fnt); - - db->invalidate(); // This will just emit 'fontDatabaseChanged()' - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - const int applicationFontsCount = privateDb()->applicationFonts.count(); - for (int i = 0; i < applicationFontsCount; ++i) - if (!removeApplicationFont(i)) - return false; - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return QSymbianTypeFaceExtras::symbianFontTableApiAvailable(); -} - -static -QFontDef cleanedFontDef(const QFontDef &req) -{ - QFontDef result = req; - if (result.pixelSize <= 0) { - result.pixelSize = QFontEngineS60::pointsToPixels(qMax(qreal(1.0), result.pointSize)); - result.pointSize = 0; - } - return result; -} - -QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *d, const QFontDef &req) -{ - const QFontCache::Key key(cleanedFontDef(req), script); - - if (!privateDb()->count) - initializeDb(); - - QFontEngine *fe = QFontCache::instance()->findEngine(key); - if (!fe) { - // Making sure that fe->fontDef.family will be an existing font. - initializeDb(); - QFontDatabasePrivate *db = privateDb(); - QtFontDesc desc; - QList<int> blacklistedFamilies; - match(script, key.def, key.def.family, QString(), -1, &desc, blacklistedFamilies); - if (!desc.family) // falling back to application font - desc.family = db->family(QApplication::font().defaultFamily()); - Q_ASSERT(desc.family); - - // Making sure that desc.family supports the requested script - QtFontDesc mappedDesc; - bool supportsScript = false; - do { - match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies); - if (mappedDesc.family == desc.family) { - supportsScript = true; - break; - } - blacklistedFamilies.append(mappedDesc.familyIndex); - } while (mappedDesc.family); - if (!supportsScript) { - blacklistedFamilies.clear(); - match(script, req, QString(), QString(), -1, &mappedDesc, blacklistedFamilies); - if (mappedDesc.family) - desc = mappedDesc; - } - - const QString fontFamily = desc.family->name; - QFontDef request = req; - request.family = fontFamily; -#ifdef QT_NO_FREETYPE - const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); - const QSymbianTypeFaceExtras *typeFaceExtras = - dbExtras->extras(fontFamily, request.weight > QFont::Normal, request.style != QFont::StyleNormal); - - // We need a valid pixelSize, e.g. for lineThickness() - if (request.pixelSize < 0) - request.pixelSize = request.pointSize * d->dpi / 72; - - fe = new QFontEngineS60(request, typeFaceExtras); -#else // QT_NO_FREETYPE - Q_UNUSED(d) - QFontEngine::FaceId faceId; - const QtFontFamily * const reqQtFontFamily = db->family(fontFamily); - faceId.filename = reqQtFontFamily->fontFilename; - faceId.index = reqQtFontFamily->fontFileIndex; - - QFontEngineFTS60 *fte = new QFontEngineFTS60(cleanedFontDef(request)); - if (fte->init(faceId, true, QFontEngineFT::Format_A8)) - fe = fte; - else - delete fte; -#endif // QT_NO_FREETYPE - - Q_ASSERT(fe); - if (script == QUnicodeTables::Common - && !(req.styleStrategy & QFont::NoFontMerging) - && !fe->symbol) { - - QStringList commonFonts; - for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { - if (scriptForWritingSystem[ws] != script) - continue; - for (int i = 0; i < db->count; ++i) { - if (db->families[i]->writingSystems[ws] & QtFontFamily::Supported) - commonFonts.append(db->families[i]->name); - } - } - - // Hack: Prioritize .ccc fonts - const QString niceEastAsianFont(QLatin1String("Sans MT 936_S60")); - if (commonFonts.removeAll(niceEastAsianFont) > 0) - commonFonts.prepend(niceEastAsianFont); - - fe = new QFontEngineMultiS60(fe, script, commonFonts); - } - } - fe->ref.ref(); - QFontCache::instance()->insertEngine(key, fe); - return fe; -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - QFontEngine *fe = 0; - QFontDef req = d->request; - - if (!d->engineData) { - const QFontCache::Key key(cleanedFontDef(req), script); - getEngineData(d, key); - } - - // the cached engineData could have already loaded the engine we want - if (d->engineData->engines[script]) - fe = d->engineData->engines[script]; - - if (!fe) { - if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - fe = new QTestFontEngine(req.pixelSize); - fe->fontDef = req; - } else { - fe = findFont(script, d, req); - } - d->engineData->engines[script] = fe; - } -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp deleted file mode 100644 index 05b7509bf6..0000000000 --- a/src/gui/text/qfontdatabase_win.cpp +++ /dev/null @@ -1,1348 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qt_windows.h" -#include <qmath.h> -#include <private/qapplication_p.h> -#include "qfont_p.h" -#include "qfontengine_p.h" -#include "qpaintdevice.h" -#include <private/qsystemlibrary_p.h> -#include "qabstractfileengine.h" -#include "qendian.h" - -#if !defined(QT_NO_DIRECTWRITE) -# include "qsettings.h" -# include "qfontenginedirectwrite_p.h" -#endif - -#ifdef Q_OS_WINCE -# include <QTemporaryFile> -#endif - -QT_BEGIN_NAMESPACE - -extern HDC shared_dc(); // common dc for all fonts - -#ifdef MAKE_TAG -#undef MAKE_TAG -#endif -// GetFontData expects the tags in little endian ;( -#define MAKE_TAG(ch1, ch2, ch3, ch4) (\ - (((quint32)(ch4)) << 24) | \ - (((quint32)(ch3)) << 16) | \ - (((quint32)(ch2)) << 8) | \ - ((quint32)(ch1)) \ - ) - -static HFONT stock_sysfont = 0; - -static bool localizedName(const QString &name) -{ - const QChar *c = name.unicode(); - for(int i = 0; i < name.length(); ++i) { - if(c[i].unicode() >= 0x100) - return true; - } - return false; -} - -static inline quint16 getUShort(const unsigned char *p) -{ - quint16 val; - val = *p++ << 8; - val |= *p; - - return val; -} - -static QString getEnglishName(const uchar *table, quint32 bytes) -{ - QString i18n_name; - enum { - NameRecordSize = 12, - FamilyId = 1, - MS_LangIdEnglish = 0x009 - }; - - // get the name table - quint16 count; - quint16 string_offset; - const unsigned char *names; - - int microsoft_id = -1; - int apple_id = -1; - int unicode_id = -1; - - if(getUShort(table) != 0) - goto error; - - count = getUShort(table+2); - string_offset = getUShort(table+4); - names = table + 6; - - if(string_offset >= bytes || 6 + count*NameRecordSize > string_offset) - goto error; - - for(int i = 0; i < count; ++i) { - // search for the correct name entry - - quint16 platform_id = getUShort(names + i*NameRecordSize); - quint16 encoding_id = getUShort(names + 2 + i*NameRecordSize); - quint16 language_id = getUShort(names + 4 + i*NameRecordSize); - quint16 name_id = getUShort(names + 6 + i*NameRecordSize); - - if(name_id != FamilyId) - continue; - - enum { - PlatformId_Unicode = 0, - PlatformId_Apple = 1, - PlatformId_Microsoft = 3 - }; - - quint16 length = getUShort(names + 8 + i*NameRecordSize); - quint16 offset = getUShort(names + 10 + i*NameRecordSize); - if(DWORD(string_offset + offset + length) >= bytes) - continue; - - if ((platform_id == PlatformId_Microsoft - && (encoding_id == 0 || encoding_id == 1)) - && (language_id & 0x3ff) == MS_LangIdEnglish - && microsoft_id == -1) - microsoft_id = i; - // not sure if encoding id 4 for Unicode is utf16 or ucs4... - else if(platform_id == PlatformId_Unicode && encoding_id < 4 && unicode_id == -1) - unicode_id = i; - else if(platform_id == PlatformId_Apple && encoding_id == 0 && language_id == 0) - apple_id = i; - } - { - bool unicode = false; - int id = -1; - if(microsoft_id != -1) { - id = microsoft_id; - unicode = true; - } else if(apple_id != -1) { - id = apple_id; - unicode = false; - } else if (unicode_id != -1) { - id = unicode_id; - unicode = true; - } - if(id != -1) { - quint16 length = getUShort(names + 8 + id*NameRecordSize); - quint16 offset = getUShort(names + 10 + id*NameRecordSize); - if(unicode) { - // utf16 - - length /= 2; - i18n_name.resize(length); - QChar *uc = (QChar *) i18n_name.unicode(); - const unsigned char *string = table + string_offset + offset; - for(int i = 0; i < length; ++i) - uc[i] = getUShort(string + 2*i); - } else { - // Apple Roman - - i18n_name.resize(length); - QChar *uc = (QChar *) i18n_name.unicode(); - const unsigned char *string = table + string_offset + offset; - for(int i = 0; i < length; ++i) - uc[i] = QLatin1Char(string[i]); - } - } - } - error: - //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); - return i18n_name; -} - -static QString getEnglishName(const QString &familyName) -{ - QString i18n_name; - - HDC hdc = GetDC( 0 ); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); - lf.lfCharSet = DEFAULT_CHARSET; - HFONT hfont = CreateFontIndirect(&lf); - - if(!hfont) { - ReleaseDC(0, hdc); - return QString(); - } - - HGDIOBJ oldobj = SelectObject( hdc, hfont ); - - const DWORD name_tag = MAKE_TAG( 'n', 'a', 'm', 'e' ); - - // get the name table - unsigned char *table = 0; - - DWORD bytes = GetFontData( hdc, name_tag, 0, 0, 0 ); - if ( bytes == GDI_ERROR ) { - // ### Unused variable - /* int err = GetLastError(); */ - goto error; - } - - table = new unsigned char[bytes]; - GetFontData(hdc, name_tag, 0, table, bytes); - if ( bytes == GDI_ERROR ) - goto error; - - i18n_name = getEnglishName(table, bytes); -error: - delete [] table; - SelectObject( hdc, oldobj ); - DeleteObject( hfont ); - ReleaseDC( 0, hdc ); - - //qDebug("got i18n name of '%s' for font '%s'", i18n_name.latin1(), familyName.toLocal8Bit().data()); - return i18n_name; -} - -extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp - -static -void addFontToDatabase(QString familyName, const QString &scriptName, - TEXTMETRIC *textmetric, - const FONTSIGNATURE *signature, - int type) -{ - const int script = -1; - const QString foundryName; - Q_UNUSED(script); - - bool italic = false; - int weight; - bool fixed; - bool ttf; - bool scalable; - int size; - -// QString escript = QString::fromWCharArray(f->elfScript); -// qDebug("script=%s", escript.latin1()); - - NEWTEXTMETRIC *tm = (NEWTEXTMETRIC *)textmetric; - fixed = !(tm->tmPitchAndFamily & TMPF_FIXED_PITCH); - ttf = (tm->tmPitchAndFamily & TMPF_TRUETYPE); - scalable = tm->tmPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE); - size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; - italic = tm->tmItalic; - weight = tm->tmWeight; - - // the "@family" fonts are just the same as "family". Ignore them. - if (familyName[0] != QLatin1Char('@') && !familyName.startsWith(QLatin1String("WST_"))) { - QtFontStyle::Key styleKey; - styleKey.style = italic ? QFont::StyleItalic : QFont::StyleNormal; - styleKey.weight = weightFromInteger(weight); - - QtFontFamily *family = privateDb()->family(familyName, true); - - if(ttf && localizedName(familyName) && family->english_name.isEmpty()) - family->english_name = getEnglishName(familyName); - - QtFontFoundry *foundry = family->foundry(foundryName, true); - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - - // add fonts windows can generate for us: - if (styleKey.weight <= QFont::DemiBold) { - QtFontStyle::Key key(styleKey); - key.weight = QFont::Bold; - QtFontStyle *style = foundry->style(key, true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - } - if (styleKey.style != QFont::StyleItalic) { - QtFontStyle::Key key(styleKey); - key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - } - if (styleKey.weight <= QFont::DemiBold && styleKey.style != QFont::StyleItalic) { - QtFontStyle::Key key(styleKey); - key.weight = QFont::Bold; - key.style = QFont::StyleItalic; - QtFontStyle *style = foundry->style(key, true); - style->smoothScalable = scalable; - style->pixelSize( size, TRUE); - } - - family->fixedPitch = fixed; - - if (!family->writingSystemCheck && type & TRUETYPE_FONTTYPE) { - quint32 unicodeRange[4] = { - signature->fsUsb[0], signature->fsUsb[1], - signature->fsUsb[2], signature->fsUsb[3] - }; -#ifdef Q_WS_WINCE - if (signature->fsUsb[0] == 0) { - // If the unicode ranges bit mask is zero then - // EnumFontFamiliesEx failed to determine it properly. - // In this case we just pretend that the font supports all languages. - unicodeRange[0] = 0xbfffffff; // second most significant bit must be zero - unicodeRange[1] = 0xffffffff; - unicodeRange[2] = 0xffffffff; - unicodeRange[3] = 0xffffffff; - } -#endif - quint32 codePageRange[2] = { - signature->fsCsb[0], signature->fsCsb[1] - }; - QList<QFontDatabase::WritingSystem> systems = qt_determine_writing_systems_from_truetype_bits(unicodeRange, codePageRange); - - for (int i = 0; i < systems.count(); ++i) { - QFontDatabase::WritingSystem writingSystem = systems.at(i); - - // ### Hack to work around problem with Thai text on Windows 7. Segoe UI contains - // the symbol for Baht, and Windows thus reports that it supports the Thai script. - // Since it's the default UI font on this platform, most widgets will be unable to - // display Thai text by default. As a temporary work around, we special case Segoe UI - // and remove the Thai script from its list of supported writing systems. - if (writingSystem != QFontDatabase::Thai || familyName != QLatin1String("Segoe UI")) - family->writingSystems[writingSystem] = QtFontFamily::Supported; - } - } else if (!family->writingSystemCheck) { - //qDebug("family='%s' script=%s", family->name.latin1(), script.latin1()); - if (scriptName == QLatin1String("Western") - || scriptName == QLatin1String("Baltic") - || scriptName == QLatin1String("Central European") - || scriptName == QLatin1String("Turkish") - || scriptName == QLatin1String("Vietnamese")) - family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Thai")) - family->writingSystems[QFontDatabase::Thai] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Symbol") - || scriptName == QLatin1String("Other")) - family->writingSystems[QFontDatabase::Symbol] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("OEM/Dos")) - family->writingSystems[QFontDatabase::Latin] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("CHINESE_GB2312")) - family->writingSystems[QFontDatabase::SimplifiedChinese] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("CHINESE_BIG5")) - family->writingSystems[QFontDatabase::TraditionalChinese] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Cyrillic")) - family->writingSystems[QFontDatabase::Cyrillic] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Hangul")) - family->writingSystems[QFontDatabase::Korean] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Hebrew")) - family->writingSystems[QFontDatabase::Hebrew] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Greek")) - family->writingSystems[QFontDatabase::Greek] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Japanese")) - family->writingSystems[QFontDatabase::Japanese] = QtFontFamily::Supported; - else if (scriptName == QLatin1String("Arabic")) - family->writingSystems[QFontDatabase::Arabic] = QtFontFamily::Supported; - } - } -} - -static -int CALLBACK -storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, int type, LPARAM /*p*/) -{ - QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); - QString script = QString::fromWCharArray(f->elfScript); - - FONTSIGNATURE signature = textmetric->ntmFontSig; - - // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is - // identical to a TEXTMETRIC except for the last four members, which we don't use - // anyway - addFontToDatabase(familyName, script, (TEXTMETRIC *)textmetric, &signature, type); - // keep on enumerating - return 1; -} - -static -void populate_database(const QString& fam) -{ - QFontDatabasePrivate *d = privateDb(); - if (!d) - return; - - QtFontFamily *family = 0; - if(!fam.isEmpty()) { - family = d->family(fam); - if(family && family->loaded) - return; - } else if (d->count) { - return; - } - - HDC dummy = GetDC(0); - - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - if (fam.isNull()) { - lf.lfFaceName[0] = 0; - } else { - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded - } - lf.lfPitchAndFamily = 0; - - EnumFontFamiliesEx(dummy, &lf, - (FONTENUMPROC)storeFont, (LPARAM)privateDb(), 0); - - ReleaseDC(0, dummy); - - for (int i = 0; i < d->applicationFonts.count(); ++i) { - QFontDatabasePrivate::ApplicationFont fnt = d->applicationFonts.at(i); - if (!fnt.memoryFont) - continue; - for (int j = 0; j < fnt.families.count(); ++j) { - const QString familyName = fnt.families.at(j); - HDC hdc = GetDC(0); - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size())); - lf.lfCharSet = DEFAULT_CHARSET; - HFONT hfont = CreateFontIndirect(&lf); - HGDIOBJ oldobj = SelectObject(hdc, hfont); - - TEXTMETRIC textMetrics; - GetTextMetrics(hdc, &textMetrics); - - addFontToDatabase(familyName, QString(), - &textMetrics, - &fnt.signatures.at(j), - TRUETYPE_FONTTYPE); - - SelectObject(hdc, oldobj); - DeleteObject(hfont); - ReleaseDC(0, hdc); - } - } - - if(!fam.isEmpty()) { - family = d->family(fam); - if(family) { - if(!family->writingSystemCheck) { - } - family->loaded = true; - } - } -} - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db || db->count) - return; - - populate_database(QString()); - -#ifdef QFONTDATABASE_DEBUG - // print the database - for (int f = 0; f < db->count; f++) { - QtFontFamily *family = db->families[f]; - qDebug(" %s: %p", qPrintable(family->name), family); - populate_database(family->name); - -#if 0 - qDebug(" scripts supported:"); - for (int i = 0; i < QUnicodeTables::ScriptCount; i++) - if(family->writingSystems[i] & QtFontFamily::Supported) - qDebug(" %d", i); - for (int fd = 0; fd < family->count; fd++) { - QtFontFoundry *foundry = family->foundries[fd]; - qDebug(" %s", foundry->name.latin1()); - for (int s = 0; s < foundry->count; s++) { - QtFontStyle *style = foundry->styles[s]; - qDebug(" style: style=%d weight=%d smooth=%d", style->key.style, - style->key.weight, style->smoothScalable ); - if(!style->smoothScalable) { - for(int i = 0; i < style->count; ++i) { - qDebug(" %d", style->pixelSizes[i].pixelSize); - } - } - } - } -#endif - } -#endif // QFONTDATABASE_DEBUG - -} - -static inline void load(const QString &family = QString(), int = -1) -{ - populate_database(family); -} - - - - - -// -------------------------------------------------------------------------------------- -// font loader -// -------------------------------------------------------------------------------------- - - - -static void initFontInfo(QFontEngineWin *fe, const QFontDef &request, HDC fontHdc, int dpi) -{ - fe->fontDef = request; // most settings are equal - - HDC dc = ((request.styleStrategy & QFont::PreferDevice) && fontHdc) ? fontHdc : shared_dc(); - SelectObject(dc, fe->hfont); - wchar_t n[64]; - GetTextFace(dc, 64, n); - fe->fontDef.family = QString::fromWCharArray(n); - fe->fontDef.fixedPitch = !(fe->tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - if (fe->fontDef.pointSize < 0) { - fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi; - } else if (fe->fontDef.pixelSize == -1) { - fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.); - } -} - -#if !defined(QT_NO_DIRECTWRITE) -static void initFontInfo(QFontEngineDirectWrite *fe, const QFontDef &request, - int dpi, IDWriteFont *font) -{ - fe->fontDef = request; - - IDWriteFontFamily *fontFamily = NULL; - HRESULT hr = font->GetFontFamily(&fontFamily); - - IDWriteLocalizedStrings *familyNames = NULL; - if (SUCCEEDED(hr)) - hr = fontFamily->GetFamilyNames(&familyNames); - - UINT32 index = 0; - BOOL exists = false; - - wchar_t localeName[LOCALE_NAME_MAX_LENGTH]; - - if (SUCCEEDED(hr)) { - int defaultLocaleSuccess = GetUserDefaultLocaleName(localeName, LOCALE_NAME_MAX_LENGTH); - - if (defaultLocaleSuccess) - hr = familyNames->FindLocaleName(localeName, &index, &exists); - - if (SUCCEEDED(hr) && !exists) - hr = familyNames->FindLocaleName(L"en-us", &index, &exists); - } - - if (!exists) - index = 0; - - UINT32 length = 0; - if (SUCCEEDED(hr)) - hr = familyNames->GetStringLength(index, &length); - - wchar_t *name = new (std::nothrow) wchar_t[length+1]; - if (name == NULL) - hr = E_OUTOFMEMORY; - - // Get the family name. - if (SUCCEEDED(hr)) - hr = familyNames->GetString(index, name, length + 1); - - if (SUCCEEDED(hr)) - fe->fontDef.family = QString::fromWCharArray(name); - - delete[] name; - if (familyNames != NULL) - familyNames->Release(); - - if (FAILED(hr)) - qErrnoWarning(hr, "initFontInfo: Failed to get family name"); - - if (fe->fontDef.pointSize < 0) - fe->fontDef.pointSize = fe->fontDef.pixelSize * 72. / dpi; - else if (fe->fontDef.pixelSize == -1) - fe->fontDef.pixelSize = qRound(fe->fontDef.pointSize * dpi / 72.); -} -#endif - -static const char *other_tryFonts[] = { - "Arial", - "MS UI Gothic", - "Gulim", - "SimSun", - "PMingLiU", - "Arial Unicode MS", - 0 -}; - -static const char *jp_tryFonts [] = { - "MS UI Gothic", - "Arial", - "Gulim", - "SimSun", - "PMingLiU", - "Arial Unicode MS", - 0 -}; - -static const char *ch_CN_tryFonts [] = { - "SimSun", - "Arial", - "PMingLiU", - "Gulim", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char *ch_TW_tryFonts [] = { - "PMingLiU", - "Arial", - "SimSun", - "Gulim", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char *kr_tryFonts[] = { - "Gulim", - "Arial", - "PMingLiU", - "SimSun", - "MS UI Gothic", - "Arial Unicode MS", - 0 -}; - -static const char **tryFonts = 0; - -#if !defined(QT_NO_DIRECTWRITE) -static QString fontNameSubstitute(const QString &familyName) -{ - QLatin1String key("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\" - "FontSubstitutes"); - return QSettings(key, QSettings::NativeFormat).value(familyName, familyName).toString(); -} -#endif - -static inline HFONT systemFont() -{ - if (stock_sysfont == 0) - stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT); - return stock_sysfont; -} - -#if !defined(DEFAULT_GUI_FONT) -#define DEFAULT_GUI_FONT 17 -#endif - -static QFontEngine *loadEngine(int script, const QFontDef &request, - HDC fontHdc, int dpi, bool rawMode, - const QtFontDesc *desc, - const QStringList &family_list) -{ - LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); - - bool useDevice = (request.styleStrategy & QFont::PreferDevice) && fontHdc; - - HDC hdc = shared_dc(); - QString font_name = desc != 0 ? desc->family->name : request.family; - - if (useDevice) { - hdc = fontHdc; - font_name = request.family; - } - - bool stockFont = false; - bool preferClearTypeAA = false; - - HFONT hfont = 0; - - -#if !defined(QT_NO_DIRECTWRITE) - bool useDirectWrite = (request.hintingPreference == QFont::PreferNoHinting) - || (request.hintingPreference == QFont::PreferVerticalHinting); - IDWriteFont *directWriteFont = 0; -#else - bool useDirectWrite = false; -#endif - - if (rawMode) { // will choose a stock font - int f, deffnt = SYSTEM_FONT; - QString fam = desc != 0 ? desc->family->name.toLower() : request.family.toLower(); - if (fam == QLatin1String("default")) - f = deffnt; - else if (fam == QLatin1String("system")) - f = SYSTEM_FONT; -#ifndef Q_WS_WINCE - else if (fam == QLatin1String("system_fixed")) - f = SYSTEM_FIXED_FONT; - else if (fam == QLatin1String("ansi_fixed")) - f = ANSI_FIXED_FONT; - else if (fam == QLatin1String("ansi_var")) - f = ANSI_VAR_FONT; - else if (fam == QLatin1String("device_default")) - f = DEVICE_DEFAULT_FONT; - else if (fam == QLatin1String("oem_fixed")) - f = OEM_FIXED_FONT; -#endif - else if (fam[0] == QLatin1Char('#')) - f = fam.right(fam.length()-1).toInt(); - else - f = deffnt; - hfont = (HFONT)GetStockObject(f); - if (!hfont) { - qErrnoWarning("QFontEngine::loadEngine: GetStockObject failed"); - hfont = systemFont(); - } - stockFont = true; - } else { - - int hint = FF_DONTCARE; - switch (request.styleHint) { - case QFont::Helvetica: - hint = FF_SWISS; - break; - case QFont::Times: - hint = FF_ROMAN; - break; - case QFont::Courier: - hint = FF_MODERN; - break; - case QFont::OldEnglish: - hint = FF_DECORATIVE; - break; - case QFont::System: - hint = FF_MODERN; - break; - default: - break; - } - - lf.lfHeight = -qRound(request.pixelSize); - lf.lfWidth = 0; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - if (desc == 0 || desc->style->key.weight == 50) - lf.lfWeight = FW_DONTCARE; - else - lf.lfWeight = (desc->style->key.weight*900)/99; - lf.lfItalic = (desc != 0 && desc->style->key.style != QFont::StyleNormal); - lf.lfCharSet = DEFAULT_CHARSET; - - int strat = OUT_DEFAULT_PRECIS; - if (request.styleStrategy & QFont::PreferBitmap) { - strat = OUT_RASTER_PRECIS; -#ifndef Q_WS_WINCE - } else if (request.styleStrategy & QFont::PreferDevice) { - strat = OUT_DEVICE_PRECIS; - } else if (request.styleStrategy & QFont::PreferOutline) { - strat = OUT_OUTLINE_PRECIS; - } else if (request.styleStrategy & QFont::ForceOutline) { - strat = OUT_TT_ONLY_PRECIS; -#endif - } - - lf.lfOutPrecision = strat; - - int qual = DEFAULT_QUALITY; - - if (request.styleStrategy & QFont::PreferMatch) - qual = DRAFT_QUALITY; -#ifndef Q_WS_WINCE - else if (request.styleStrategy & QFont::PreferQuality) - qual = PROOF_QUALITY; -#endif - - if (request.styleStrategy & QFont::PreferAntialias) { - if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP) { - qual = CLEARTYPE_QUALITY; - preferClearTypeAA = true; - } else { - qual = ANTIALIASED_QUALITY; - } - } else if (request.styleStrategy & QFont::NoAntialias) { - qual = NONANTIALIASED_QUALITY; - } - - lf.lfQuality = qual; - - lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - lf.lfPitchAndFamily = DEFAULT_PITCH | hint; - - QString fam = font_name; - - if(fam.isEmpty()) - fam = QLatin1String("MS Sans Serif"); - - if ((fam == QLatin1String("MS Sans Serif")) - && (request.style == QFont::StyleItalic || (-lf.lfHeight > 18 && -lf.lfHeight != 24))) { - fam = QLatin1String("Arial"); // MS Sans Serif has bearing problems in italic, and does not scale - } - if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) - fam = QLatin1String("Courier New"); - - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded - - hfont = CreateFontIndirect(&lf); - if (!hfont) - qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect failed"); - - stockFont = (hfont == 0); - bool ttf = false; - int avWidth = 0; - BOOL res; - HGDIOBJ oldObj = SelectObject(hdc, hfont); - - TEXTMETRIC tm; - res = GetTextMetrics(hdc, &tm); - avWidth = tm.tmAveCharWidth; - ttf = tm.tmPitchAndFamily & TMPF_TRUETYPE; - SelectObject(hdc, oldObj); - - if (!ttf || !useDirectWrite) { - useDirectWrite = false; - - if (hfont && (!ttf || request.stretch != 100)) { - DeleteObject(hfont); - if (!res) - qErrnoWarning("QFontEngine::loadEngine: GetTextMetrics failed"); - lf.lfWidth = avWidth * request.stretch/100; - hfont = CreateFontIndirect(&lf); - if (!hfont) - qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed"); - } - -#ifndef Q_WS_WINCE - if (hfont == 0) { - hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); - stockFont = true; - } -#else - if (hfont == 0) { - hfont = (HFONT)GetStockObject(SYSTEM_FONT); - stockFont = true; - } -#endif - - } - -#if !defined(QT_NO_DIRECTWRITE) - else { - // Default to false for DirectWrite (and re-enable once/if everything - // turns out okay) - useDirectWrite = false; - - QFontDatabasePrivate *db = privateDb(); - if (db->directWriteFactory == 0) { - HRESULT hr = DWriteCreateFactory( - DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast<IUnknown **>(&db->directWriteFactory) - ); - if (FAILED(hr)) { - qErrnoWarning("QFontEngine::loadEngine: DWriteCreateFactory failed"); - } else { - hr = db->directWriteFactory->GetGdiInterop(&db->directWriteGdiInterop); - if (FAILED(hr)) - qErrnoWarning("QFontEngine::loadEngine: GetGdiInterop failed"); - } - } - - if (db->directWriteGdiInterop != 0) { - QString nameSubstitute = fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName)); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), - sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); - - HRESULT hr = db->directWriteGdiInterop->CreateFontFromLOGFONT( - &lf, - &directWriteFont); - if (FAILED(hr)) { -#ifndef QT_NO_DEBUG - qErrnoWarning("QFontEngine::loadEngine: CreateFontFromLOGFONT failed " - "for %ls (0x%lx)", - lf.lfFaceName, hr); -#endif - } else { - DeleteObject(hfont); - useDirectWrite = true; - } - } - } -#endif - - } - - QFontEngine *fe = 0; - if (!useDirectWrite) { - QFontEngineWin *few = new QFontEngineWin(font_name, hfont, stockFont, lf); - if (preferClearTypeAA) - few->glyphFormat = QFontEngineGlyphCache::Raster_RGBMask; - - // Also check for OpenType tables when using complex scripts - // ### TODO: This only works for scripts that require OpenType. More generally - // for scripts that do not require OpenType we should just look at the list of - // supported writing systems in the font's OS/2 table. - if (scriptRequiresOpenType(script)) { - HB_Face hbFace = few->harfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { - FM_DEBUG(" OpenType support missing for script\n"); - delete few; - return 0; - } - } - - initFontInfo(few, request, fontHdc, dpi); - fe = few; - } - -#if !defined(QT_NO_DIRECTWRITE) - else { - QFontDatabasePrivate *db = privateDb(); - - IDWriteFontFace *directWriteFontFace = NULL; - HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace); - if (SUCCEEDED(hr)) { - QFontEngineDirectWrite *fedw = new QFontEngineDirectWrite(db->directWriteFactory, - directWriteFontFace, - request.pixelSize); - - initFontInfo(fedw, request, dpi, directWriteFont); - - fe = fedw; - } else { - qErrnoWarning(hr, "QFontEngine::loadEngine: CreateFontFace failed"); - } - } - - if (directWriteFont != 0) - directWriteFont->Release(); -#endif - - if(script == QUnicodeTables::Common - && !(request.styleStrategy & QFont::NoFontMerging) - && desc != 0 - && !(desc->family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) { - if(!tryFonts) { - LANGID lid = GetUserDefaultLangID(); - switch( lid&0xff ) { - case LANG_CHINESE: // Chinese (Taiwan) - if ( lid == 0x0804 ) // Taiwan - tryFonts = ch_TW_tryFonts; - else - tryFonts = ch_CN_tryFonts; - break; - case LANG_JAPANESE: - tryFonts = jp_tryFonts; - break; - case LANG_KOREAN: - tryFonts = kr_tryFonts; - break; - default: - tryFonts = other_tryFonts; - break; - } - } - QStringList fm = QFontDatabase().families(); - QStringList list = family_list; - const char **tf = tryFonts; - while(tf && *tf) { - if(fm.contains(QLatin1String(*tf))) - list << QLatin1String(*tf); - ++tf; - } - QFontEngine *mfe = new QFontEngineMultiWin(fe, list); - mfe->fontDef = fe->fontDef; - fe = mfe; - } - return fe; -} - -QFontEngine *qt_load_font_engine_win(const QFontDef &request) -{ - // From qfont.cpp - extern int qt_defaultDpi(); - - QFontCache::Key key(request, QUnicodeTables::Common); - QFontEngine *fe = QFontCache::instance()->findEngine(key); - if (fe != 0) - return fe; - else - return loadEngine(QUnicodeTables::Common, request, 0, qt_defaultDpi(), false, 0, - QStringList()); -} - -const char *styleHint(const QFontDef &request) -{ - const char *stylehint = 0; - switch (request.styleHint) { - case QFont::SansSerif: - stylehint = "Arial"; - break; - case QFont::Serif: - stylehint = "Times New Roman"; - break; - case QFont::TypeWriter: - stylehint = "Courier New"; - break; - default: - if (request.fixedPitch) - stylehint = "Courier New"; - break; - } - return stylehint; -} - -static QFontEngine *loadWin(const QFontPrivate *d, int script, const QFontDef &req) -{ - // list of families to try - QStringList family_list = familyList(req); - - const char *stylehint = styleHint(d->request); - if (stylehint) - family_list << QLatin1String(stylehint); - - // append the default fallback font for the specified script - // family_list << ... ; ########### - - // add the default family - QString defaultFamily = QApplication::font().family(); - if (! family_list.contains(defaultFamily)) - family_list << defaultFamily; - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - family_list << QApplication::font().defaultFamily(); - - // null family means find the first font matching the specified script - family_list << QString(); - - QtFontDesc desc; - QFontEngine *fe = 0; - QList<int> blacklistedFamilies; - - while (!fe) { - for (int i = 0; i < family_list.size(); ++i) { - QString family, foundry; - parseFontName(family_list.at(i), foundry, family); - FM_DEBUG("loadWin: >>>>>>>>>>>>>>trying to match '%s'", family.toLatin1().data()); - QT_PREPEND_NAMESPACE(match)(script, req, family, foundry, -1, &desc, blacklistedFamilies); - if (desc.family) - break; - } - if (!desc.family) - break; - fe = loadEngine(script, req, d->hdc, d->dpi, d->rawMode, &desc, family_list); - if (!fe) - blacklistedFamilies.append(desc.familyIndex); - } - return fe; -} - -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - // sanity checks - if (!qApp) - qWarning("QFontDatabase::load: Must construct QApplication first"); - Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); - - // normalize the request to get better caching - QFontDef req = d->request; - if (req.pixelSize <= 0) - req.pixelSize = floor((100.0 * req.pointSize * d->dpi) / 72. + 0.5) / 100; - if (req.pixelSize < 1) - req.pixelSize = 1; - if (req.weight == 0) - req.weight = QFont::Normal; - if (req.stretch == 0) - req.stretch = 100; - - QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen); - if (!d->engineData) - getEngineData(d, key); - - // the cached engineData could have already loaded the engine we want - if (d->engineData->engines[script]) - return; - - QFontEngine *fe = QFontCache::instance()->findEngine(key); - - // set it to the actual pointsize, so QFontInfo will do the right thing - if (req.pointSize < 0) - req.pointSize = req.pixelSize*72./d->dpi; - - if (!fe) { - if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - fe = new QTestFontEngine(req.pixelSize); - fe->fontDef = req; - } else { - QMutexLocker locker(fontDatabaseMutex()); - if (!privateDb()->count) - initializeDb(); - fe = loadWin(d, script, req); - } - if (!fe) { - fe = new QFontEngineBox(req.pixelSize); - fe->fontDef = QFontDef(); - } - } - d->engineData->engines[script] = fe; - fe->ref.ref(); - QFontCache::instance()->insertEngine(key, fe); -} - -#if !defined(FR_PRIVATE) -#define FR_PRIVATE 0x10 -#endif - -typedef int (WINAPI *PtrAddFontResourceExW)(LPCWSTR, DWORD, PVOID); -typedef HANDLE (WINAPI *PtrAddFontMemResourceEx)(PVOID, DWORD, PVOID, DWORD *); -typedef BOOL (WINAPI *PtrRemoveFontResourceExW)(LPCWSTR, DWORD, PVOID); -typedef BOOL (WINAPI *PtrRemoveFontMemResourceEx)(HANDLE); - -static QList<quint32> getTrueTypeFontOffsets(const uchar *fontData) -{ - QList<quint32> offsets; - const quint32 headerTag = *reinterpret_cast<const quint32 *>(fontData); - if (headerTag != MAKE_TAG('t', 't', 'c', 'f')) { - if (headerTag != MAKE_TAG(0, 1, 0, 0) - && headerTag != MAKE_TAG('O', 'T', 'T', 'O') - && headerTag != MAKE_TAG('t', 'r', 'u', 'e') - && headerTag != MAKE_TAG('t', 'y', 'p', '1')) - return offsets; - offsets << 0; - return offsets; - } - const quint32 numFonts = qFromBigEndian<quint32>(fontData + 8); - for (uint i = 0; i < numFonts; ++i) { - offsets << qFromBigEndian<quint32>(fontData + 12 + i * 4); - } - return offsets; -} - -static void getFontTable(const uchar *fileBegin, const uchar *data, quint32 tag, const uchar **table, quint32 *length) -{ - const quint16 numTables = qFromBigEndian<quint16>(data + 4); - for (uint i = 0; i < numTables; ++i) { - const quint32 offset = 12 + 16 * i; - if (*reinterpret_cast<const quint32 *>(data + offset) == tag) { - *table = fileBegin + qFromBigEndian<quint32>(data + offset + 8); - *length = qFromBigEndian<quint32>(data + offset + 12); - return; - } - } - *table = 0; - *length = 0; - return; -} - -static void getFamiliesAndSignatures(const QByteArray &fontData, QFontDatabasePrivate::ApplicationFont *appFont) -{ - const uchar *data = reinterpret_cast<const uchar *>(fontData.constData()); - - QList<quint32> offsets = getTrueTypeFontOffsets(data); - if (offsets.isEmpty()) - return; - - for (int i = 0; i < offsets.count(); ++i) { - const uchar *font = data + offsets.at(i); - const uchar *table; - quint32 length; - getFontTable(data, font, MAKE_TAG('n', 'a', 'm', 'e'), &table, &length); - if (!table) - continue; - QString name = getEnglishName(table, length); - if (name.isEmpty()) - continue; - - appFont->families << name; - FONTSIGNATURE signature; - getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length); - if (table && length >= 86) { - // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec - signature.fsUsb[0] = qFromBigEndian<quint32>(table + 42); - signature.fsUsb[1] = qFromBigEndian<quint32>(table + 46); - signature.fsUsb[2] = qFromBigEndian<quint32>(table + 50); - signature.fsUsb[3] = qFromBigEndian<quint32>(table + 54); - - signature.fsCsb[0] = qFromBigEndian<quint32>(table + 78); - signature.fsCsb[1] = qFromBigEndian<quint32>(table + 82); - } else { - memset(&signature, 0, sizeof(signature)); - } - appFont->signatures << signature; - } -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ - if(!fnt->data.isEmpty()) { -#ifndef Q_OS_WINCE - PtrAddFontMemResourceEx ptrAddFontMemResourceEx = (PtrAddFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), - "AddFontMemResourceEx"); - if (!ptrAddFontMemResourceEx) - return; -#endif - getFamiliesAndSignatures(fnt->data, fnt); - if (fnt->families.isEmpty()) - return; - -#ifdef Q_OS_WINCE - HANDLE handle = 0; - - { -#ifdef QT_NO_TEMPORARYFILE - wchar_t lpBuffer[MAX_PATH]; - GetTempPath(MAX_PATH, lpBuffer); - QString s = QString::fromWCharArray(lpBuffer); - QFile tempfile(s + QLatin1String("/font") + QString::number(GetTickCount()) + QLatin1String(".ttf")); - if (!tempfile.open(QIODevice::ReadWrite)) -#else - QTemporaryFile tempfile(QLatin1String("XXXXXXXX.ttf")); - if (!tempfile.open()) -#endif // QT_NO_TEMPORARYFILE - return; - if (tempfile.write(fnt->data) == -1) - return; - -#ifndef QT_NO_TEMPORARYFILE - tempfile.setAutoRemove(false); -#endif - fnt->fileName = QFileInfo(tempfile.fileName()).absoluteFilePath(); - } - - if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0) { - QFile(fnt->fileName).remove(); - return; - } -#else - DWORD dummy = 0; - HANDLE handle = ptrAddFontMemResourceEx((void *)fnt->data.constData(), fnt->data.size(), 0, - &dummy); - if (handle == 0) - return; -#endif // Q_OS_WINCE - - fnt->handle = handle; - fnt->data = QByteArray(); - fnt->memoryFont = true; - } else { - QFile f(fnt->fileName); - if (!f.open(QIODevice::ReadOnly)) - return; - QByteArray data = f.readAll(); - f.close(); - getFamiliesAndSignatures(data, fnt); - -#ifdef Q_OS_WINCE - QFileInfo fileinfo(fnt->fileName); - fnt->fileName = fileinfo.absoluteFilePath(); - if (AddFontResource((LPCWSTR)fnt->fileName.utf16()) == 0) - return; -#else - PtrAddFontResourceExW ptrAddFontResourceExW = (PtrAddFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), - "AddFontResourceExW"); - if (!ptrAddFontResourceExW - || ptrAddFontResourceExW((wchar_t*)fnt->fileName.utf16(), FR_PRIVATE, 0) == 0) - return; -#endif // Q_OS_WINCE - - fnt->memoryFont = false; - } -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (handle < 0 || handle >= db->applicationFonts.count()) - return false; - - const QFontDatabasePrivate::ApplicationFont font = db->applicationFonts.at(handle); - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - if (font.memoryFont) { -#ifdef Q_OS_WINCE - bool removeSucceeded = RemoveFontResource((LPCWSTR)font.fileName.utf16()); - QFile tempfile(font.fileName); - tempfile.remove(); - if (!removeSucceeded) - return false; -#else - PtrRemoveFontMemResourceEx ptrRemoveFontMemResourceEx = (PtrRemoveFontMemResourceEx)QSystemLibrary::resolve(QLatin1String("gdi32"), - "RemoveFontMemResourceEx"); - if (!ptrRemoveFontMemResourceEx - || !ptrRemoveFontMemResourceEx(font.handle)) - return false; -#endif // Q_OS_WINCE - } else { -#ifdef Q_OS_WINCE - if (!RemoveFontResource((LPCWSTR)font.fileName.utf16())) - return false; -#else - PtrRemoveFontResourceExW ptrRemoveFontResourceExW = (PtrRemoveFontResourceExW)QSystemLibrary::resolve(QLatin1String("gdi32"), - "RemoveFontResourceExW"); - if (!ptrRemoveFontResourceExW - || !ptrRemoveFontResourceExW((LPCWSTR)font.fileName.utf16(), FR_PRIVATE, 0)) - return false; -#endif // Q_OS_WINCE - } - - db->invalidate(); - return true; -} - -bool QFontDatabase::removeAllApplicationFonts() -{ - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - for (int i = 0; i < db->applicationFonts.count(); ++i) - if (!removeApplicationFont(i)) - return false; - return true; -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ - return true; -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp deleted file mode 100644 index 0c0c4c8343..0000000000 --- a/src/gui/text/qfontdatabase_x11.cpp +++ /dev/null @@ -1,2146 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <qplatformdefs.h> - -#include <qdebug.h> -#include <qpaintdevice.h> -#include <qelapsedtimer.h> - -#include <private/qt_x11_p.h> -#include "qx11info_x11.h" -#include <qdebug.h> -#include <qfile.h> -#include <qtemporaryfile.h> -#include <qabstractfileengine.h> -#include <qmath.h> - -#include <ctype.h> -#include <stdlib.h> - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <sys/mman.h> - -#include <private/qfontengine_x11_p.h> - -#ifndef QT_NO_FONTCONFIG -#include <ft2build.h> -#include FT_FREETYPE_H - -#if FC_VERSION >= 20402 -#include <fontconfig/fcfreetype.h> -#endif -#endif - -QT_BEGIN_NAMESPACE - -// from qfont_x11.cpp -extern double qt_pointSize(double pixelSize, int dpi); -extern double qt_pixelSize(double pointSize, int dpi); - -// from qapplication.cpp -extern bool qt_is_gui_used; - -static inline void capitalize (char *s) -{ - bool space = true; - while(*s) { - if (space) - *s = toupper(*s); - space = (*s == ' '); - ++s; - } -} - - -/* - To regenerate the writingSystems_for_xlfd_encoding table, run - 'util/unicode/x11/makeencodings' and paste the generated - 'encodings.c' here. -*/ -// ----- begin of generated code ----- - -#define make_tag( c1, c2, c3, c4 ) \ - ((((unsigned int)c1)<<24) | (((unsigned int)c2)<<16) | \ - (((unsigned int)c3)<<8) | ((unsigned int)c4)) - -struct XlfdEncoding { - const char *name; - int id; - int mib; - unsigned int hash1; - unsigned int hash2; -}; - -static const XlfdEncoding xlfd_encoding[] = { - { "iso8859-1", 0, 4, make_tag('i','s','o','8'), make_tag('5','9','-','1') }, - { "iso8859-2", 1, 5, make_tag('i','s','o','8'), make_tag('5','9','-','2') }, - { "iso8859-3", 2, 6, make_tag('i','s','o','8'), make_tag('5','9','-','3') }, - { "iso8859-4", 3, 7, make_tag('i','s','o','8'), make_tag('5','9','-','4') }, - { "iso8859-9", 4, 12, make_tag('i','s','o','8'), make_tag('5','9','-','9') }, - { "iso8859-10", 5, 13, make_tag('i','s','o','8'), make_tag('9','-','1','0') }, - { "iso8859-13", 6, 109, make_tag('i','s','o','8'), make_tag('9','-','1','3') }, - { "iso8859-14", 7, 110, make_tag('i','s','o','8'), make_tag('9','-','1','4') }, - { "iso8859-15", 8, 111, make_tag('i','s','o','8'), make_tag('9','-','1','5') }, - { "hp-roman8", 9, 2004, make_tag('h','p','-','r'), make_tag('m','a','n','8') }, - { "iso8859-5", 10, 8, make_tag('i','s','o','8'), make_tag('5','9','-','5') }, - { "*-cp1251", 11, 2251, 0, make_tag('1','2','5','1') }, - { "koi8-ru", 12, 2084, make_tag('k','o','i','8'), make_tag('8','-','r','u') }, - { "koi8-u", 13, 2088, make_tag('k','o','i','8'), make_tag('i','8','-','u') }, - { "koi8-r", 14, 2084, make_tag('k','o','i','8'), make_tag('i','8','-','r') }, - { "iso8859-7", 15, 10, make_tag('i','s','o','8'), make_tag('5','9','-','7') }, - { "iso8859-8", 16, 85, make_tag('i','s','o','8'), make_tag('5','9','-','8') }, - { "gb18030-0", 17, -114, make_tag('g','b','1','8'), make_tag('3','0','-','0') }, - { "gb18030.2000-0", 18, -113, make_tag('g','b','1','8'), make_tag('0','0','-','0') }, - { "gbk-0", 19, -113, make_tag('g','b','k','-'), make_tag('b','k','-','0') }, - { "gb2312.*-0", 20, 57, make_tag('g','b','2','3'), 0 }, - { "jisx0201*-0", 21, 15, make_tag('j','i','s','x'), 0 }, - { "jisx0208*-0", 22, 63, make_tag('j','i','s','x'), 0 }, - { "ksc5601*-*", 23, 36, make_tag('k','s','c','5'), 0 }, - { "big5hkscs-0", 24, -2101, make_tag('b','i','g','5'), make_tag('c','s','-','0') }, - { "hkscs-1", 25, -2101, make_tag('h','k','s','c'), make_tag('c','s','-','1') }, - { "big5*-*", 26, -2026, make_tag('b','i','g','5'), 0 }, - { "tscii-*", 27, 2028, make_tag('t','s','c','i'), 0 }, - { "tis620*-*", 28, 2259, make_tag('t','i','s','6'), 0 }, - { "iso8859-11", 29, 2259, make_tag('i','s','o','8'), make_tag('9','-','1','1') }, - { "mulelao-1", 30, -4242, make_tag('m','u','l','e'), make_tag('a','o','-','1') }, - { "ethiopic-unicode", 31, 0, make_tag('e','t','h','i'), make_tag('c','o','d','e') }, - { "iso10646-1", 32, 0, make_tag('i','s','o','1'), make_tag('4','6','-','1') }, - { "unicode-*", 33, 0, make_tag('u','n','i','c'), 0 }, - { "*-symbol", 34, 0, 0, make_tag('m','b','o','l') }, - { "*-fontspecific", 35, 0, 0, make_tag('i','f','i','c') }, - { "fontspecific-*", 36, 0, make_tag('f','o','n','t'), 0 }, - { 0, 0, 0, 0, 0 } -}; - -static const char writingSystems_for_xlfd_encoding[sizeof(xlfd_encoding)][QFontDatabase::WritingSystemsCount] = { - // iso8859-1 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-2 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-3 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-4 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-9 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-10 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-13 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-14 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-15 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // hp-roman8 - { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-5 - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // *-cp1251 - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // koi8-ru - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // koi8-u - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // koi8-r - { 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-7 - { 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-8 - { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // gb18030-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // gb18030.2000-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // gbk-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // gb2312.*-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, - 0, 0 }, - // jisx0201*-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0 }, - // jisx0208*-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0 }, - // ksc5601*-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, - 0, 0 }, - // big5hkscs-0 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0 }, - // hkscs-1 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0 }, - // big5*-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, - 0, 0 }, - // tscii-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // tis620*-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso8859-11 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // mulelao-1 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // ethiopic-unicode - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0 }, - // iso10646-1 - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0, 0 }, - // unicode-* - { 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, - 0, 0 }, - // *-symbol - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0 }, - // *-fontspecific - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0 }, - // fontspecific-* - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0 } - -}; - -// ----- end of generated code ----- - - -const int numEncodings = sizeof(xlfd_encoding) / sizeof(XlfdEncoding) - 1; - -int qt_xlfd_encoding_id(const char *encoding) -{ - // qDebug("looking for encoding id for '%s'", encoding); - int len = strlen(encoding); - if (len < 4) - return -1; - unsigned int hash1 = make_tag(encoding[0], encoding[1], encoding[2], encoding[3]); - const char *ch = encoding + len - 4; - unsigned int hash2 = make_tag(ch[0], ch[1], ch[2], ch[3]); - - const XlfdEncoding *enc = xlfd_encoding; - for (; enc->name; ++enc) { - if ((enc->hash1 && enc->hash1 != hash1) || - (enc->hash2 && enc->hash2 != hash2)) - continue; - // hashes match, do a compare if strings match - // the enc->name can contain '*'s we have to interpret correctly - const char *n = enc->name; - const char *e = encoding; - while (1) { - // qDebug("bol: *e='%c', *n='%c'", *e, *n); - if (*e == '\0') { - if (*n) - break; - // qDebug("found encoding id %d", enc->id); - return enc->id; - } - if (*e == *n) { - ++e; - ++n; - continue; - } - if (*n != '*') - break; - ++n; - // qDebug("skip: *e='%c', *n='%c'", *e, *n); - while (*e && *e != *n) - ++e; - } - } - // qDebug("couldn't find encoding %s", encoding); - return -1; -} - -int qt_mib_for_xlfd_encoding(const char *encoding) -{ - int id = qt_xlfd_encoding_id(encoding); - if (id != -1) return xlfd_encoding[id].mib; - return 0; -} - -int qt_encoding_id_for_mib(int mib) -{ - const XlfdEncoding *enc = xlfd_encoding; - for (; enc->name; ++enc) { - if (enc->mib == mib) - return enc->id; - } - return -1; -} - -static const char * xlfd_for_id(int id) -{ - // special case: -1 returns the "*-*" encoding, allowing us to do full - // database population in a single X server round trip. - if (id < 0 || id > numEncodings) - return "*-*"; - return xlfd_encoding[id].name; -} - -enum XLFDFieldNames { - Foundry, - Family, - Weight, - Slant, - Width, - AddStyle, - PixelSize, - PointSize, - ResolutionX, - ResolutionY, - Spacing, - AverageWidth, - CharsetRegistry, - CharsetEncoding, - NFontFields -}; - -// Splits an X font name into fields separated by '-' -static bool parseXFontName(char *fontName, char **tokens) -{ - if (! fontName || fontName[0] == '0' || fontName[0] != '-') { - tokens[0] = 0; - return false; - } - - int i; - ++fontName; - for (i = 0; i < NFontFields && fontName && fontName[0]; ++i) { - tokens[i] = fontName; - for (;; ++fontName) { - if (*fontName == '-') - break; - if (! *fontName) { - fontName = 0; - break; - } - } - - if (fontName) *fontName++ = '\0'; - } - - if (i < NFontFields) { - for (int j = i ; j < NFontFields; ++j) - tokens[j] = 0; - return false; - } - - return true; -} - -static inline bool isZero(char *x) -{ - return (x[0] == '0' && x[1] == 0); -} - -static inline bool isScalable(char **tokens) -{ - return (isZero(tokens[PixelSize]) && - isZero(tokens[PointSize]) && - isZero(tokens[AverageWidth])); -} - -static inline bool isSmoothlyScalable(char **tokens) -{ - return (isZero(tokens[ResolutionX]) && - isZero(tokens[ResolutionY])); -} - -static inline bool isFixedPitch(char **tokens) -{ - return (tokens[Spacing][0] == 'm' || - tokens[Spacing][0] == 'c' || - tokens[Spacing][0] == 'M' || - tokens[Spacing][0] == 'C'); -} - -/* - Fills in a font definition (QFontDef) from an XLFD (X Logical Font - Description). - - Returns true if the given xlfd is valid. -*/ -bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *desc) -{ - char *tokens[NFontFields]; - QByteArray buffer = xlfd; - if (! parseXFontName(buffer.data(), tokens)) - return false; - - capitalize(tokens[Family]); - capitalize(tokens[Foundry]); - - fd->styleStrategy |= QFont::NoAntialias; - fd->family = QString::fromLatin1(tokens[Family]); - QString foundry = QString::fromLatin1(tokens[Foundry]); - if (! foundry.isEmpty() && foundry != QLatin1String("*") && (!desc || desc->family->count > 1)) - fd->family += - QLatin1String(" [") + foundry + QLatin1Char(']'); - - if (qstrlen(tokens[AddStyle]) > 0) - fd->addStyle = QString::fromLatin1(tokens[AddStyle]); - else - fd->addStyle.clear(); - - fd->pointSize = atoi(tokens[PointSize])/10.; - fd->styleHint = QFont::AnyStyle; // ### any until we match families - - char slant = tolower((uchar) tokens[Slant][0]); - fd->style = (slant == 'o' ? QFont::StyleOblique : (slant == 'i' ? QFont::StyleItalic : QFont::StyleNormal)); - char fixed = tolower((uchar) tokens[Spacing][0]); - fd->fixedPitch = (fixed == 'm' || fixed == 'c'); - fd->weight = getFontWeight(QLatin1String(tokens[Weight])); - - int r = atoi(tokens[ResolutionY]); - fd->pixelSize = atoi(tokens[PixelSize]); - // not "0" or "*", or required DPI - if (r && fd->pixelSize && r != dpi) { - // calculate actual pointsize for display DPI - fd->pointSize = qt_pointSize(fd->pixelSize, dpi); - } else if (fd->pixelSize == 0 && fd->pointSize) { - // calculate pixel size from pointsize/dpi - fd->pixelSize = qRound(qt_pixelSize(fd->pointSize, dpi)); - } - - return true; -} - -/* - Fills in a font definition (QFontDef) from the font properties in an - XFontStruct. - - Returns true if the QFontDef could be filled with properties from - the XFontStruct. -*/ -static bool qt_fillFontDef(XFontStruct *fs, QFontDef *fd, int dpi, QtFontDesc *desc) -{ - unsigned long value; - if (!fs || !XGetFontProperty(fs, XA_FONT, &value)) - return false; - - char *n = XGetAtomName(QX11Info::display(), value); - QByteArray xlfd(n); - if (n) - XFree(n); - return qt_fillFontDef(xlfd.toLower(), fd, dpi, desc); -} - - -static QtFontStyle::Key getStyle(char ** tokens) -{ - QtFontStyle::Key key; - - char slant0 = tolower((uchar) tokens[Slant][0]); - - if (slant0 == 'r') { - if (tokens[Slant][1]) { - char slant1 = tolower((uchar) tokens[Slant][1]); - - if (slant1 == 'o') - key.style = QFont::StyleOblique; - else if (slant1 == 'i') - key.style = QFont::StyleItalic; - } - } else if (slant0 == 'o') - key.style = QFont::StyleOblique; - else if (slant0 == 'i') - key.style = QFont::StyleItalic; - - key.weight = getFontWeight(QLatin1String(tokens[Weight])); - - if (qstrcmp(tokens[Width], "normal") == 0) { - key.stretch = 100; - } else if (qstrcmp(tokens[Width], "semi condensed") == 0 || - qstrcmp(tokens[Width], "semicondensed") == 0) { - key.stretch = 90; - } else if (qstrcmp(tokens[Width], "condensed") == 0) { - key.stretch = 80; - } else if (qstrcmp(tokens[Width], "narrow") == 0) { - key.stretch = 60; - } - - return key; -} - - -static bool xlfdsFullyLoaded = false; -static unsigned char encodingLoaded[numEncodings]; - -static void loadXlfds(const char *reqFamily, int encoding_id) -{ - QFontDatabasePrivate *db = privateDb(); - QtFontFamily *fontFamily = reqFamily ? db->family(QLatin1String(reqFamily)) : 0; - - // make sure we don't load twice - if ((encoding_id == -1 && xlfdsFullyLoaded) - || (encoding_id != -1 && encodingLoaded[encoding_id])) - return; - if (fontFamily && fontFamily->xlfdLoaded) - return; - - int fontCount; - // force the X server to give us XLFDs - QByteArray xlfd_pattern("-*-"); - xlfd_pattern += (reqFamily && reqFamily[0] != '\0') ? reqFamily : "*"; - xlfd_pattern += "-*-*-*-*-*-*-*-*-*-*-"; - xlfd_pattern += xlfd_for_id(encoding_id); - - char **fontList = XListFonts(QX11Info::display(), - xlfd_pattern, - 0xffff, &fontCount); - // qDebug("requesting xlfd='%s', got %d fonts", xlfd_pattern.data(), fontCount); - - - char *tokens[NFontFields]; - - for(int i = 0 ; i < fontCount ; i++) { - if (! parseXFontName(fontList[i], tokens)) - continue; - - // get the encoding_id for this xlfd. we need to do this - // here, since we can pass -1 to this function to do full - // database population - *(tokens[CharsetEncoding] - 1) = '-'; - int encoding_id = qt_xlfd_encoding_id(tokens[CharsetRegistry]); - if (encoding_id == -1) - continue; - - char *familyName = tokens[Family]; - capitalize(familyName); - char *foundryName = tokens[Foundry]; - capitalize(foundryName); - QtFontStyle::Key styleKey = getStyle(tokens); - - bool smooth_scalable = false; - bool bitmap_scalable = false; - if (isScalable(tokens)) { - if (isSmoothlyScalable(tokens)) - smooth_scalable = true; - else - bitmap_scalable = true; - } - uint pixelSize = atoi(tokens[PixelSize]); - uint xpointSize = atoi(tokens[PointSize]); - uint xres = atoi(tokens[ResolutionX]); - uint yres = atoi(tokens[ResolutionY]); - uint avgwidth = atoi(tokens[AverageWidth]); - bool fixedPitch = isFixedPitch(tokens); - - if (avgwidth == 0 && pixelSize != 0) { - /* - Ignore bitmap scalable fonts that are automatically - generated by some X servers. We know they are bitmap - scalable because even though they have a specified pixel - size, the average width is zero. - */ - continue; - } - - QtFontFamily *family = fontFamily ? fontFamily : db->family(QLatin1String(familyName), true); - family->fontFileIndex = -1; - family->symbol_checked = true; - QtFontFoundry *foundry = family->foundry(QLatin1String(foundryName), true); - QtFontStyle *style = foundry->style(styleKey, true); - - delete [] style->weightName; - style->weightName = qstrdup(tokens[Weight]); - delete [] style->setwidthName; - style->setwidthName = qstrdup(tokens[Width]); - - if (smooth_scalable) { - style->smoothScalable = true; - style->bitmapScalable = false; - pixelSize = SMOOTH_SCALABLE; - } - if (!style->smoothScalable && bitmap_scalable) - style->bitmapScalable = true; - if (!fixedPitch) - family->fixedPitch = false; - - QtFontSize *size = style->pixelSize(pixelSize, true); - QtFontEncoding *enc = - size->encodingID(encoding_id, xpointSize, xres, yres, avgwidth, true); - enc->pitch = *tokens[Spacing]; - if (!enc->pitch) enc->pitch = '*'; - - for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { - if (writingSystems_for_xlfd_encoding[encoding_id][i]) - family->writingSystems[i] = QtFontFamily::Supported; - } - } - if (!reqFamily) { - // mark encoding as loaded - if (encoding_id == -1) - xlfdsFullyLoaded = true; - else - encodingLoaded[encoding_id] = true; - } - - XFreeFontNames(fontList); -} - - -#ifndef QT_NO_FONTCONFIG - -#ifndef FC_WIDTH -#define FC_WIDTH "width" -#endif - -static int getFCWeight(int fc_weight) -{ - int qtweight = QFont::Black; - if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2) - qtweight = QFont::Light; - else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2) - qtweight = QFont::Normal; - else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2) - qtweight = QFont::DemiBold; - else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) - qtweight = QFont::Bold; - - return qtweight; -} - -QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request) -{ - QFontDef fontDef; - fontDef.styleStrategy = request.styleStrategy; - - fontDef.hintingPreference = request.hintingPreference; - FcChar8 *value = 0; - if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) { - fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value)); - } - - double dpi; - if (FcPatternGetDouble(pattern, FC_DPI, 0, &dpi) != FcResultMatch) { - if (X11->display) - dpi = QX11Info::appDpiY(); - else - dpi = qt_defaultDpiY(); - } - - double size; - if (FcPatternGetDouble(pattern, FC_PIXEL_SIZE, 0, &size) == FcResultMatch) - fontDef.pixelSize = size; - else - fontDef.pixelSize = 12; - - fontDef.pointSize = qt_pointSize(fontDef.pixelSize, qRound(dpi)); - - /* ### - fontDef.styleHint - */ - - int weight; - if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight) != FcResultMatch) - weight = FC_WEIGHT_MEDIUM; - fontDef.weight = getFCWeight(weight); - - int slant; - if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant) != FcResultMatch) - slant = FC_SLANT_ROMAN; - fontDef.style = (slant == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - - - FcBool scalable; - if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = false; - if (scalable) { - fontDef.stretch = request.stretch; - fontDef.style = request.style; - } else { - int width; - if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width) == FcResultMatch) - fontDef.stretch = width; - else - fontDef.stretch = 100; - } - - int spacing; - if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing) == FcResultMatch) { - fontDef.fixedPitch = (spacing >= FC_MONO); - fontDef.ignorePitch = false; - } else { - fontDef.ignorePitch = true; - } - - return fontDef; -} - -static const char *specialLanguages[] = { - "en", // Common - "el", // Greek - "ru", // Cyrillic - "hy", // Armenian - "he", // Hebrew - "ar", // Arabic - "syr", // Syriac - "div", // Thaana - "hi", // Devanagari - "bn", // Bengali - "pa", // Gurmukhi - "gu", // Gujarati - "or", // Oriya - "ta", // Tamil - "te", // Telugu - "kn", // Kannada - "ml", // Malayalam - "si", // Sinhala - "th", // Thai - "lo", // Lao - "bo", // Tibetan - "my", // Myanmar - "ka", // Georgian - "ko", // Hangul - "", // Ogham - "", // Runic - "km", // Khmer - "" // N'Ko -}; -enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; - -static const ushort specialChars[] = { - 0, // English - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - 0, // Syriac - 0, // Thaana - 0, // Devanagari - 0, // Bengali - 0, // Gurmukhi - 0, // Gujarati - 0, // Oriya - 0, // Tamil - 0xc15, // Telugu - 0xc95, // Kannada - 0xd15, // Malayalam - 0xd9a, // Sinhala - 0, // Thai - 0, // Lao - 0, // Tibetan - 0x1000, // Myanmar - 0, // Georgian - 0, // Hangul - 0x1681, // Ogham - 0x16a0, // Runic - 0, // Khmer - 0x7ca // N'Ko -}; -enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; - -// this could become a list of all languages used for each writing -// system, instead of using the single most common language. -static const char *languageForWritingSystem[] = { - 0, // Any - "en", // Latin - "el", // Greek - "ru", // Cyrillic - "hy", // Armenian - "he", // Hebrew - "ar", // Arabic - "syr", // Syriac - "div", // Thaana - "hi", // Devanagari - "bn", // Bengali - "pa", // Gurmukhi - "gu", // Gujarati - "or", // Oriya - "ta", // Tamil - "te", // Telugu - "kn", // Kannada - "ml", // Malayalam - "si", // Sinhala - "th", // Thai - "lo", // Lao - "bo", // Tibetan - "my", // Myanmar - "ka", // Georgian - "km", // Khmer - "zh-cn", // SimplifiedChinese - "zh-tw", // TraditionalChinese - "ja", // Japanese - "ko", // Korean - "vi", // Vietnamese - 0, // Symbol - 0, // Ogham - 0, // Runic - 0 // N'Ko -}; -enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; - -// Unfortunately FontConfig doesn't know about some languages. We have to test these through the -// charset. The lists below contain the systems where we need to do this. -static const ushort sampleCharForWritingSystem[] = { - 0, // Any - 0, // Latin - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - 0, // Syriac - 0, // Thaana - 0, // Devanagari - 0, // Bengali - 0, // Gurmukhi - 0, // Gujarati - 0, // Oriya - 0, // Tamil - 0xc15, // Telugu - 0xc95, // Kannada - 0xd15, // Malayalam - 0xd9a, // Sinhala - 0, // Thai - 0, // Lao - 0, // Tibetan - 0x1000, // Myanmar - 0, // Georgian - 0, // Khmer - 0, // SimplifiedChinese - 0, // TraditionalChinese - 0, // Japanese - 0, // Korean - 0, // Vietnamese - 0, // Symbol - 0x1681, // Ogham - 0x16a0, // Runic - 0x7ca // N'Ko -}; -enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) }; - -// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no -// open type tables for is directly. Do this so we don't pick some strange -// pseudo unicode font -static const char *openType[] = { - 0, // Any - 0, // Latin - 0, // Greek - 0, // Cyrillic - 0, // Armenian - 0, // Hebrew - 0, // Arabic - "syrc", // Syriac - "thaa", // Thaana - "deva", // Devanagari - "beng", // Bengali - "guru", // Gurmukhi - "gurj", // Gujarati - "orya", // Oriya - "taml", // Tamil - "telu", // Telugu - "knda", // Kannada - "mlym", // Malayalam - "sinh", // Sinhala - 0, // Thai - 0, // Lao - "tibt", // Tibetan - "mymr", // Myanmar - 0, // Georgian - "khmr", // Khmer - 0, // SimplifiedChinese - 0, // TraditionalChinese - 0, // Japanese - 0, // Korean - 0, // Vietnamese - 0, // Symbol - 0, // Ogham - 0, // Runic - "nko " // N'Ko -}; -enum { OpenTypeCount = sizeof(openType) / sizeof(const char *) }; - - -static void loadFontConfig() -{ - Q_ASSERT_X(X11, "QFontDatabase", - "A QApplication object needs to be constructed before FontConfig is used."); - if (!X11->has_fontconfig) - return; - - Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialLanguageCount, - "QFontDatabase", "New scripts have been added."); - Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialCharCount, - "QFontDatabase", "New scripts have been added."); - Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == LanguageCount, - "QFontDatabase", "New writing systems have been added."); - Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == SampleCharCount, - "QFontDatabase", "New writing systems have been added."); - Q_ASSERT_X(int(QFontDatabase::WritingSystemsCount) == OpenTypeCount, - "QFontDatabase", "New writing systems have been added."); - - QFontDatabasePrivate *db = privateDb(); - FcFontSet *fonts; - - FcPattern *pattern = FcPatternCreate(); - FcDefaultSubstitute(pattern); - FcChar8 *lang = 0; - if (FcPatternGetString(pattern, FC_LANG, 0, &lang) == FcResultMatch) - db->systemLang = QString::fromUtf8((const char *) lang); - FcPatternDestroy(pattern); - - QString familyName; - FcChar8 *value = 0; - int weight_value; - int slant_value; - int spacing_value; - FcChar8 *file_value; - int index_value; - FcChar8 *foundry_value; - FcBool scalable; - - { - FcObjectSet *os = FcObjectSetCreate(); - FcPattern *pattern = FcPatternCreate(); - const char *properties [] = { - FC_FAMILY, FC_WEIGHT, FC_SLANT, - FC_SPACING, FC_FILE, FC_INDEX, - FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, - FC_WIDTH, -#if FC_VERSION >= 20297 - FC_CAPABILITY, -#endif - (const char *)0 - }; - const char **p = properties; - while (*p) { - FcObjectSetAdd(os, *p); - ++p; - } - fonts = FcFontList(0, pattern, os); - FcObjectSetDestroy(os); - FcPatternDestroy(pattern); - } - - for (int i = 0; i < fonts->nfont; i++) { - if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) - continue; - // capitalize(value); - familyName = QString::fromUtf8((const char *)value); - slant_value = FC_SLANT_ROMAN; - weight_value = FC_WEIGHT_MEDIUM; - spacing_value = FC_PROPORTIONAL; - file_value = 0; - index_value = 0; - scalable = FcTrue; - - if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) - slant_value = FC_SLANT_ROMAN; - if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) - weight_value = FC_WEIGHT_MEDIUM; - if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) - spacing_value = FC_PROPORTIONAL; - if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) - file_value = 0; - if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &index_value) != FcResultMatch) - index_value = 0; - if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = FcTrue; - if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) - foundry_value = 0; - QtFontFamily *family = db->family(familyName, true); - - FcLangSet *langset = 0; - FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); - if (res == FcResultMatch) { - for (int i = 1; i < LanguageCount; ++i) { - const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; - if (!lang) { - family->writingSystems[i] |= QtFontFamily::UnsupportedFT; - } else { - FcLangResult langRes = FcLangSetHasLang(langset, lang); - if (langRes != FcLangDifferentLang) - family->writingSystems[i] = QtFontFamily::Supported; - else - family->writingSystems[i] |= QtFontFamily::UnsupportedFT; - } - } - family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT; - family->ftWritingSystemCheck = true; - } else { - // we set Other to supported for symbol fonts. It makes no - // sense to merge these with other ones, as they are - // special in a way. - for (int i = 1; i < LanguageCount; ++i) - family->writingSystems[i] |= QtFontFamily::UnsupportedFT; - family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported; - } - - FcCharSet *cs = 0; - res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); - if (res == FcResultMatch) { - // some languages are not supported by FontConfig, we rather check the - // charset to detect these - for (int i = 1; i < SampleCharCount; ++i) { - if (!sampleCharForWritingSystem[i]) - continue; - if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) - family->writingSystems[i] = QtFontFamily::Supported; - } - } - -#if FC_VERSION >= 20297 - for (int j = 1; j < LanguageCount; ++j) { - if (family->writingSystems[j] == QtFontFamily::Supported && requiresOpenType(j) && openType[j]) { - FcChar8 *cap; - res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); - if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) - family->writingSystems[j] = QtFontFamily::UnsupportedFT; - } - } -#endif - - QByteArray file((const char *)file_value); - family->fontFilename = file; - family->fontFileIndex = index_value; - - QtFontStyle::Key styleKey; - styleKey.style = (slant_value == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant_value == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - styleKey.weight = getFCWeight(weight_value); - if (!scalable) { - int width = 100; - FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); - styleKey.stretch = width; - } - - QtFontFoundry *foundry - = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true); - QtFontStyle *style = foundry->style(styleKey, true); - - if (spacing_value < FC_MONO) - family->fixedPitch = false; - - QtFontSize *size; - if (scalable) { - style->smoothScalable = true; - size = style->pixelSize(SMOOTH_SCALABLE, true); - } else { - double pixel_size = 0; - FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); - size = style->pixelSize((int)pixel_size, true); - } - QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); - enc->pitch = (spacing_value >= FC_CHARCELL ? 'c' : - (spacing_value >= FC_MONO ? 'm' : 'p')); - } - - FcFontSetDestroy (fonts); - - struct FcDefaultFont { - const char *qtname; - const char *rawname; - bool fixed; - }; - const FcDefaultFont defaults[] = { - { "Serif", "serif", false }, - { "Sans Serif", "sans-serif", false }, - { "Monospace", "monospace", true }, - { 0, 0, false } - }; - const FcDefaultFont *f = defaults; - while (f->qtname) { - QtFontFamily *family = db->family(QLatin1String(f->qtname), true); - family->fixedPitch = f->fixed; - family->synthetic = true; - QtFontFoundry *foundry = family->foundry(QString(), true); - - // aliases only make sense for 'common', not for any of the specials - for (int i = 1; i < LanguageCount; ++i) { - if (requiresOpenType(i)) - family->writingSystems[i] = QtFontFamily::UnsupportedFT; - else - family->writingSystems[i] = QtFontFamily::Supported; - } - family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT; - - QtFontStyle::Key styleKey; - for (int i = 0; i < 4; ++i) { - styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic; - styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal; - QtFontStyle *style = foundry->style(styleKey, true); - style->smoothScalable = true; - QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true); - QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); - enc->pitch = (f->fixed ? 'm' : 'p'); - } - ++f; - } -} -#endif // QT_NO_FONTCONFIG - -static void initializeDb(); - -static void load(const QString &family = QString(), int script = -1, bool forceXLFD = false) -{ - if (X11->has_fontconfig && !forceXLFD) { - initializeDb(); - return; - } - -#ifdef QFONTDATABASE_DEBUG - QElapsedTimer t; - t.start(); -#endif - - if (family.isNull() && script == -1) { - loadXlfds(0, -1); - } else { - if (family.isNull()) { - // load all families in all writing systems that match \a script - for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { - if (scriptForWritingSystem[ws] != script) - continue; - for (int i = 0; i < numEncodings; ++i) { - if (writingSystems_for_xlfd_encoding[i][ws]) - loadXlfds(0, i); - } - } - } else { - QtFontFamily *f = privateDb()->family(family); - // could reduce this further with some more magic: - // would need to remember the encodings loaded for the family. - if (!f || !f->xlfdLoaded) - loadXlfds(family.toLatin1(), -1); - } - } - -#ifdef QFONTDATABASE_DEBUG - FD_DEBUG("QFontDatabase: load(%s, %d) took %d ms", - family.toLatin1().constData(), script, t.elapsed()); -#endif -} - -static void checkSymbolFont(QtFontFamily *family) -{ - if (!family || family->symbol_checked || family->fontFilename.isEmpty()) - return; -// qDebug() << "checking " << family->rawName; - family->symbol_checked = true; - - QFontEngine::FaceId id; - id.filename = family->fontFilename; - id.index = family->fontFileIndex; - QFreetypeFace *f = QFreetypeFace::getFace(id); - if (!f) { - qWarning("checkSymbolFonts: Couldn't open face %s (%s/%d)", - qPrintable(family->name), family->fontFilename.data(), family->fontFileIndex); - return; - } - for (int i = 0; i < f->face->num_charmaps; ++i) { - FT_CharMap cm = f->face->charmaps[i]; - if (cm->encoding == FT_ENCODING_ADOBE_CUSTOM - || cm->encoding == FT_ENCODING_MS_SYMBOL) { - for (int x = QFontDatabase::Latin; x < QFontDatabase::Other; ++x) - family->writingSystems[x] = QtFontFamily::Unsupported; - family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported; - break; - } - } - f->release(id); -} - -static void checkSymbolFonts(const QString &family = QString()) -{ -#ifndef QT_NO_FONTCONFIG - QFontDatabasePrivate *d = privateDb(); - - if (family.isEmpty()) { - for (int i = 0; i < d->count; ++i) - checkSymbolFont(d->families[i]); - } else { - checkSymbolFont(d->family(family)); - } -#endif -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt); - -static void initializeDb() -{ - QFontDatabasePrivate *db = privateDb(); - if (!db || db->count) - return; - - QElapsedTimer t; - t.start(); - -#ifndef QT_NO_FONTCONFIG - if (db->reregisterAppFonts) { - db->reregisterAppFonts = false; - for (int i = 0; i < db->applicationFonts.count(); ++i) - if (!db->applicationFonts.at(i).families.isEmpty()) { - registerFont(&db->applicationFonts[i]); - } - } - - loadFontConfig(); - FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", int(t.elapsed())); -#endif - - t.start(); - -#ifndef QT_NO_FONTCONFIG - for (int i = 0; i < db->count; i++) { - for (int j = 0; j < db->families[i]->count; ++j) { // each foundry - QtFontFoundry *foundry = db->families[i]->foundries[j]; - for (int k = 0; k < foundry->count; ++k) { - QtFontStyle *style = foundry->styles[k]; - if (style->key.style != QFont::StyleNormal) continue; - - QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE); - if (! size) continue; // should not happen - QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); - if (! enc) continue; // should not happen either - - QtFontStyle::Key key = style->key; - - // does this style have an italic equivalent? - key.style = QFont::StyleItalic; - QtFontStyle *equiv = foundry->style(key); - if (equiv) continue; - - // does this style have an oblique equivalent? - key.style = QFont::StyleOblique; - equiv = foundry->style(key); - if (equiv) continue; - - // let's fake one... - equiv = foundry->style(key, true); - equiv->smoothScalable = true; - - QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true); - QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true); - - // keep the same pitch - equiv_enc->pitch = enc->pitch; - } - } - } -#endif - - -#ifdef QFONTDATABASE_DEBUG -#ifndef QT_NO_FONTCONFIG - if (!X11->has_fontconfig) -#endif - // load everything at startup in debug mode. - loadXlfds(0, -1); - - // print the database - for (int f = 0; f < db->count; f++) { - QtFontFamily *family = db->families[f]; - FD_DEBUG("'%s' %s fixed=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""), - (family->fixedPitch ? "yes" : "no")); - for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { - QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i); - FD_DEBUG("\t%s: %s", QFontDatabase::writingSystemName(ws).toLatin1().constData(), - ((family->writingSystems[i] & QtFontFamily::Supported) ? "Supported" : - (family->writingSystems[i] & QtFontFamily::Unsupported) == QtFontFamily::Unsupported ? - "Unsupported" : "Unknown")); - } - - for (int fd = 0; fd < family->count; fd++) { - QtFontFoundry *foundry = family->foundries[fd]; - FD_DEBUG("\t\t'%s'", foundry->name.latin1()); - for (int s = 0; s < foundry->count; s++) { - QtFontStyle *style = foundry->styles[s]; - FD_DEBUG("\t\t\tstyle: style=%d weight=%d (%s)\n" - "\t\t\tstretch=%d (%s)", - style->key.style, style->key.weight, - style->weightName, style->key.stretch, - style->setwidthName ? style->setwidthName : "nil"); - if (style->smoothScalable) - FD_DEBUG("\t\t\t\tsmooth scalable"); - else if (style->bitmapScalable) - FD_DEBUG("\t\t\t\tbitmap scalable"); - if (style->pixelSizes) { - qDebug("\t\t\t\t%d pixel sizes", style->count); - for (int z = 0; z < style->count; ++z) { - QtFontSize *size = style->pixelSizes + z; - for (int e = 0; e < size->count; ++e) { - FD_DEBUG("\t\t\t\t size %5d pitch %c encoding %s", - size->pixelSize, - size->encodings[e].pitch, - xlfd_for_id(size->encodings[e].encoding)); - } - } - } - } - } - } -#endif // QFONTDATABASE_DEBUG -} - - -// -------------------------------------------------------------------------------------- -// font loader -// -------------------------------------------------------------------------------------- - -static const char *styleHint(const QFontDef &request) -{ - const char *stylehint = 0; - switch (request.styleHint) { - case QFont::SansSerif: - stylehint = "sans-serif"; - break; - case QFont::Serif: - stylehint = "serif"; - break; - case QFont::TypeWriter: - stylehint = "monospace"; - break; - default: - if (request.fixedPitch) - stylehint = "monospace"; - break; - } - return stylehint; -} - -#ifndef QT_NO_FONTCONFIG - -void qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontDef &request) -{ - int weight_value = FC_WEIGHT_BLACK; - if (request.weight == 0) - weight_value = FC_WEIGHT_MEDIUM; - else if (request.weight < (QFont::Light + QFont::Normal) / 2) - weight_value = FC_WEIGHT_LIGHT; - else if (request.weight < (QFont::Normal + QFont::DemiBold) / 2) - weight_value = FC_WEIGHT_MEDIUM; - else if (request.weight < (QFont::DemiBold + QFont::Bold) / 2) - weight_value = FC_WEIGHT_DEMIBOLD; - else if (request.weight < (QFont::Bold + QFont::Black) / 2) - weight_value = FC_WEIGHT_BOLD; - FcPatternDel(pattern, FC_WEIGHT); - FcPatternAddInteger(pattern, FC_WEIGHT, weight_value); - - int slant_value = FC_SLANT_ROMAN; - if (request.style == QFont::StyleItalic) - slant_value = FC_SLANT_ITALIC; - else if (request.style == QFont::StyleOblique) - slant_value = FC_SLANT_OBLIQUE; - FcPatternDel(pattern, FC_SLANT); - FcPatternAddInteger(pattern, FC_SLANT, slant_value); - - double size_value = qMax(qreal(1.), request.pixelSize); - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value); - - int stretch = request.stretch; - if (!stretch) - stretch = 100; - FcPatternDel(pattern, FC_WIDTH); - FcPatternAddInteger(pattern, FC_WIDTH, stretch); - - if (X11->display && QX11Info::appDepth(screen) <= 8) { - FcPatternDel(pattern, FC_ANTIALIAS); - // can't do antialiasing on 8bpp - FcPatternAddBool(pattern, FC_ANTIALIAS, false); - } else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) { - FcPatternDel(pattern, FC_ANTIALIAS); - FcPatternAddBool(pattern, FC_ANTIALIAS, - !(request.styleStrategy & QFont::NoAntialias)); - } - - if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { - Q_ASSERT(script < QUnicodeTables::ScriptCount); - FcLangSet *ls = FcLangSetCreate(); - FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); - FcPatternDel(pattern, FC_LANG); - FcPatternAddLangSet(pattern, FC_LANG, ls); - FcLangSetDestroy(ls); - } -} - -static bool preferScalable(const QFontDef &request) -{ - return request.styleStrategy & (QFont::PreferOutline|QFont::ForceOutline|QFont::PreferQuality|QFont::PreferAntialias); -} - - -static FcPattern *getFcPattern(const QFontPrivate *fp, int script, const QFontDef &request) -{ - if (!X11->has_fontconfig) - return 0; - - FcPattern *pattern = FcPatternCreate(); - if (!pattern) - return 0; - - FcValue value; - value.type = FcTypeString; - - QtFontDesc desc; - QStringList families_and_foundries = familyList(request); - for (int i = 0; i < families_and_foundries.size(); ++i) { - QString family, foundry; - parseFontName(families_and_foundries.at(i), foundry, family); - if (!family.isEmpty()) { - QByteArray cs = family.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAdd(pattern, FC_FAMILY, value, FcTrue); - } - if (i == 0) { - QT_PREPEND_NAMESPACE(match)(script, request, family, foundry, -1, &desc); - if (!foundry.isEmpty()) { - QByteArray cs = foundry.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FOUNDRY, value, FcTrue); - } - } - } - - const char *stylehint = styleHint(request); - if (stylehint) { - value.u.s = (const FcChar8 *)stylehint; - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - } - - if (!request.ignorePitch) { - char pitch_value = FC_PROPORTIONAL; - if (request.fixedPitch || (desc.family && desc.family->fixedPitch)) - pitch_value = FC_MONO; - FcPatternAddInteger(pattern, FC_SPACING, pitch_value); - } - FcPatternAddBool(pattern, FC_OUTLINE, !(request.styleStrategy & QFont::PreferBitmap)); - if (preferScalable(request) || (desc.style && desc.style->smoothScalable)) - FcPatternAddBool(pattern, FC_SCALABLE, true); - - qt_addPatternProps(pattern, fp->screen, script, request); - - FcDefaultSubstitute(pattern); - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcConfigSubstitute(0, pattern, FcMatchFont); - - // these should only get added to the pattern _after_ substitution - // append the default fallback font for the specified script - extern QString qt_fallback_font_family(int); - QString fallback = qt_fallback_font_family(script); - if (!fallback.isEmpty()) { - QByteArray cs = fallback.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - } - - // add the default family - QString defaultFamily = QApplication::font().family(); - QByteArray cs = defaultFamily.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - - // add QFont::defaultFamily() to the list, for compatibility with - // previous versions - defaultFamily = QApplication::font().defaultFamily(); - cs = defaultFamily.toUtf8(); - value.u.s = (const FcChar8 *)cs.data(); - FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); - - return pattern; -} - - -static void FcFontSetRemove(FcFontSet *fs, int at) -{ - Q_ASSERT(at < fs->nfont); - FcPatternDestroy(fs->fonts[at]); - int len = (--fs->nfont - at) * sizeof(FcPattern *);; - if (len > 0) - memmove(fs->fonts + at, fs->fonts + at + 1, len); -} - -static QFontEngine *tryPatternLoad(FcPattern *p, int screen, - const QFontDef &request, int script, FcPattern **matchedPattern = 0) -{ -#ifdef FONT_MATCH_DEBUG - FcChar8 *fam; - FcPatternGetString(p, FC_FAMILY, 0, &fam); - FM_DEBUG("==== trying %s\n", fam); -#endif - FM_DEBUG("passes charset test\n"); - FcPattern *pattern = FcPatternDuplicate(p); - // add properties back in as the font selected from the - // list doesn't contain them. - qt_addPatternProps(pattern, screen, script, request); - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - FcResult res; - FcPattern *match = FcFontMatch(0, pattern, &res); - - if (matchedPattern) - *matchedPattern = 0; - - QFontEngineX11FT *engine = 0; - if (!match) // probably no fonts available. - goto done; - - if (matchedPattern) - *matchedPattern = FcPatternDuplicate(match); - - if (script != QUnicodeTables::Common) { - // skip font if it doesn't support the language we want - if (specialChars[script]) { - // need to check the charset, as the langset doesn't work for these scripts - FcCharSet *cs; - if (FcPatternGetCharSet(match, FC_CHARSET, 0, &cs) != FcResultMatch) - goto done; - if (!FcCharSetHasChar(cs, specialChars[script])) - goto done; - } else if (*specialLanguages[script] != '\0'){ - FcLangSet *langSet = 0; - if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch) - goto done; - if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual) - goto done; - } - } - - // enforce non-antialiasing if requested. the ft font engine looks at this property. - if (request.styleStrategy & QFont::NoAntialias) { - FcPatternDel(match, FC_ANTIALIAS); - FcPatternAddBool(match, FC_ANTIALIAS, false); - } - - engine = new QFontEngineX11FT(match, qt_FcPatternToQFontDef(match, request), screen); - if (engine->invalid()) { - FM_DEBUG(" --> invalid!\n"); - delete engine; - engine = 0; - } else if (scriptRequiresOpenType(script)) { - HB_Face hbFace = engine->harfbuzzFace(); - if (!hbFace || !hbFace->supported_scripts[script]) { - FM_DEBUG(" OpenType support missing for script\n"); - delete engine; - engine = 0; - } - } -done: - FcPatternDestroy(pattern); - if (!engine && matchedPattern && *matchedPattern) { - FcPatternDestroy(*matchedPattern); - *matchedPattern = 0; - } - return engine; -} - -FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request) -{ - FcResult result; - FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result); -#ifdef FONT_MATCH_DEBUG - FM_DEBUG("first font in fontset:\n"); - FcPatternPrint(fs->fonts[0]); -#endif - - FcBool forceScalable = request.styleStrategy & QFont::ForceOutline; - - // remove fonts if they are not scalable (and should be) - if (forceScalable && fs) { - for (int i = 0; i < fs->nfont; ++i) { - FcPattern *font = fs->fonts[i]; - FcResult res; - FcBool scalable; - res = FcPatternGetBool(font, FC_SCALABLE, 0, &scalable); - if (res != FcResultMatch || !scalable) { - FcFontSetRemove(fs, i); -#ifdef FONT_MATCH_DEBUG - FM_DEBUG("removing pattern:"); - FcPatternPrint(font); -#endif - --i; // go back one - } - } - } - - FM_DEBUG("final pattern contains %d fonts\n", fs->nfont); - - return fs; -} - -static QFontEngine *loadFc(const QFontPrivate *fp, int script, const QFontDef &request) -{ - FM_DEBUG("===================== loadFc: script=%d family='%s'\n", script, request.family.toLatin1().data()); - FcPattern *pattern = getFcPattern(fp, script, request); - -#ifdef FONT_MATCH_DEBUG - FM_DEBUG("\n\nfinal FcPattern contains:\n"); - FcPatternPrint(pattern); -#endif - - QFontEngine *fe = 0; - FcPattern *matchedPattern = 0; - fe = tryPatternLoad(pattern, fp->screen, request, script, &matchedPattern); - if (!fe) { - FcFontSet *fs = qt_fontSetForPattern(pattern, request); - - if (fs) { - for (int i = 0; !fe && i < fs->nfont; ++i) - fe = tryPatternLoad(fs->fonts[i], fp->screen, request, script, &matchedPattern); - FcFontSetDestroy(fs); - } - FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)"); - } - if (fe - && script == QUnicodeTables::Common - && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) { - fe = new QFontEngineMultiFT(fe, matchedPattern, pattern, fp->screen, request); - } else { - FcPatternDestroy(pattern); - if (matchedPattern) - FcPatternDestroy(matchedPattern); - } - return fe; -} - -static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count) -{ -#if FC_VERSION < 20402 - Q_UNUSED(data) - return FcFreeTypeQuery(file, id, blanks, count); -#else - if (data.isEmpty()) - return FcFreeTypeQuery(file, id, blanks, count); - - extern FT_Library qt_getFreetype(); - FT_Library lib = qt_getFreetype(); - - FcPattern *pattern = 0; - - FT_Face face; - if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { - *count = face->num_faces; - - pattern = FcFreeTypeQueryFace(face, file, id, blanks); - - FT_Done_Face(face); - } - - return pattern; -#endif -} -#endif // QT_NO_FONTCONFIG - -static QFontEngine *loadRaw(const QFontPrivate *fp, const QFontDef &request) -{ - Q_ASSERT(fp && fp->rawMode); - - QByteArray xlfd = request.family.toLatin1(); - FM_DEBUG("Loading XLFD (rawmode) '%s'", xlfd.data()); - - QFontEngine *fe; - XFontStruct *xfs; - if (!(xfs = XLoadQueryFont(QX11Info::display(), xlfd.data()))) - if (!(xfs = XLoadQueryFont(QX11Info::display(), "fixed"))) - return 0; - - fe = new QFontEngineXLFD(xfs, xlfd, 0); - if (! qt_fillFontDef(xfs, &fe->fontDef, fp->dpi, 0) && - ! qt_fillFontDef(xlfd, &fe->fontDef, fp->dpi, 0)) - fe->fontDef = QFontDef(); - return fe; -} - -QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &request, int force_encoding_id) -{ - QMutexLocker locker(fontDatabaseMutex()); - - QtFontDesc desc; - FM_DEBUG() << "---> loadXlfd: request is" << request.family; - QStringList families_and_foundries = familyList(request); - const char *stylehint = styleHint(request); - if (stylehint) - families_and_foundries << QString::fromLatin1(stylehint); - families_and_foundries << QString(); - FM_DEBUG() << "loadXlfd: list is" << families_and_foundries; - for (int i = 0; i < families_and_foundries.size(); ++i) { - QString family, foundry; - QT_PREPEND_NAMESPACE(parseFontName)(families_and_foundries.at(i), foundry, family); - FM_DEBUG("loadXlfd: >>>>>>>>>>>>>>trying to match '%s' encoding=%d", family.toLatin1().data(), force_encoding_id); - QT_PREPEND_NAMESPACE(match)(script, request, family, foundry, force_encoding_id, &desc, QList<int>(), true); - if (desc.family) - break; - } - - QFontEngine *fe = 0; - if (force_encoding_id != -1 - || (request.styleStrategy & QFont::NoFontMerging) - || (desc.family && desc.family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) { - if (desc.family) { - int px = desc.size->pixelSize; - if (desc.style->smoothScalable && px == SMOOTH_SCALABLE) - px = request.pixelSize; - else if (desc.style->bitmapScalable && px == 0) - px = request.pixelSize; - - QByteArray xlfd("-"); - xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1(); - xlfd += '-'; - xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1(); - xlfd += '-'; - xlfd += desc.style->weightName ? desc.style->weightName : "*"; - xlfd += '-'; - xlfd += (desc.style->key.style == QFont::StyleItalic - ? 'i' - : (desc.style->key.style == QFont::StyleOblique ? 'o' : 'r')); - xlfd += '-'; - xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*"; - // ### handle add-style - xlfd += "-*-"; - xlfd += QByteArray::number(px); - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->xpoint); - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->xres); - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->yres); - xlfd += '-'; - xlfd += desc.encoding->pitch; - xlfd += '-'; - xlfd += QByteArray::number(desc.encoding->avgwidth); - xlfd += '-'; - xlfd += xlfd_for_id(desc.encoding->encoding); - - FM_DEBUG(" using XLFD: %s\n", xlfd.data()); - - const int mib = xlfd_encoding[desc.encoding->encoding].mib; - XFontStruct *xfs; - if ((xfs = XLoadQueryFont(QX11Info::display(), xlfd))) { - fe = new QFontEngineXLFD(xfs, xlfd, mib); - const int dpi = QX11Info::appDpiY(); - if (!qt_fillFontDef(xfs, &fe->fontDef, dpi, &desc) - && !qt_fillFontDef(xlfd, &fe->fontDef, dpi, &desc)) { - initFontDef(desc, request, &fe->fontDef); - } - } - } - if (!fe) { - fe = new QFontEngineBox(request.pixelSize); - fe->fontDef = QFontDef(); - } - } else { - QList<int> encodings; - if (desc.encoding) { - if (desc.encoding->encoding >= 0) - encodings.append(int(desc.encoding->encoding)); - } - - if (desc.size) { - // append all other encodings for the matched font - for (int i = 0; i < desc.size->count; ++i) { - QtFontEncoding *e = desc.size->encodings + i; - if (e == desc.encoding || e->encoding < 0) - continue; - encodings.append(int(e->encoding)); - } - } - // fill in the missing encodings - const XlfdEncoding *enc = xlfd_encoding; - for (; enc->name; ++enc) { - if (!encodings.contains(enc->id) && enc->id >= 0) { - encodings.append(enc->id); - } - } - -#if defined(FONT_MATCH_DEBUG) - FM_DEBUG(" using MultiXLFD, encodings:"); - for (int i = 0; i < encodings.size(); ++i) { - const int id = encodings.at(i); - FM_DEBUG(" %2d: %s", xlfd_encoding[id].id, xlfd_encoding[id].name); - } -#endif - - fe = new QFontEngineMultiXLFD(request, encodings, screen); - } - return fe; -} - -#if (defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6)) && defined(Q_CC_GNU) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) -#define NEEDS_GCC_BUG_WORKAROUND -#endif - -#ifdef NEEDS_GCC_BUG_WORKAROUND -static inline void gccBugWorkaround(const QFontDef &req) -{ - char buffer[8]; - snprintf(buffer, 8, "%f", req.pixelSize); -} -#endif - -/*! \internal - Loads a QFontEngine for the specified \a script that matches the - QFontDef \e request member variable. -*/ -void QFontDatabase::load(const QFontPrivate *d, int script) -{ - Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); - - // normalize the request to get better caching - QFontDef req = d->request; - if (req.pixelSize <= 0) - req.pixelSize = qFloor(qt_pixelSize(req.pointSize, d->dpi) * 100.0 + 0.5) * 0.01; - if (req.pixelSize < 1) - req.pixelSize = 1; - -#ifdef NEEDS_GCC_BUG_WORKAROUND - // req.pixelSize ends up with a bogus value unless this workaround is called - gccBugWorkaround(req); -#endif - - if (req.weight == 0) - req.weight = QFont::Normal; - if (req.stretch == 0) - req.stretch = 100; - - QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen); - if (!d->engineData) - getEngineData(d, key); - - // the cached engineData could have already loaded the engine we want - if (d->engineData->engines[script]) - return; - - // set it to the actual pointsize, so QFontInfo will do the right thing - if (req.pointSize < 0) - req.pointSize = qt_pointSize(req.pixelSize, d->dpi); - - - QFontEngine *fe = QFontCache::instance()->findEngine(key); - - if (!fe) { - QMutexLocker locker(fontDatabaseMutex()); - if (!privateDb()->count) - initializeDb(); - - const bool mainThread = (qApp->thread() == QThread::currentThread()); - if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { - fe = new QTestFontEngine(req.pixelSize); - fe->fontDef = req; - } else if (d->rawMode) { - if (mainThread) - fe = loadRaw(d, req); -#ifndef QT_NO_FONTCONFIG - } else if (X11->has_fontconfig) { - fe = loadFc(d, script, req); -#endif - } else if (mainThread && qt_is_gui_used) { - fe = loadXlfd(d->screen, script, req); - } - if (!fe) { - fe = new QFontEngineBox(req.pixelSize); - fe->fontDef = QFontDef(); - } - } - if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) { - for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { - if (!d->engineData->engines[i]) { - d->engineData->engines[i] = fe; - fe->ref.ref(); - } - } - } else { - d->engineData->engines[script] = fe; - fe->ref.ref(); - } - QFontCache::instance()->insertEngine(key, fe); -} - -static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) -{ -#if defined(QT_NO_FONTCONFIG) - return; -#else - if (!X11->has_fontconfig) - return; - - FcConfig *config = FcConfigGetCurrent(); - if (!config) - return; - - FcFontSet *set = FcConfigGetFonts(config, FcSetApplication); - if (!set) { - FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-existent"); - set = FcConfigGetFonts(config, FcSetApplication); // try again - if (!set) - return; - } - - QString fileNameForQuery = fnt->fileName; -#if FC_VERSION < 20402 - QTemporaryFile tmp; - - if (!fnt->data.isEmpty()) { - if (!tmp.open()) - return; - tmp.write(fnt->data); - tmp.flush(); - fileNameForQuery = tmp.fileName(); - } -#endif - - int id = 0; - FcBlanks *blanks = FcConfigGetBlanks(0); - int count = 0; - - QStringList families; - QFontDatabasePrivate *db = privateDb(); - - FcPattern *pattern = 0; - do { - pattern = queryFont((const FcChar8 *)QFile::encodeName(fileNameForQuery).constData(), - fnt->data, id, blanks, &count); - if (!pattern) - return; - - FcPatternDel(pattern, FC_FILE); - FcPatternAddString(pattern, FC_FILE, (const FcChar8 *)fnt->fileName.toUtf8().constData()); - - FcChar8 *fam = 0, *familylang = 0; - int i, n = 0; - for (i = 0; ; i++) { - if (FcPatternGetString(pattern, FC_FAMILYLANG, i, &familylang) != FcResultMatch) - break; - QString familyLang = QString::fromUtf8((const char *) familylang); - if (familyLang.compare(db->systemLang, Qt::CaseInsensitive) == 0) { - n = i; - break; - } - } - - if (FcPatternGetString(pattern, FC_FAMILY, n, &fam) == FcResultMatch) { - QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); - families << family; - } - - if (!FcFontSetAdd(set, pattern)) - return; - - ++id; - } while (pattern && id < count); - - fnt->families = families; -#endif -} - -bool QFontDatabase::removeApplicationFont(int handle) -{ -#if defined(QT_NO_FONTCONFIG) - return false; -#else - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (handle < 0 || handle >= db->applicationFonts.count()) - return false; - - FcConfigAppFontClear(0); - - db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); - - db->reregisterAppFonts = true; - db->invalidate(); - return true; -#endif -} - -bool QFontDatabase::removeAllApplicationFonts() -{ -#if defined(QT_NO_FONTCONFIG) - return false; -#else - QMutexLocker locker(fontDatabaseMutex()); - - QFontDatabasePrivate *db = privateDb(); - if (db->applicationFonts.isEmpty()) - return false; - - FcConfigAppFontClear(0); - db->applicationFonts.clear(); - db->invalidate(); - return true; -#endif -} - -bool QFontDatabase::supportsThreadedFontRendering() -{ -#if defined(QT_NO_FONTCONFIG) - return false; -#else - return X11->has_fontconfig; -#endif -} - -QString QFontDatabase::resolveFontFamilyAlias(const QString &family) -{ -#if defined(QT_NO_FONTCONFIG) - return family; -#else - FcPattern *pattern = FcPatternCreate(); - if (!pattern) - return family; - - FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) family.toUtf8().data()); - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - FcChar8 *familyAfterSubstitution; - FcPatternGetString(pattern, FC_FAMILY, 0, &familyAfterSubstitution); - QString resolved = QString::fromUtf8((const char *) familyAfterSubstitution); - FcPatternDestroy(pattern); - - return resolved; -#endif -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm deleted file mode 100644 index cbf51e6ec5..0000000000 --- a/src/gui/text/qfontengine_coretext.mm +++ /dev/null @@ -1,880 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_coretext_p.h" - -#include <QtCore/qendian.h> -#include <QtCore/qsettings.h> - -#include <private/qimage_p.h> - -#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -QT_BEGIN_NAMESPACE - -static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90); - -static void loadAdvancesForGlyphs(CTFontRef ctfont, - QVarLengthArray<CGGlyph> &cgGlyphs, - QGlyphLayout *glyphs, int len, - QTextEngine::ShaperFlags flags, - const QFontDef &fontDef) -{ - Q_UNUSED(flags); - QVarLengthArray<CGSize> advances(len); - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, cgGlyphs.data(), advances.data(), len); - - for (int i = 0; i < len; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - continue; - glyphs->advances_x[i] = QFixed::fromReal(advances[i].width); - glyphs->advances_y[i] = QFixed::fromReal(advances[i].height); - } - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < len; ++i) { - glyphs->advances_x[i] = glyphs->advances_x[i].round(); - glyphs->advances_y[i] = glyphs->advances_y[i].round(); - } - } -} - -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - CTFontSymbolicTraits symbolicTraits = 0; - if (fontDef.weight >= QFont::Bold) - symbolicTraits |= kCTFontBoldTrait; - switch (fontDef.style) { - case QFont::StyleNormal: - break; - case QFont::StyleItalic: - case QFont::StyleOblique: - symbolicTraits |= kCTFontItalicTrait; - break; - } - - transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - } - - QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize); - QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, &transform); - ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, &transform, symbolicTraits, symbolicTraits); - - // CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does - // not exist for the given font. (for example italic) - if (ctfont == 0) { - ctfont = baseFont; - CFRetain(ctfont); - } - init(kerning); -} - -QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(CGFontRef cgFontRef, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - - transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - } - - ctfont = CTFontCreateWithGraphicsFont(cgFontRef, fontDef.pixelSize, &transform, NULL); - init(kerning); -} - -QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti() -{ - CFRelease(ctfont); -} - -void QCoreTextFontEngineMulti::init(bool kerning) -{ - Q_ASSERT(ctfont != NULL); - attributeDict = CFDictionaryCreateMutable(0, 2, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(attributeDict, NSFontAttributeName, ctfont); - if (!kerning) { - float zero = 0.0; - QCFType<CFNumberRef> noKern = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero); - CFDictionaryAddValue(attributeDict, kCTKernAttributeName, noKern); - } - - QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef); - fe->ref.ref(); - engines.append(fe); -} - -uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef font) const -{ - for (int i = 0; i < engines.count(); ++i) { - if (CFEqual(engineAt(i)->ctfont, font)) - return i; - } - - QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this); - QCoreTextFontEngine *fe = new QCoreTextFontEngine(font, fontDef); - fe->ref.ref(); - that->engines.append(fe); - return engines.count() - 1; -} - -bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *, - QScriptItem *si) const -{ - QCFType<CFStringRef> cfstring = CFStringCreateWithCharactersNoCopy(0, - reinterpret_cast<const UniChar *>(str), - len, kCFAllocatorNull); - QCFType<CFAttributedStringRef> attributedString = CFAttributedStringCreate(0, cfstring, attributeDict); - QCFType<CTTypesetterRef> typeSetter; - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - if (flags & QTextEngine::RightToLeft) { - const void *optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel }; - const short rtlForcedEmbeddingLevelValue = 1; - const void *rtlOptionValues[] = { CFNumberCreate(kCFAllocatorDefault, kCFNumberShortType, &rtlForcedEmbeddingLevelValue) }; - QCFType<CFDictionaryRef> options = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, 1, - &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - typeSetter = CTTypesetterCreateWithAttributedStringAndOptions(attributedString, options); - } else -#else - Q_UNUSED(flags); -#endif - typeSetter = CTTypesetterCreateWithAttributedString(attributedString); - - CFRange range = {0, 0}; - QCFType<CTLineRef> line = CTTypesetterCreateLine(typeSetter, range); - CFArrayRef array = CTLineGetGlyphRuns(line); - uint arraySize = CFArrayGetCount(array); - glyph_t *outGlyphs = glyphs->glyphs; - HB_GlyphAttributes *outAttributes = glyphs->attributes; - QFixed *outAdvances_x = glyphs->advances_x; - QFixed *outAdvances_y = glyphs->advances_y; - glyph_t *initialGlyph = outGlyphs; - - if (arraySize == 0) { - // CoreText failed to shape the text we gave it, so we assume one glyph - // per character and build a list of invalid glyphs with zero advance - *nglyphs = len; - for (int i = 0; i < len; ++i) { - outGlyphs[i] = 0; - if (logClusters) - logClusters[i] = i; - outAdvances_x[i] = QFixed(); - outAdvances_y[i] = QFixed(); - outAttributes[i].clusterStart = true; - } - return true; - } - - const bool rtl = (CTRunGetStatus(static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, 0))) & kCTRunStatusRightToLeft); - - bool outOBounds = false; - for (uint i = 0; i < arraySize; ++i) { - CTRunRef run = static_cast<CTRunRef>(CFArrayGetValueAtIndex(array, rtl ? (arraySize - 1 - i) : i)); - CFIndex glyphCount = CTRunGetGlyphCount(run); - if (glyphCount == 0) - continue; - - Q_ASSERT((CTRunGetStatus(run) & kCTRunStatusRightToLeft) == rtl); - CFRange stringRange = CTRunGetStringRange(run); - int prepend = 0; -#if MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5 - UniChar beginGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location); - QChar dir = QChar::direction(beginGlyph); - bool beginWithOverride = dir == QChar::DirLRO || dir == QChar::DirRLO || dir == QChar::DirLRE || dir == QChar::DirRLE; - if (beginWithOverride) { - logClusters[stringRange.location] = 0; - outGlyphs[0] = 0xFFFF; - outAdvances_x[0] = 0; - outAdvances_y[0] = 0; - outAttributes[0].clusterStart = true; - outAttributes[0].dontPrint = true; - outGlyphs++; - outAdvances_x++; - outAdvances_y++; - outAttributes++; - prepend = 1; - } -#endif - UniChar endGlyph = CFStringGetCharacterAtIndex(cfstring, stringRange.location + stringRange.length - 1); - bool endWithPDF = QChar::direction(endGlyph) == QChar::DirPDF; - if (endWithPDF) - glyphCount++; - - if (!outOBounds && outGlyphs + glyphCount - initialGlyph > *nglyphs) { - outOBounds = true; - } - if (!outOBounds) { - CFDictionaryRef runAttribs = CTRunGetAttributes(run); - //NSLog(@"Dictionary %@", runAttribs); - if (!runAttribs) - runAttribs = attributeDict; - CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName)); - uint fontIndex = fontIndexForFont(runFont); - const QFontEngine *engine = engineAt(fontIndex); - fontIndex <<= 24; - si->ascent = qMax(engine->ascent(), si->ascent); - si->descent = qMax(engine->descent(), si->descent); - si->leading = qMax(engine->leading(), si->leading); - //NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont)); - if (endWithPDF) - glyphCount--; - - QVarLengthArray<CGGlyph, 512> cgglyphs(0); - const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run); - if (!tmpGlyphs) { - cgglyphs.resize(glyphCount); - CTRunGetGlyphs(run, range, cgglyphs.data()); - tmpGlyphs = cgglyphs.constData(); - } - QVarLengthArray<CGPoint, 512> cgpoints(0); - const CGPoint *tmpPoints = CTRunGetPositionsPtr(run); - if (!tmpPoints) { - cgpoints.resize(glyphCount); - CTRunGetPositions(run, range, cgpoints.data()); - tmpPoints = cgpoints.constData(); - } - - const int rtlOffset = rtl ? (glyphCount - 1) : 0; - const int rtlSign = rtl ? -1 : 1; - - if (logClusters) { - CFRange stringRange = CTRunGetStringRange(run); - QVarLengthArray<CFIndex, 512> stringIndices(0); - const CFIndex *tmpIndices = CTRunGetStringIndicesPtr(run); - if (!tmpIndices) { - stringIndices.resize(glyphCount); - CTRunGetStringIndices(run, range, stringIndices.data()); - tmpIndices = stringIndices.constData(); - } - - const int firstGlyphIndex = outGlyphs - initialGlyph; - outAttributes[0].clusterStart = true; - - CFIndex k = 0; - CFIndex i = 0; - for (i = stringRange.location + prepend; - (i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) { - if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location + prepend) { - logClusters[i] = k + firstGlyphIndex; - outAttributes[k].clusterStart = true; - ++k; - } else { - logClusters[i] = k + firstGlyphIndex - 1; - } - } - // in case of a ligature at the end, fill the remaining logcluster entries - for (;i < stringRange.location + stringRange.length; i++) { - logClusters[i] = k + firstGlyphIndex - 1; - } - } - for (CFIndex i = 0; i < glyphCount - 1; ++i) { - int idx = rtlOffset + rtlSign * i; - outGlyphs[idx] = tmpGlyphs[i] | fontIndex; - outAdvances_x[idx] = QFixed::fromReal(tmpPoints[i + 1].x - tmpPoints[i].x); - // Use negative y advance for flipped coordinate system - outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i].y - tmpPoints[i + 1].y); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - outAdvances_x[idx] = outAdvances_x[idx].round(); - outAdvances_y[idx] = outAdvances_y[idx].round(); - } - } - CGSize lastGlyphAdvance; - CTFontGetAdvancesForGlyphs(runFont, kCTFontHorizontalOrientation, tmpGlyphs + glyphCount - 1, &lastGlyphAdvance, 1); - - outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex; - outAdvances_x[rtl ? 0 : (glyphCount - 1)] = - (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(lastGlyphAdvance.width).round() - : QFixed::fromReal(lastGlyphAdvance.width); - - if (endWithPDF) { - logClusters[stringRange.location + stringRange.length - 1] = glyphCount + prepend; - outGlyphs[glyphCount] = 0xFFFF; - outAdvances_x[glyphCount] = 0; - outAdvances_y[glyphCount] = 0; - outAttributes[glyphCount].clusterStart = true; - outAttributes[glyphCount].dontPrint = true; - glyphCount++; - } - } - outGlyphs += glyphCount; - outAttributes += glyphCount; - outAdvances_x += glyphCount; - outAdvances_y += glyphCount; - } - *nglyphs = (outGlyphs - initialGlyph); - return !outOBounds; -} - -bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - *nglyphs = len; - QCFType<CFStringRef> cfstring; - - QVarLengthArray<CGGlyph> cgGlyphs(len); - CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); - - for (int i = 0; i < len; ++i) { - if (cgGlyphs[i]) { - glyphs->glyphs[i] = cgGlyphs[i]; - } else { - if (!cfstring) - cfstring = CFStringCreateWithCharactersNoCopy(0, reinterpret_cast<const UniChar *>(str), len, kCFAllocatorNull); - QCFType<CTFontRef> substituteFont = CTFontCreateForString(ctfont, cfstring, CFRangeMake(i, 1)); - CGGlyph substituteGlyph = 0; - CTFontGetGlyphsForCharacters(substituteFont, (const UniChar*)str + i, &substituteGlyph, 1); - if (substituteGlyph) { - const uint fontIndex = (fontIndexForFont(substituteFont) << 24); - glyphs->glyphs[i] = substituteGlyph | fontIndex; - if (!(flags & QTextEngine::GlyphIndicesOnly)) { - CGSize advance; - CTFontGetAdvancesForGlyphs(substituteFont, kCTFontHorizontalOrientation, &substituteGlyph, &advance, 1); - glyphs->advances_x[i] = QFixed::fromReal(advance.width); - glyphs->advances_y[i] = QFixed::fromReal(advance.height); - } - } - } - } - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef); - return true; -} - -void QCoreTextFontEngineMulti::loadEngine(int) -{ - // Do nothing - Q_ASSERT(false); -} - -extern int qt_antialiasing_threshold; // from qapplication.cpp - -static inline CGAffineTransform transformFromFontDef(const QFontDef &fontDef) -{ - CGAffineTransform transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - return transform; -} - -QCoreTextFontEngine::QCoreTextFontEngine(CTFontRef font, const QFontDef &def) -{ - fontDef = def; - transform = transformFromFontDef(fontDef); - ctfont = font; - CFRetain(ctfont); - cgFont = CTFontCopyGraphicsFont(font, NULL); - init(); -} - -QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def) -{ - fontDef = def; - transform = transformFromFontDef(fontDef); - cgFont = font; - // Keep reference count balanced - CFRetain(cgFont); - ctfont = CTFontCreateWithGraphicsFont(font, fontDef.pixelSize, &transform, NULL); - init(); -} - -QCoreTextFontEngine::~QCoreTextFontEngine() -{ - CFRelease(cgFont); - CFRelease(ctfont); -} - -extern QFont::Weight weightFromInteger(int weight); // qfontdatabase.cpp - -int getTraitValue(CFDictionaryRef allTraits, CFStringRef trait) -{ - if (CFDictionaryContainsKey(allTraits, trait)) { - CFNumberRef traitNum = (CFNumberRef) CFDictionaryGetValue(allTraits, trait); - float v = 0; - CFNumberGetValue(traitNum, kCFNumberFloatType, &v); - // the value we get from CFNumberRef is from -1.0 to 1.0 - int value = v * 500 + 500; - return value; - } - - return 0; -} - -void QCoreTextFontEngine::init() -{ - Q_ASSERT(ctfont != NULL); - Q_ASSERT(cgFont != NULL); - - QCFString family = CTFontCopyFamilyName(ctfont); - fontDef.family = family; - - synthesisFlags = 0; - CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(ctfont); - if (traits & kCTFontItalicTrait) - fontDef.style = QFont::StyleItalic; - - CFDictionaryRef allTraits = CTFontCopyTraits(ctfont); - fontDef.weight = weightFromInteger(getTraitValue(allTraits, kCTFontWeightTrait)); - int slant = getTraitValue(allTraits, kCTFontSlantTrait); - if (slant > 500 && !(traits & kCTFontItalicTrait)) - fontDef.style = QFont::StyleOblique; - CFRelease(allTraits); - - if (fontDef.weight >= QFont::Bold && !(traits & kCTFontBoldTrait)) - synthesisFlags |= SynthesizedBold; - // XXX: we probably don't need to synthesis italic for oblique font - if (fontDef.style != QFont::StyleNormal && !(traits & kCTFontItalicTrait)) - synthesisFlags |= SynthesizedItalic; - - avgCharWidth = 0; - QByteArray os2Table = getSfntTable(MAKE_TAG('O', 'S', '/', '2')); - unsigned emSize = CTFontGetUnitsPerEm(ctfont); - if (os2Table.size() >= 10) { - fsType = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 8)); - // qAbs is a workaround for weird fonts like Lucida Grande - qint16 width = qAbs(qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(os2Table.constData() + 2))); - avgCharWidth = QFixed::fromReal(width * fontDef.pixelSize / emSize); - } else - avgCharWidth = QFontEngine::averageCharWidth(); - - ctMaxCharWidth = ctMinLeftBearing = ctMinRightBearing = 0; - QByteArray hheaTable = getSfntTable(MAKE_TAG('h', 'h', 'e', 'a')); - if (hheaTable.size() >= 16) { - quint16 width = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 10)); - ctMaxCharWidth = width * fontDef.pixelSize / emSize; - qint16 bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 12)); - ctMinLeftBearing = bearing * fontDef.pixelSize / emSize; - bearing = qFromBigEndian<qint16>(reinterpret_cast<const uchar *>(hheaTable.constData() + 14)); - ctMinRightBearing = bearing * fontDef.pixelSize / emSize; - } -} - -bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, - int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - *nglyphs = len; - QCFType<CFStringRef> cfstring; - - QVarLengthArray<CGGlyph> cgGlyphs(len); - CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len); - - for (int i = 0; i < len; ++i) - if (cgGlyphs[i]) - glyphs->glyphs[i] = cgGlyphs[i]; - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, len, flags, fontDef); - return true; -} - -glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs) -{ - QFixed w; - bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; - - for (int i = 0; i < glyphs.numGlyphs; ++i) { - w += round ? glyphs.effectiveAdvance(i).round() - : glyphs.effectiveAdvance(i); - } - return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); -} - -glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) -{ - glyph_metrics_t ret; - CGGlyph g = glyph; - CGRect rect = CTFontGetBoundingRectsForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, 0, 1); - if (synthesisFlags & QFontEngine::SynthesizedItalic) { - rect.size.width += rect.size.height * SYNTHETIC_ITALIC_SKEW; - } - ret.width = QFixed::fromReal(rect.size.width); - ret.height = QFixed::fromReal(rect.size.height); - ret.x = QFixed::fromReal(rect.origin.x); - ret.y = -QFixed::fromReal(rect.origin.y) - ret.height; - CGSize advances[1]; - CTFontGetAdvancesForGlyphs(ctfont, kCTFontHorizontalOrientation, &g, advances, 1); - ret.xoff = QFixed::fromReal(advances[0].width); - ret.yoff = QFixed::fromReal(advances[0].height); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - ret.xoff = ret.xoff.round(); - ret.yoff = ret.yoff.round(); - } - - return ret; -} - -QFixed QCoreTextFontEngine::ascent() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetAscent(ctfont)).round() - : QFixed::fromReal(CTFontGetAscent(ctfont)); -} -QFixed QCoreTextFontEngine::descent() const -{ - QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont)); - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - d = d.round(); - - // subtract a pixel to even out the historical +1 in QFontMetrics::height(). - // Fix in Qt 5. - return d - 1; -} -QFixed QCoreTextFontEngine::leading() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetLeading(ctfont)).round() - : QFixed::fromReal(CTFontGetLeading(ctfont)); -} -QFixed QCoreTextFontEngine::xHeight() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round() - : QFixed::fromReal(CTFontGetXHeight(ctfont)); -} - -QFixed QCoreTextFontEngine::averageCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? avgCharWidth.round() : avgCharWidth; -} - -qreal QCoreTextFontEngine::maxCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMaxCharWidth) : ctMaxCharWidth; -} - -qreal QCoreTextFontEngine::minLeftBearing() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinLeftBearing) : ctMinLeftBearing; -} - -qreal QCoreTextFontEngine::minRightBearing() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(ctMinRightBearing) : ctMinLeftBearing; -} - -void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) -{ - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(x, y); - getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - CGContextSetFontSize(ctx, fontDef.pixelSize); - - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight); - - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - - QVarLengthArray<CGSize> advances(glyphs.size()); - QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size()); - - for (int i = 0; i < glyphs.size() - 1; ++i) { - advances[i].width = (positions[i + 1].x - positions[i].x).toReal(); - advances[i].height = (positions[i + 1].y - positions[i].y).toReal(); - cgGlyphs[i] = glyphs[i]; - } - advances[glyphs.size() - 1].width = 0; - advances[glyphs.size() - 1].height = 0; - cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1]; - - CGContextSetFont(ctx, cgFont); - //NSLog(@"Font inDraw %@ ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont)); - - CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(), - positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - } - - CGContextSetTextMatrix(ctx, oldTextMatrix); -} - -struct ConvertPathInfo -{ - ConvertPathInfo(QPainterPath *newPath, const QPointF &newPos) : path(newPath), pos(newPos) {} - QPainterPath *path; - QPointF pos; -}; - -static void convertCGPathToQPainterPath(void *info, const CGPathElement *element) -{ - ConvertPathInfo *myInfo = static_cast<ConvertPathInfo *>(info); - switch(element->type) { - case kCGPathElementMoveToPoint: - myInfo->path->moveTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y()); - break; - case kCGPathElementAddLineToPoint: - myInfo->path->lineTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y()); - break; - case kCGPathElementAddQuadCurveToPoint: - myInfo->path->quadTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y(), - element->points[1].x + myInfo->pos.x(), - element->points[1].y + myInfo->pos.y()); - break; - case kCGPathElementAddCurveToPoint: - myInfo->path->cubicTo(element->points[0].x + myInfo->pos.x(), - element->points[0].y + myInfo->pos.y(), - element->points[1].x + myInfo->pos.x(), - element->points[1].y + myInfo->pos.y(), - element->points[2].x + myInfo->pos.x(), - element->points[2].y + myInfo->pos.y()); - break; - case kCGPathElementCloseSubpath: - myInfo->path->closeSubpath(); - break; - default: - qDebug() << "Unhandled path transform type: " << element->type; - } - -} - -void QCoreTextFontEngine::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nGlyphs, - QPainterPath *path, QTextItem::RenderFlags) -{ - CGAffineTransform cgMatrix = CGAffineTransformIdentity; - cgMatrix = CGAffineTransformScale(cgMatrix, 1, -1); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - - for (int i = 0; i < nGlyphs; ++i) { - QCFType<CGPathRef> cgpath = CTFontCreatePathForGlyph(ctfont, glyphs[i], &cgMatrix); - ConvertPathInfo info(path, positions[i].toPointF()); - CGPathApply(cgpath, &info, convertCGPathToQPainterPath); - } -} - -QImage QCoreTextFontEngine::imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int /*margin*/, bool aa) -{ - const glyph_metrics_t br = boundingBox(glyph); - QImage im(qRound(br.width)+2, qRound(br.height)+2, QImage::Format_RGB32); - im.fill(0); - - CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - uint cgflags = kCGImageAlphaNoneSkipFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), - 8, im.bytesPerLine(), colorspace, - cgflags); - CGContextSetFontSize(ctx, fontDef.pixelSize); - CGContextSetShouldAntialias(ctx, aa || - (fontDef.pointSize > qt_antialiasing_threshold - && !(fontDef.styleStrategy & QFont::NoAntialias))); - CGContextSetShouldSmoothFonts(ctx, aa); - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0); - - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, SYNTHETIC_ITALIC_SKEW, 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - CGContextSetFont(ctx, cgFont); - - qreal pos_x = -br.x.toReal() + subPixelPosition.toReal(); - qreal pos_y = im.height() + br.y.toReal() - 1; - CGContextSetTextPosition(ctx, pos_x, pos_y); - - CGSize advance; - advance.width = 0; - advance.height = 0; - CGGlyph cgGlyph = glyph; - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - } - - CGContextRelease(ctx); - - return im; -} - -QImage QCoreTextFontEngine::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) -{ - QImage im = imageForGlyph(glyph, subPixelPosition, 0, false); - - QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - for (int y=0; y<im.height(); ++y) { - uint *src = (uint*) im.scanLine(y); - uchar *dst = indexed.scanLine(y); - for (int x=0; x<im.width(); ++x) { - *dst = qGray(*src); - ++dst; - ++src; - } - } - - return indexed; -} - -QImage QCoreTextFontEngine::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, const QTransform &x) -{ - if (x.type() >= QTransform::TxScale) - return QFontEngine::alphaRGBMapForGlyph(glyph, subPixelPosition, margin, x); - - QImage im = imageForGlyph(glyph, subPixelPosition, margin, true); - qGamma_correct_back_to_linear_cs(&im); - return im; -} - -void QCoreTextFontEngine::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - int i, numGlyphs = glyphs->numGlyphs; - QVarLengthArray<CGGlyph> cgGlyphs(numGlyphs); - - for (i = 0; i < numGlyphs; ++i) { - if (glyphs->glyphs[i] & 0xff000000) - cgGlyphs[i] = 0; - else - cgGlyphs[i] = glyphs->glyphs[i]; - } - - loadAdvancesForGlyphs(ctfont, cgGlyphs, glyphs, numGlyphs, flags, fontDef); -} - -QFontEngine::FaceId QCoreTextFontEngine::faceId() const -{ - return QFontEngine::FaceId(); -} - -bool QCoreTextFontEngine::canRender(const QChar *string, int len) -{ - QVarLengthArray<CGGlyph> cgGlyphs(len); - return CTFontGetGlyphsForCharacters(ctfont, (const UniChar *) string, cgGlyphs.data(), len); -} - -bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0); - if (!table || !length) - return false; - CFIndex tableLength = CFDataGetLength(table); - int availableLength = *length; - *length = tableLength; - if (buffer) { - if (tableLength > availableLength) - return false; - CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer); - } - return true; -} - -void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *) -{ - // ### -} - -QFixed QCoreTextFontEngine::emSquareSize() const -{ - return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); -} - -QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const -{ - QFontDef newFontDef = fontDef; - newFontDef.pixelSize = pixelSize; - newFontDef.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - - return new QCoreTextFontEngine(cgFont, newFontDef); -} - -QT_END_NAMESPACE - -#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - diff --git a/src/gui/text/qfontengine_coretext_p.h b/src/gui/text/qfontengine_coretext_p.h deleted file mode 100644 index 3775bc6002..0000000000 --- a/src/gui/text/qfontengine_coretext_p.h +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_CORETEXT_P_H -#define QFONTENGINE_CORETEXT_P_H - -#include <private/qfontengine_p.h> - -#if !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -class QRawFontPrivate; -class QCoreTextFontEngineMulti; -class QCoreTextFontEngine : public QFontEngine -{ -public: - QCoreTextFontEngine(CTFontRef font, const QFontDef &def); - QCoreTextFontEngine(CGFontRef font, const QFontDef &def); - ~QCoreTextFontEngine(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t glyph); - - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual QFixed xHeight() const; - virtual qreal maxCharWidth() const; - virtual QFixed averageCharWidth() const; - - virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, - QPainterPath *path, QTextItem::RenderFlags); - - virtual const char *name() const { return "QCoreTextFontEngine"; } - - virtual bool canRender(const QChar *string, int len); - - virtual int synthesized() const { return synthesisFlags; } - virtual bool supportsSubPixelPositions() const { return true; } - - virtual Type type() const { return QFontEngine::Mac; } - - void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight); - - virtual FaceId faceId() const; - virtual bool getSfntTableData(uint /*tag*/, uchar * /*buffer*/, uint * /*length*/) const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition); - virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); - virtual qreal minRightBearing() const; - virtual qreal minLeftBearing() const; - virtual QFixed emSquareSize() const; - - virtual QFontEngine *cloneWithSize(qreal pixelSize) const; - -private: - friend class QRawFontPrivate; - - void init(); - QImage imageForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, bool colorful); - CTFontRef ctfont; - CGFontRef cgFont; - int synthesisFlags; - CGAffineTransform transform; - QFixed avgCharWidth; - qreal ctMaxCharWidth; - qreal ctMinLeftBearing; - qreal ctMinRightBearing; - friend class QCoreTextFontEngineMulti; -}; - -class QCoreTextFontEngineMulti : public QFontEngineMulti -{ -public: - QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning); - QCoreTextFontEngineMulti(CGFontRef cgFontRef, const QFontDef &fontDef, bool kerning); - ~QCoreTextFontEngineMulti(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QTextEngine::ShaperFlags flags) const; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *charAttributes, - QScriptItem *si) const; - - virtual const char *name() const { return "CoreText"; } - inline CTFontRef macFontID() const { return ctfont; } - -protected: - virtual void loadEngine(int at); - -private: - void init(bool kerning); - inline const QCoreTextFontEngine *engineAt(int i) const - { return static_cast<const QCoreTextFontEngine *>(engines.at(i)); } - - uint fontIndexForFont(CTFontRef font) const; - CTFontRef ctfont; - mutable QCFType<CFMutableDictionaryRef> attributeDict; - CGAffineTransform transform; - friend class QFontDialogPrivate; -}; - -#endif// !defined(Q_WS_MAC) || (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) - -#endif // QFONTENGINE_CORETEXT_P_H diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm deleted file mode 100644 index 9f094ad7d1..0000000000 --- a/src/gui/text/qfontengine_mac.mm +++ /dev/null @@ -1,1236 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_mac_p.h" - -#include <private/qapplication_p.h> -#include <private/qfontengine_p.h> -#include <private/qpainter_p.h> -#include <private/qtextengine_p.h> -#include <qbitmap.h> -#include <private/qpaintengine_mac_p.h> -#include <private/qprintengine_mac_p.h> -#include <qglobal.h> -#include <qpixmap.h> -#include <qpixmapcache.h> -#include <qvarlengtharray.h> -#include <qdebug.h> -#include <qendian.h> -#include <qmath.h> -#include <private/qimage_p.h> - -#include <ApplicationServices/ApplicationServices.h> -#include <AppKit/AppKit.h> - -QT_BEGIN_NAMESPACE - -/***************************************************************************** - QFontEngine debug facilities - *****************************************************************************/ -//#define DEBUG_ADVANCES - -extern int qt_antialiasing_threshold; // QApplication.cpp - -#ifndef FixedToQFixed -#define FixedToQFixed(a) QFixed::fromFixed((a) >> 10) -#define QFixedToFixed(x) ((x).value() << 10) -#endif - -class QMacFontPath -{ - float x, y; - QPainterPath *path; -public: - inline QMacFontPath(float _x, float _y, QPainterPath *_path) : x(_x), y(_y), path(_path) { } - inline void setPosition(float _x, float _y) { x = _x; y = _y; } - inline void advance(float _x) { x += _x; } - static OSStatus lineTo(const Float32Point *, void *); - static OSStatus cubicTo(const Float32Point *, const Float32Point *, - const Float32Point *, void *); - static OSStatus moveTo(const Float32Point *, void *); - static OSStatus closePath(void *); -}; - -OSStatus QMacFontPath::lineTo(const Float32Point *pt, void *data) - -{ - QMacFontPath *p = static_cast<QMacFontPath*>(data); - p->path->lineTo(p->x + pt->x, p->y + pt->y); - return noErr; -} - -OSStatus QMacFontPath::cubicTo(const Float32Point *cp1, const Float32Point *cp2, - const Float32Point *ep, void *data) - -{ - QMacFontPath *p = static_cast<QMacFontPath*>(data); - p->path->cubicTo(p->x + cp1->x, p->y + cp1->y, - p->x + cp2->x, p->y + cp2->y, - p->x + ep->x, p->y + ep->y); - return noErr; -} - -OSStatus QMacFontPath::moveTo(const Float32Point *pt, void *data) -{ - QMacFontPath *p = static_cast<QMacFontPath*>(data); - p->path->moveTo(p->x + pt->x, p->y + pt->y); - return noErr; -} - -OSStatus QMacFontPath::closePath(void *data) -{ - static_cast<QMacFontPath*>(data)->path->closeSubpath(); - return noErr; -} - - -#ifndef QT_MAC_USE_COCOA -QFontEngineMacMulti::QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - this->kerning = kerning; - - // hopefully (CTFontCreateWithName or CTFontCreateWithFontDescriptor) + CTFontCreateCopyWithSymbolicTraits - // (or CTFontCreateWithQuickdrawInstance) - FMFontFamily fmFamily; - FMFontStyle fntStyle = 0; - fmFamily = FMGetFontFamilyFromATSFontFamilyRef(atsFamily); - if (fmFamily == kInvalidFontFamily) { - // Use the ATSFont then... - fontID = FMGetFontFromATSFontRef(atsFontRef); - } else { - if (fontDef.weight >= QFont::Bold) - fntStyle |= ::bold; - if (fontDef.style != QFont::StyleNormal) - fntStyle |= ::italic; - - FMFontStyle intrinsicStyle; - FMFont fnt = 0; - if (FMGetFontFromFontFamilyInstance(fmFamily, fntStyle, &fnt, &intrinsicStyle) == noErr) - fontID = FMGetATSFontRefFromFont(fnt); - } - - // CFDictionaryRef, <CTStringAttributes.h> - OSStatus status; - - status = ATSUCreateTextLayout(&textLayout); - Q_ASSERT(status == noErr); - - const int maxAttributeCount = 5; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - Fixed size = FixRatio(fontDef.pixelSize, 1); - tags[attributeCount] = kATSUSizeTag; - sizes[attributeCount] = sizeof(size); - values[attributeCount] = &size; - ++attributeCount; - - tags[attributeCount] = kATSUFontTag; - sizes[attributeCount] = sizeof(fontID); - values[attributeCount] = &this->fontID; - ++attributeCount; - - transform = CGAffineTransformIdentity; - if (fontDef.stretch != 100) { - transform = CGAffineTransformMakeScale(float(fontDef.stretch) / float(100), 1); - tags[attributeCount] = kATSUFontMatrixTag; - sizes[attributeCount] = sizeof(transform); - values[attributeCount] = &transform; - ++attributeCount; - } - - status = ATSUCreateStyle(&style); - Q_ASSERT(status == noErr); - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - status = ATSUSetAttributes(style, attributeCount, tags, sizes, values); - Q_ASSERT(status == noErr); - - QFontEngineMac *fe = new QFontEngineMac(style, fontID, fontDef, this); - fe->ref.ref(); - engines.append(fe); -} - -QFontEngineMacMulti::~QFontEngineMacMulti() -{ - ATSUDisposeTextLayout(textLayout); - ATSUDisposeStyle(style); - - for (int i = 0; i < engines.count(); ++i) { - QFontEngineMac *fe = const_cast<QFontEngineMac *>(static_cast<const QFontEngineMac *>(engines.at(i))); - fe->multiEngine = 0; - if (!fe->ref.deref()) - delete fe; - } - engines.clear(); -} - -struct QGlyphLayoutInfo -{ - QGlyphLayout *glyphs; - int *numGlyphs; - bool callbackCalled; - int *mappedFonts; - QTextEngine::ShaperFlags flags; - QFontEngineMacMulti::ShaperItem *shaperItem; - unsigned int styleStrategy; -}; - -static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATSULineRef lineRef, URefCon refCon, - void *operationExtraParameter, ATSULayoutOperationCallbackStatus *callbackStatus) -{ - Q_UNUSED(selector); - Q_UNUSED(operationExtraParameter); - - QGlyphLayoutInfo *nfo = reinterpret_cast<QGlyphLayoutInfo *>(refCon); - nfo->callbackCalled = true; - - ATSLayoutRecord *layoutData = 0; - ItemCount itemCount = 0; - - OSStatus e = noErr; - e = ATSUDirectGetLayoutDataArrayPtrFromLineRef(lineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - /*iCreate =*/ false, - (void **) &layoutData, - &itemCount); - if (e != noErr) - return e; - - *nfo->numGlyphs = itemCount - 1; - - Fixed *baselineDeltas = 0; - - e = ATSUDirectGetLayoutDataArrayPtrFromLineRef(lineRef, kATSUDirectDataBaselineDeltaFixedArray, - /*iCreate =*/ true, - (void **) &baselineDeltas, - &itemCount); - if (e != noErr) - return e; - - int nextCharStop = -1; - int currentClusterGlyph = -1; // first glyph in log cluster - QFontEngineMacMulti::ShaperItem *item = nfo->shaperItem; - if (item->charAttributes) { - item = nfo->shaperItem; -#if !defined(QT_NO_DEBUG) - int surrogates = 0; - const QChar *str = item->string; - for (int i = item->from; i < item->from + item->length - 1; ++i) { - surrogates += (str[i].unicode() >= 0xd800 && str[i].unicode() < 0xdc00 - && str[i+1].unicode() >= 0xdc00 && str[i+1].unicode() < 0xe000); - } -#endif - for (nextCharStop = item->from; nextCharStop < item->from + item->length; ++nextCharStop) - if (item->charAttributes[nextCharStop].charStop) - break; - nextCharStop -= item->from; - } - - nfo->glyphs->attributes[0].clusterStart = true; - int glyphIdx = 0; - int glyphIncrement = 1; - if (nfo->flags & QTextEngine::RightToLeft) { - glyphIdx = itemCount - 2; - glyphIncrement = -1; - } - for (int i = 0; i < *nfo->numGlyphs; ++i, glyphIdx += glyphIncrement) { - - int charOffset = layoutData[glyphIdx].originalOffset / sizeof(UniChar); - const int fontIdx = nfo->mappedFonts[charOffset]; - - ATSGlyphRef glyphId = layoutData[glyphIdx].glyphID; - - QFixed yAdvance = FixedToQFixed(baselineDeltas[glyphIdx]); - QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos); - - if (nfo->styleStrategy & QFont::ForceIntegerMetrics) { - yAdvance = yAdvance.round(); - xAdvance = xAdvance.round(); - } - - if (glyphId != 0xffff || i == 0) { - if (i < nfo->glyphs->numGlyphs) - { - nfo->glyphs->glyphs[i] = (glyphId & 0x00ffffff) | (fontIdx << 24); - - nfo->glyphs->advances_y[i] = yAdvance; - nfo->glyphs->advances_x[i] = xAdvance; - } - } else { - // ATSUI gives us 0xffff as glyph id at the index in the glyph array for - // a character position that maps to a ligtature. Such a glyph id does not - // result in any visual glyph, but it may have an advance, which is why we - // sum up the glyph advances. - --i; - nfo->glyphs->advances_y[i] += yAdvance; - nfo->glyphs->advances_x[i] += xAdvance; - *nfo->numGlyphs -= 1; - } - - if (item->log_clusters) { - if (charOffset >= nextCharStop) { - nfo->glyphs->attributes[i].clusterStart = true; - currentClusterGlyph = i; - - ++nextCharStop; - for (; nextCharStop < item->length; ++nextCharStop) - if (item->charAttributes[item->from + nextCharStop].charStop) - break; - } else { - if (currentClusterGlyph == -1) - currentClusterGlyph = i; - } - item->log_clusters[charOffset] = currentClusterGlyph; - - // surrogate handling - if (charOffset < item->length - 1) { - QChar current = item->string[item->from + charOffset]; - QChar next = item->string[item->from + charOffset + 1]; - if (current.unicode() >= 0xd800 && current.unicode() < 0xdc00 - && next.unicode() >= 0xdc00 && next.unicode() < 0xe000) { - item->log_clusters[charOffset + 1] = currentClusterGlyph; - } - } - } - } - - /* - if (item) { - qDebug() << "resulting logclusters:"; - for (int i = 0; i < item->length; ++i) - qDebug() << "logClusters[" << i << "] =" << item->log_clusters[i]; - qDebug() << "clusterstarts:"; - for (int i = 0; i < *nfo->numGlyphs; ++i) - qDebug() << "clusterStart[" << i << "] =" << nfo->glyphs[i].attributes.clusterStart; - } - */ - - ATSUDirectReleaseLayoutDataArrayPtr(lineRef, kATSUDirectDataBaselineDeltaFixedArray, - (void **) &baselineDeltas); - - ATSUDirectReleaseLayoutDataArrayPtr(lineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, - (void **) &layoutData); - - *callbackStatus = kATSULayoutOperationCallbackStatusHandled; - return noErr; -} - -int QFontEngineMacMulti::fontIndexForFontID(ATSUFontID id) const -{ - for (int i = 0; i < engines.count(); ++i) { - if (engineAt(i)->fontID == id) - return i; - } - - QFontEngineMacMulti *that = const_cast<QFontEngineMacMulti *>(this); - QFontEngineMac *fe = new QFontEngineMac(style, id, fontDef, that); - fe->ref.ref(); - that->engines.append(fe); - return engines.count() - 1; -} - -bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - return stringToCMap(str, len, glyphs, nglyphs, flags, /*logClusters=*/0, /*charAttributes=*/0); -} - -bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *charAttributes, QScriptItem *) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - ShaperItem shaperItem; - shaperItem.string = str; - shaperItem.from = 0; - shaperItem.length = len; - shaperItem.glyphs = *glyphs; - shaperItem.glyphs.numGlyphs = *nglyphs; - shaperItem.flags = flags; - shaperItem.log_clusters = logClusters; - shaperItem.charAttributes = charAttributes; - - const int maxChars = qMax(1, - int(SHRT_MAX / maxCharWidth()) - - 10 // subtract a few to be on the safe side - ); - if (len < maxChars || !charAttributes) - return stringToCMapInternal(str, len, glyphs, nglyphs, flags, &shaperItem); - - int charIdx = 0; - int glyphIdx = 0; - ShaperItem tmpItem = shaperItem; - - do { - tmpItem.from = shaperItem.from + charIdx; - - int charCount = qMin(maxChars, len - charIdx); - - int lastWhitespace = tmpItem.from + charCount - 1; - int lastSoftBreak = lastWhitespace; - int lastCharStop = lastSoftBreak; - for (int i = lastCharStop; i >= tmpItem.from; --i) { - if (tmpItem.charAttributes[i].whiteSpace) { - lastWhitespace = i; - break; - } if (tmpItem.charAttributes[i].lineBreakType != HB_NoBreak) { - lastSoftBreak = i; - } if (tmpItem.charAttributes[i].charStop) { - lastCharStop = i; - } - } - charCount = qMin(lastWhitespace, qMin(lastSoftBreak, lastCharStop)) - tmpItem.from + 1; - - int glyphCount = shaperItem.glyphs.numGlyphs - glyphIdx; - if (glyphCount <= 0) - return false; - tmpItem.length = charCount; - tmpItem.glyphs = shaperItem.glyphs.mid(glyphIdx, glyphCount); - tmpItem.log_clusters = shaperItem.log_clusters + charIdx; - if (!stringToCMapInternal(tmpItem.string + tmpItem.from, tmpItem.length, - &tmpItem.glyphs, &glyphCount, flags, - &tmpItem)) { - *nglyphs = glyphIdx + glyphCount; - return false; - } - for (int i = 0; i < charCount; ++i) - tmpItem.log_clusters[i] += glyphIdx; - glyphIdx += glyphCount; - charIdx += charCount; - } while (charIdx < len); - *nglyphs = glyphIdx; - glyphs->numGlyphs = glyphIdx; - - return true; -} - -bool QFontEngineMacMulti::stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags,ShaperItem *shaperItem) const -{ - //qDebug() << "stringToCMap" << QString(str, len); - - OSStatus e = noErr; - - e = ATSUSetTextPointerLocation(textLayout, (UniChar *)(str), 0, len, len); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetTextPointerLocation %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - QGlyphLayoutInfo nfo; - nfo.glyphs = glyphs; - nfo.numGlyphs = nglyphs; - nfo.callbackCalled = false; - nfo.flags = flags; - nfo.shaperItem = shaperItem; - nfo.styleStrategy = fontDef.styleStrategy; - - int prevNumGlyphs = *nglyphs; - - QVarLengthArray<int> mappedFonts(len); - for (int i = 0; i < len; ++i) - mappedFonts[i] = 0; - nfo.mappedFonts = mappedFonts.data(); - - Q_ASSERT(sizeof(void *) <= sizeof(URefCon)); - e = ATSUSetTextLayoutRefCon(textLayout, (URefCon)&nfo); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetTextLayoutRefCon %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - { - const int maxAttributeCount = 3; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - tags[attributeCount] = kATSULineLayoutOptionsTag; - ATSLineLayoutOptions layopts = kATSLineHasNoOpticalAlignment - | kATSLineIgnoreFontLeading - | kATSLineNoSpecialJustification // we do kashidas ourselves - | kATSLineDisableAllJustification - ; - - if (fontDef.styleStrategy & QFont::NoAntialias) - layopts |= kATSLineNoAntiAliasing; - - if (!kerning) - layopts |= kATSLineDisableAllKerningAdjustments; - - values[attributeCount] = &layopts; - sizes[attributeCount] = sizeof(layopts); - ++attributeCount; - - tags[attributeCount] = kATSULayoutOperationOverrideTag; - ATSULayoutOperationOverrideSpecifier spec; - spec.operationSelector = kATSULayoutOperationPostLayoutAdjustment; - spec.overrideUPP = atsuPostLayoutCallback; - values[attributeCount] = &spec; - sizes[attributeCount] = sizeof(spec); - ++attributeCount; - - // CTWritingDirection - Boolean direction; - if (flags & QTextEngine::RightToLeft) - direction = kATSURightToLeftBaseDirection; - else - direction = kATSULeftToRightBaseDirection; - tags[attributeCount] = kATSULineDirectionTag; - values[attributeCount] = &direction; - sizes[attributeCount] = sizeof(direction); - ++attributeCount; - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - e = ATSUSetLayoutControls(textLayout, attributeCount, tags, sizes, values); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetLayoutControls %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - } - - e = ATSUSetRunStyle(textLayout, style, 0, len); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUSetRunStyle %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - if (!(fontDef.styleStrategy & QFont::NoFontMerging)) { - int pos = 0; - do { - ATSUFontID substFont = 0; - UniCharArrayOffset changedOffset = 0; - UniCharCount changeCount = 0; - - e = ATSUMatchFontsToText(textLayout, pos, len - pos, - &substFont, &changedOffset, - &changeCount); - if (e == kATSUFontsMatched) { - int fontIdx = fontIndexForFontID(substFont); - for (uint i = 0; i < changeCount; ++i) - mappedFonts[changedOffset + i] = fontIdx; - pos = changedOffset + changeCount; - ATSUSetRunStyle(textLayout, engineAt(fontIdx)->style, changedOffset, changeCount); - } else if (e == kATSUFontsNotMatched) { - pos = changedOffset + changeCount; - } - } while (pos < len && e != noErr); - } - { // trigger the a layout - // CFAttributedStringCreate, CTFramesetterCreateWithAttributedString (or perhaps Typesetter) - Rect rect; - e = ATSUMeasureTextImage(textLayout, kATSUFromTextBeginning, kATSUToTextEnd, - /*iLocationX =*/ 0, /*iLocationY =*/ 0, - &rect); - if (e != noErr) { - qWarning("Qt: internal: %ld: Error ATSUMeasureTextImage %s: %d", long(e), __FILE__, __LINE__); - return false; - } - } - - if (!nfo.callbackCalled) { - qWarning("Qt: internal: %ld: Error ATSUMeasureTextImage did not trigger callback %s: %d", long(e), __FILE__, __LINE__); - return false; - } - - ATSUClearLayoutCache(textLayout, kATSUFromTextBeginning); - if (prevNumGlyphs < *nfo.numGlyphs) - return false; - return true; -} - -void QFontEngineMacMulti::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - Q_ASSERT(false); - Q_UNUSED(glyphs); - Q_UNUSED(flags); -} - -void QFontEngineMacMulti::doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const -{ - //Q_ASSERT(false); -} - -void QFontEngineMacMulti::loadEngine(int /*at*/) -{ - // should never be called! - Q_ASSERT(false); -} - -bool QFontEngineMacMulti::canRender(const QChar *string, int len) -{ - ATSUSetTextPointerLocation(textLayout, reinterpret_cast<const UniChar *>(string), 0, len, len); - ATSUSetRunStyle(textLayout, style, 0, len); - - OSStatus e = noErr; - int pos = 0; - do { - FMFont substFont = 0; - UniCharArrayOffset changedOffset = 0; - UniCharCount changeCount = 0; - - // CTFontCreateForString - e = ATSUMatchFontsToText(textLayout, pos, len - pos, - &substFont, &changedOffset, - &changeCount); - if (e == kATSUFontsMatched) { - pos = changedOffset + changeCount; - } else if (e == kATSUFontsNotMatched) { - break; - } - } while (pos < len && e != noErr); - - return e == noErr || e == kATSUFontsMatched; -} - -QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine) - : fontID(fontID), multiEngine(multiEngine), cmap(0), symbolCMap(false) -{ - fontDef = def; - ATSUCreateAndCopyStyle(baseStyle, &style); - ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); - cgFont = CGFontCreateWithPlatformFont(&atsFont); - - const int maxAttributeCount = 4; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - synthesisFlags = 0; - - // synthesizing using CG is not recommended - quint16 macStyle = 0; - { - uchar data[4]; - ByteCount len = 4; - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 44, 4, &data, &len) == noErr) - macStyle = qFromBigEndian<quint16>(data); - } - - Boolean atsuBold = false; - Boolean atsuItalic = false; - if (fontDef.weight >= QFont::Bold) { - if (!(macStyle & 1)) { - synthesisFlags |= SynthesizedBold; - atsuBold = true; - tags[attributeCount] = kATSUQDBoldfaceTag; - sizes[attributeCount] = sizeof(atsuBold); - values[attributeCount] = &atsuBold; - ++attributeCount; - } - } - if (fontDef.style != QFont::StyleNormal) { - if (!(macStyle & 2)) { - synthesisFlags |= SynthesizedItalic; - atsuItalic = true; - tags[attributeCount] = kATSUQDItalicTag; - sizes[attributeCount] = sizeof(atsuItalic); - values[attributeCount] = &atsuItalic; - ++attributeCount; - } - } - - tags[attributeCount] = kATSUFontTag; - values[attributeCount] = &fontID; - sizes[attributeCount] = sizeof(fontID); - ++attributeCount; - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - OSStatus err = ATSUSetAttributes(style, attributeCount, tags, sizes, values); - Q_ASSERT(err == noErr); - Q_UNUSED(err); - - // CTFontCopyTable - quint16 tmpFsType; - if (ATSFontGetTable(atsFont, MAKE_TAG('O', 'S', '/', '2'), 8, 2, &tmpFsType, 0) == noErr) - fsType = qFromBigEndian<quint16>(tmpFsType); - else - fsType = 0; - - if (multiEngine) - transform = multiEngine->transform; - else - transform = CGAffineTransformIdentity; - - ATSUTextMeasurement metric; - - ATSUGetAttribute(style, kATSUAscentTag, sizeof(metric), &metric, 0); - m_ascent = FixRound(metric); - - ATSUGetAttribute(style, kATSUDescentTag, sizeof(metric), &metric, 0); - m_descent = FixRound(metric); - - ATSUGetAttribute(style, kATSULeadingTag, sizeof(metric), &metric, 0); - m_leading = FixRound(metric); - - ATSFontMetrics metrics; - - ATSFontGetHorizontalMetrics(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &metrics); - m_maxCharWidth = metrics.maxAdvanceWidth * fontDef.pointSize; - - ATSFontGetHorizontalMetrics(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &metrics); - m_xHeight = QFixed::fromReal(metrics.xHeight * fontDef.pointSize); - - ATSFontGetHorizontalMetrics(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &metrics); - m_averageCharWidth = QFixed::fromReal(metrics.avgAdvanceWidth * fontDef.pointSize); - - // Use width of 'X' if ATSFontGetHorizontalMetrics returns 0 for avgAdvanceWidth. - if (m_averageCharWidth == QFixed(0)) { - QChar c('X'); - QGlyphLayoutArray<1> glyphs; - int nglyphs = 1; - stringToCMap(&c, 1, &glyphs, &nglyphs, 0); - glyph_metrics_t metrics = boundingBox(glyphs); - m_averageCharWidth = metrics.width; - } -} - -QFontEngineMac::~QFontEngineMac() -{ - ATSUDisposeStyle(style); -} - -static inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { - uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; - ++i; - } - } - return uc; -} - -// Not used directly for shaping, only used to calculate m_averageCharWidth -bool QFontEngineMac::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (!cmap) { - cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); - int size = 0; - cmap = getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), cmapTable.size(), &symbolCMap, &size); - if (!cmap) - return false; - } - if (symbolCMap) { - for (int i = 0; i < len; ++i) { - unsigned int uc = getChar(str, i, len); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); - if(!glyphs->glyphs[i] && uc < 0x100) - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else { - for (int i = 0; i < len; ++i) { - unsigned int uc = getChar(str, i, len); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); - } - } - - *nglyphs = len; - glyphs->numGlyphs = *nglyphs; - - if (!(flags & QTextEngine::GlyphIndicesOnly)) - recalcAdvances(glyphs, flags); - - return true; -} - -void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - Q_UNUSED(flags) - - QVarLengthArray<GlyphID> atsuGlyphs(glyphs->numGlyphs); - for (int i = 0; i < glyphs->numGlyphs; ++i) - atsuGlyphs[i] = glyphs->glyphs[i]; - - QVarLengthArray<ATSGlyphScreenMetrics> metrics(glyphs->numGlyphs); - - ATSUGlyphGetScreenMetrics(style, glyphs->numGlyphs, atsuGlyphs.data(), sizeof(GlyphID), - /* iForcingAntiAlias =*/ false, - /* iAntiAliasSwitch =*/true, - metrics.data()); - - for (int i = 0; i < glyphs->numGlyphs; ++i) { - glyphs->advances_x[i] = QFixed::fromReal(metrics[i].deviceAdvance.x); - glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - glyphs->advances_x[i] = glyphs->advances_x[i].round(); - glyphs->advances_y[i] = glyphs->advances_y[i].round(); - } - } -} - -glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs) -{ - QFixed w; - bool round = fontDef.styleStrategy & QFont::ForceIntegerMetrics; - for (int i = 0; i < glyphs.numGlyphs; ++i) { - w += round ? glyphs.effectiveAdvance(i).round() - : glyphs.effectiveAdvance(i); - } - return glyph_metrics_t(0, -(ascent()), w - lastRightBearing(glyphs, round), ascent()+descent(), w, 0); -} - -glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph) -{ - GlyphID atsuGlyph = glyph; - - ATSGlyphScreenMetrics metrics; - - ATSUGlyphGetScreenMetrics(style, 1, &atsuGlyph, 0, - /* iForcingAntiAlias =*/ false, - /* iAntiAliasSwitch =*/true, - &metrics); - - // ### check again - - glyph_metrics_t gm; - gm.width = int(metrics.width); - gm.height = int(metrics.height); - gm.x = QFixed::fromReal(metrics.topLeft.x); - gm.y = -QFixed::fromReal(metrics.topLeft.y); - gm.xoff = QFixed::fromReal(metrics.deviceAdvance.x); - gm.yoff = QFixed::fromReal(metrics.deviceAdvance.y); - - if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - gm.x = gm.x.floor(); - gm.y = gm.y.floor(); - gm.xoff = gm.xoff.round(); - gm.yoff = gm.yoff.round(); - } - - return gm; -} - -QFixed QFontEngineMac::ascent() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_ascent.round() - : m_ascent; -} - -QFixed QFontEngineMac::descent() const -{ - // subtract a pixel to even out the historical +1 in QFontMetrics::height(). - // Fix in Qt 5. - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_descent.round() - 1 - : m_descent; -} - -QFixed QFontEngineMac::leading() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_leading.round() - : m_leading; -} - -qreal QFontEngineMac::maxCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qRound(m_maxCharWidth) - : m_maxCharWidth; -} - -QFixed QFontEngineMac::xHeight() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_xHeight.round() - : m_xHeight; -} - -QFixed QFontEngineMac::averageCharWidth() const -{ - return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_averageCharWidth.round() - : m_averageCharWidth; -} - -static void addGlyphsToPathHelper(ATSUStyle style, glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path) -{ - if (!numGlyphs) - return; - - OSStatus e; - - QMacFontPath fontpath(0, 0, path); - ATSCubicMoveToUPP moveTo = NewATSCubicMoveToUPP(QMacFontPath::moveTo); - ATSCubicLineToUPP lineTo = NewATSCubicLineToUPP(QMacFontPath::lineTo); - ATSCubicCurveToUPP cubicTo = NewATSCubicCurveToUPP(QMacFontPath::cubicTo); - ATSCubicClosePathUPP closePath = NewATSCubicClosePathUPP(QMacFontPath::closePath); - - // CTFontCreatePathForGlyph - for (int i = 0; i < numGlyphs; ++i) { - GlyphID glyph = glyphs[i]; - - fontpath.setPosition(positions[i].x.toReal(), positions[i].y.toReal()); - ATSUGlyphGetCubicPaths(style, glyph, moveTo, lineTo, - cubicTo, closePath, &fontpath, &e); - } - - DisposeATSCubicMoveToUPP(moveTo); - DisposeATSCubicLineToUPP(lineTo); - DisposeATSCubicCurveToUPP(cubicTo); - DisposeATSCubicClosePathUPP(closePath); -} - -void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, QPainterPath *path, - QTextItem::RenderFlags) -{ - addGlyphsToPathHelper(style, glyphs, positions, numGlyphs, path); -} - - -/*! - Helper function for alphaMapForGlyph and alphaRGBMapForGlyph. The two are identical, except for - the subpixel antialiasing... -*/ -QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful) -{ - const glyph_metrics_t br = boundingBox(glyph); - QImage im(qRound(br.width)+2, qRound(br.height)+4, QImage::Format_RGB32); - im.fill(0xff000000); - - CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); - uint cgflags = kCGImageAlphaNoneSkipFirst; -#ifdef kCGBitmapByteOrder32Host //only needed because CGImage.h added symbols in the minor version - cgflags |= kCGBitmapByteOrder32Host; -#endif - CGContextRef ctx = CGBitmapContextCreate(im.bits(), im.width(), im.height(), - 8, im.bytesPerLine(), colorspace, - cgflags); - CGContextSetFontSize(ctx, fontDef.pixelSize); - CGContextSetShouldAntialias(ctx, fontDef.pointSize > qt_antialiasing_threshold && !(fontDef.styleStrategy & QFont::NoAntialias)); - // turn off sub-pixel hinting - no support for that in OpenGL - CGContextSetShouldSmoothFonts(ctx, colorful); - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0); - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, tanf(14 * acosf(0) / 90), 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - CGContextSetRGBFillColor(ctx, 1, 1, 1, 1); - CGContextSetTextDrawingMode(ctx, kCGTextFill); - CGContextSetFont(ctx, cgFont); - - qreal pos_x = -br.x.toReal() + 1; - qreal pos_y = im.height() + br.y.toReal() - 2; - CGContextSetTextPosition(ctx, pos_x, pos_y); - - CGSize advance; - advance.width = 0; - advance.height = 0; - CGGlyph cgGlyph = glyph; - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, pos_x + 0.5 * lineThickness().toReal(), pos_y); - CGContextShowGlyphsWithAdvances(ctx, &cgGlyph, &advance, 1); - } - - CGContextRelease(ctx); - - return im; -} - -QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph) -{ - QImage im = imageForGlyph(glyph, 2, false); - - QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - for (int y=0; y<im.height(); ++y) { - uint *src = (uint*) im.scanLine(y); - uchar *dst = indexed.scanLine(y); - for (int x=0; x<im.width(); ++x) { - *dst = qGray(*src); - ++dst; - ++src; - } - } - - return indexed; -} - -QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) -{ - QImage im = imageForGlyph(glyph, margin, true); - - if (t.type() >= QTransform::TxScale) { - im = im.transformed(t); - } - - qGamma_correct_back_to_linear_cs(&im); - - return im; -} - - -bool QFontEngineMac::canRender(const QChar *string, int len) -{ - Q_ASSERT(false); - Q_UNUSED(string); - Q_UNUSED(len); - return false; -} - -void QFontEngineMac::draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight) -{ - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix; - matrix.translate(x, y); - getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - CGContextSetFontSize(ctx, fontDef.pixelSize); - - CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx); - - CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight); - - CGAffineTransformConcat(cgMatrix, oldTextMatrix); - - if (synthesisFlags & QFontEngine::SynthesizedItalic) - cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0)); - - cgMatrix = CGAffineTransformConcat(cgMatrix, transform); - - CGContextSetTextMatrix(ctx, cgMatrix); - - CGContextSetTextDrawingMode(ctx, kCGTextFill); - - - QVarLengthArray<CGSize> advances(glyphs.size()); - QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size()); - - for (int i = 0; i < glyphs.size() - 1; ++i) { - advances[i].width = (positions[i + 1].x - positions[i].x).toReal(); - advances[i].height = (positions[i + 1].y - positions[i].y).toReal(); - cgGlyphs[i] = glyphs[i]; - } - advances[glyphs.size() - 1].width = 0; - advances[glyphs.size() - 1].height = 0; - cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1]; - - CGContextSetFont(ctx, cgFont); - - CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - - if (synthesisFlags & QFontEngine::SynthesizedBold) { - CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(), - positions[0].y.toReal()); - - CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size()); - } - - CGContextSetTextMatrix(ctx, oldTextMatrix); -} - -QFontEngine::FaceId QFontEngineMac::faceId() const -{ - FaceId ret; -#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) -if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) { - // CTFontGetPlatformFont - FSRef ref; - if (ATSFontGetFileReference(FMGetATSFontRefFromFont(fontID), &ref) != noErr) - return ret; - ret.filename = QByteArray(128, 0); - ret.index = fontID; - FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); -}else -#endif -{ - FSSpec spec; - if (ATSFontGetFileSpecification(FMGetATSFontRefFromFont(fontID), &spec) != noErr) - return ret; - - FSRef ref; - FSpMakeFSRef(&spec, &ref); - ret.filename = QByteArray(128, 0); - ret.index = fontID; - FSRefMakePath(&ref, (UInt8 *)ret.filename.data(), ret.filename.size()); -} - return ret; -} - -QByteArray QFontEngineMac::getSfntTable(uint tag) const -{ - ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); - - ByteCount length; - OSStatus status = ATSFontGetTable(atsFont, tag, 0, 0, 0, &length); - if (status != noErr) - return QByteArray(); - QByteArray table(length, 0); - // CTFontCopyTable - status = ATSFontGetTable(atsFont, tag, 0, table.length(), table.data(), &length); - if (status != noErr) - return QByteArray(); - return table; -} - -QFontEngine::Properties QFontEngineMac::properties() const -{ - QFontEngine::Properties props; - ATSFontRef atsFont = FMGetATSFontRefFromFont(fontID); - quint16 tmp; - // CTFontGetUnitsPerEm - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 18, 2, &tmp, 0) == noErr) - props.emSquare = qFromBigEndian<quint16>(tmp); - struct { - qint16 xMin; - qint16 yMin; - qint16 xMax; - qint16 yMax; - } bbox; - bbox.xMin = bbox.xMax = bbox.yMin = bbox.yMax = 0; - // CTFontGetBoundingBox - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'e', 'a', 'd'), 36, 8, &bbox, 0) == noErr) { - bbox.xMin = qFromBigEndian<quint16>(bbox.xMin); - bbox.yMin = qFromBigEndian<quint16>(bbox.yMin); - bbox.xMax = qFromBigEndian<quint16>(bbox.xMax); - bbox.yMax = qFromBigEndian<quint16>(bbox.yMax); - } - struct { - qint16 ascender; - qint16 descender; - qint16 linegap; - } metrics; - metrics.ascender = metrics.descender = metrics.linegap = 0; - // CTFontGetAscent, etc. - if (ATSFontGetTable(atsFont, MAKE_TAG('h', 'h', 'e', 'a'), 4, 6, &metrics, 0) == noErr) { - metrics.ascender = qFromBigEndian<quint16>(metrics.ascender); - metrics.descender = qFromBigEndian<quint16>(metrics.descender); - metrics.linegap = qFromBigEndian<quint16>(metrics.linegap); - } - props.ascent = metrics.ascender; - props.descent = -metrics.descender; - props.leading = metrics.linegap; - props.boundingBox = QRectF(bbox.xMin, -bbox.yMax, - bbox.xMax - bbox.xMin, - bbox.yMax - bbox.yMin); - props.italicAngle = 0; - props.capHeight = props.ascent; - - qint16 lw = 0; - // fonts lie - if (ATSFontGetTable(atsFont, MAKE_TAG('p', 'o', 's', 't'), 10, 2, &lw, 0) == noErr) - lw = qFromBigEndian<quint16>(lw); - props.lineWidth = lw; - - // CTFontCopyPostScriptName - QCFString psName; - if (ATSFontGetPostScriptName(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &psName) == noErr) - props.postscriptName = QString(psName).toUtf8(); - props.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(props.postscriptName); - return props; -} - -void QFontEngineMac::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - ATSUStyle unscaledStyle; - ATSUCreateAndCopyStyle(style, &unscaledStyle); - - int emSquare = properties().emSquare.toInt(); - - const int maxAttributeCount = 4; - ATSUAttributeTag tags[maxAttributeCount + 1]; - ByteCount sizes[maxAttributeCount + 1]; - ATSUAttributeValuePtr values[maxAttributeCount + 1]; - int attributeCount = 0; - - Fixed size = FixRatio(emSquare, 1); - tags[attributeCount] = kATSUSizeTag; - sizes[attributeCount] = sizeof(size); - values[attributeCount] = &size; - ++attributeCount; - - Q_ASSERT(attributeCount < maxAttributeCount + 1); - OSStatus err = ATSUSetAttributes(unscaledStyle, attributeCount, tags, sizes, values); - Q_ASSERT(err == noErr); - Q_UNUSED(err); - - // various CTFont metrics functions: CTFontGetBoundingRectsForGlyphs, CTFontGetAdvancesForGlyphs - GlyphID atsuGlyph = glyph; - ATSGlyphScreenMetrics atsuMetrics; - ATSUGlyphGetScreenMetrics(unscaledStyle, 1, &atsuGlyph, 0, - /* iForcingAntiAlias =*/ false, - /* iAntiAliasSwitch =*/true, - &atsuMetrics); - - metrics->width = int(atsuMetrics.width); - metrics->height = int(atsuMetrics.height); - metrics->x = QFixed::fromReal(atsuMetrics.topLeft.x); - metrics->y = -QFixed::fromReal(atsuMetrics.topLeft.y); - metrics->xoff = QFixed::fromReal(atsuMetrics.deviceAdvance.x); - metrics->yoff = QFixed::fromReal(atsuMetrics.deviceAdvance.y); - - QFixedPoint p; - addGlyphsToPathHelper(unscaledStyle, &glyph, &p, 1, path); - - ATSUDisposeStyle(unscaledStyle); -} -#endif // !QT_MAC_USE_COCOA - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_mac_p.h b/src/gui/text/qfontengine_mac_p.h deleted file mode 100644 index 292ea98d9a..0000000000 --- a/src/gui/text/qfontengine_mac_p.h +++ /dev/null @@ -1,165 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_MAC_P_H -#define QFONTENGINE_MAC_P_H - -#include <private/qfontengine_p.h> - -#ifndef QT_MAC_USE_COCOA -class QFontEngineMacMulti; -class QFontEngineMac : public QFontEngine -{ - friend class QFontEngineMacMulti; -public: - QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFontDef &def, QFontEngineMacMulti *multiEngine = 0); - virtual ~QFontEngineMac(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *numGlyphs, QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t glyph); - - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual QFixed xHeight() const; - virtual qreal maxCharWidth() const; - virtual QFixed averageCharWidth() const; - - virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, - QPainterPath *path, QTextItem::RenderFlags); - - virtual const char *name() const { return "QFontEngineMac"; } - - virtual bool canRender(const QChar *string, int len); - - virtual int synthesized() const { return synthesisFlags; } - - virtual Type type() const { return QFontEngine::Mac; } - - void draw(CGContextRef ctx, qreal x, qreal y, const QTextItemInt &ti, int paintDeviceHeight); - - virtual FaceId faceId() const; - virtual QByteArray getSfntTable(uint tag) const; - virtual Properties properties() const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual QImage alphaMapForGlyph(glyph_t); - virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); - -private: - QImage imageForGlyph(glyph_t glyph, int margin, bool colorful); - - ATSUFontID fontID; - QCFType<CGFontRef> cgFont; - ATSUStyle style; - int synthesisFlags; - mutable QGlyphLayout kashidaGlyph; - QFontEngineMacMulti *multiEngine; - mutable const unsigned char *cmap; - mutable bool symbolCMap; - mutable QByteArray cmapTable; - CGAffineTransform transform; - QFixed m_ascent; - QFixed m_descent; - QFixed m_leading; - qreal m_maxCharWidth; - QFixed m_xHeight; - QFixed m_averageCharWidth; -}; - -class QFontEngineMacMulti : public QFontEngineMulti -{ - friend class QFontEngineMac; -public: - // internal - struct ShaperItem - { - inline ShaperItem() : string(0), from(0), length(0), - log_clusters(0), charAttributes(0) {} - - const QChar *string; - int from; - int length; - QGlyphLayout glyphs; - unsigned short *log_clusters; - const HB_CharAttributes *charAttributes; - QTextEngine::ShaperFlags flags; - }; - - QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, const ATSFontRef &atsFontRef, const QFontDef &fontDef, bool kerning); - virtual ~QFontEngineMacMulti(); - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, - unsigned short *logClusters, const HB_CharAttributes *charAttributes, QScriptItem *) const; - - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual const char *name() const { return "ATSUI"; } - - virtual bool canRender(const QChar *string, int len); - - inline ATSUFontID macFontID() const { return fontID; } - -protected: - virtual void loadEngine(int at); - -private: - inline const QFontEngineMac *engineAt(int i) const - { return static_cast<const QFontEngineMac *>(engines.at(i)); } - - bool stringToCMapInternal(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags, ShaperItem *item) const; - - int fontIndexForFontID(ATSUFontID id) const; - - ATSUFontID fontID; - uint kerning : 1; - - mutable ATSUTextLayout textLayout; - mutable ATSUStyle style; - CGAffineTransform transform; -}; -#endif //!QT_MAC_USE_COCOA - -#endif // QFONTENGINE_MAC_P_H diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index 851bb5964c..b1d25b7d0f 100644 --- a/src/gui/text/qfontengine_qpa.cpp +++ b/src/gui/text/qfontengine_qpa.cpp @@ -46,7 +46,6 @@ #include <QtCore/QDir> #include <QtCore/QBuffer> -#include <QtGui/private/qapplication_p.h> #include <QtGui/QPlatformFontDatabase> #include <QtGui/private/qpaintengine_raster_p.h> diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp deleted file mode 100644 index b71c4a7aba..0000000000 --- a/src/gui/text/qfontengine_qws.cpp +++ /dev/null @@ -1,665 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_p.h" -#include <private/qunicodetables_p.h> -#include <qwsdisplay_qws.h> -#include <qvarlengtharray.h> -#include <private/qpainter_p.h> -#include <private/qpaintengine_raster_p.h> -#include <private/qpdf_p.h> -#include "qtextengine_p.h" -#include "private/qcore_unix_p.h" // overrides QT_OPEN - -#include <qdebug.h> - - -#ifndef QT_NO_QWS_QPF - -#include "qfile.h" -#include "qdir.h" - -#define QT_USE_MMAP -#include <stdlib.h> - -#ifdef QT_USE_MMAP -// for mmap -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/mman.h> -#include <fcntl.h> -#include <errno.h> - -# if defined(QT_LINUXBASE) && !defined(MAP_FILE) - // LSB 3.2 does not define MAP_FILE -# define MAP_FILE 0 -# endif - -#endif - -#endif // QT_NO_QWS_QPF - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_QWS_QPF -QT_BEGIN_INCLUDE_NAMESPACE -#include "qplatformdefs.h" -QT_END_INCLUDE_NAMESPACE - -static inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { - uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; - ++i; - } - } - return uc; -} - -#define FM_SMOOTH 1 - - -class Q_PACKED QPFGlyphMetrics { - -public: - quint8 linestep; - quint8 width; - quint8 height; - quint8 flags; - - qint8 bearingx; // Difference from pen position to glyph's left bbox - quint8 advance; // Difference between pen positions - qint8 bearingy; // Used for putting characters on baseline - - qint8 reserved; // Do not use - - // Flags: - // RendererOwnsData - the renderer is responsible for glyph data - // memory deletion otherwise QPFGlyphTree must - // delete [] the data when the glyph is deleted. - enum Flags { RendererOwnsData=0x01 }; -}; - -class QPFGlyph { -public: - QPFGlyph() { metrics=0; data=0; } - QPFGlyph(QPFGlyphMetrics* m, uchar* d) : - metrics(m), data(d) { } - ~QPFGlyph() {} - - QPFGlyphMetrics* metrics; - uchar* data; -}; - -struct Q_PACKED QPFFontMetrics{ - qint8 ascent,descent; - qint8 leftbearing,rightbearing; - quint8 maxwidth; - qint8 leading; - quint8 flags; - quint8 underlinepos; - quint8 underlinewidth; - quint8 reserved3; -}; - - -class QPFGlyphTree { -public: - /* reads in a tree like this: - - A-Z - / \ - 0-9 a-z - - etc. - - */ - glyph_t min,max; - QPFGlyphTree* less; - QPFGlyphTree* more; - QPFGlyph* glyph; -public: -#ifdef QT_USE_MMAP - QPFGlyphTree(uchar*& data) - { - read(data); - } -#else - QPFGlyphTree(QIODevice& f) - { - read(f); - } -#endif - - ~QPFGlyphTree() - { - // NOTE: does not delete glyph[*].metrics or .data. - // the caller does this (only they know who owns - // the data). See clear(). - delete less; - delete more; - delete [] glyph; - } - - bool inFont(glyph_t g) const - { - if ( g < min ) { - if ( !less ) - return false; - return less->inFont(g); - } else if ( g > max ) { - if ( !more ) - return false; - return more->inFont(g); - } - return true; - } - - QPFGlyph* get(glyph_t g) - { - if ( g < min ) { - if ( !less ) - return 0; - return less->get(g); - } else if ( g > max ) { - if ( !more ) - return 0; - return more->get(g); - } - return &glyph[g - min]; - } - int totalChars() const - { - if ( !this ) return 0; - return max-min+1 + less->totalChars() + more->totalChars(); - } - int weight() const - { - if ( !this ) return 0; - return 1 + less->weight() + more->weight(); - } - - void dump(int indent=0) - { - for (int i=0; i<indent; i++) printf(" "); - printf("%d..%d",min,max); - //if ( indent == 0 ) - printf(" (total %d)",totalChars()); - printf("\n"); - if ( less ) less->dump(indent+1); - if ( more ) more->dump(indent+1); - } - -private: - QPFGlyphTree() - { - } - -#ifdef QT_USE_MMAP - void read(uchar*& data) - { - // All node data first - readNode(data); - // Then all non-video data - readMetrics(data); - // Then all video data - readData(data); - } -#else - void read(QIODevice& f) - { - // All node data first - readNode(f); - // Then all non-video data - readMetrics(f); - // Then all video data - readData(f); - } -#endif - -#ifdef QT_USE_MMAP - void readNode(uchar*& data) - { - uchar rw = *data++; - uchar cl = *data++; - min = (rw << 8) | cl; - rw = *data++; - cl = *data++; - max = (rw << 8) | cl; - int flags = *data++; - if ( flags & 1 ) - less = new QPFGlyphTree; - else - less = 0; - if ( flags & 2 ) - more = new QPFGlyphTree; - else - more = 0; - int n = max-min+1; - glyph = new QPFGlyph[n]; - - if ( less ) - less->readNode(data); - if ( more ) - more->readNode(data); - } -#else - void readNode(QIODevice& f) - { - char rw; - char cl; - f.getChar(&rw); - f.getChar(&cl); - min = (rw << 8) | cl; - f.getChar(&rw); - f.getChar(&cl); - max = (rw << 8) | cl; - char flags; - f.getChar(&flags); - if ( flags & 1 ) - less = new QPFGlyphTree; - else - less = 0; - if ( flags & 2 ) - more = new QPFGlyphTree; - else - more = 0; - int n = max-min+1; - glyph = new QPFGlyph[n]; - - if ( less ) - less->readNode(f); - if ( more ) - more->readNode(f); - } -#endif - -#ifdef QT_USE_MMAP - void readMetrics(uchar*& data) - { - int n = max-min+1; - for (int i=0; i<n; i++) { - glyph[i].metrics = (QPFGlyphMetrics*)data; - data += sizeof(QPFGlyphMetrics); - } - if ( less ) - less->readMetrics(data); - if ( more ) - more->readMetrics(data); - } -#else - void readMetrics(QIODevice& f) - { - int n = max-min+1; - for (int i=0; i<n; i++) { - glyph[i].metrics = new QPFGlyphMetrics; - f.read((char*)glyph[i].metrics, sizeof(QPFGlyphMetrics)); - } - if ( less ) - less->readMetrics(f); - if ( more ) - more->readMetrics(f); - } -#endif - -#ifdef QT_USE_MMAP - void readData(uchar*& data) - { - int n = max-min+1; - for (int i=0; i<n; i++) { - QSize s( glyph[i].metrics->width, glyph[i].metrics->height ); - //######### s = qt_screen->mapToDevice( s ); - uint datasize = glyph[i].metrics->linestep * s.height(); - glyph[i].data = data; data += datasize; - } - if ( less ) - less->readData(data); - if ( more ) - more->readData(data); - } -#else - void readData(QIODevice& f) - { - int n = max-min+1; - for (int i=0; i<n; i++) { - QSize s( glyph[i].metrics->width, glyph[i].metrics->height ); - //############### s = qt_screen->mapToDevice( s ); - uint datasize = glyph[i].metrics->linestep * s.height(); - glyph[i].data = new uchar[datasize]; // ### deleted? - f.read((char*)glyph[i].data, datasize); - } - if ( less ) - less->readData(f); - if ( more ) - more->readData(f); - } -#endif - -}; - -class QFontEngineQPF1Data -{ -public: - QPFFontMetrics fm; - QPFGlyphTree *tree; - void *mmapStart; - size_t mmapLength; -}; - -#if defined(Q_OS_INTEGRITY) -static void *qt_mmap(void *start, size_t length, int /*prot*/, int /*flags*/, int fd, off_t offset) -{ - // INTEGRITY cannot mmap local files - load it into a local buffer - if (::lseek(fd, offset, SEEK_SET) == -1) { -# if defined(DEBUG_FONTENGINE) - perror("lseek failed"); -# endif - } - void *buf = malloc(length); - if (::read(fd, buf, length) != (ssize_t)length) { -# if defined(DEBUG_FONTENGINE) - perror("read failed"); -# endif - } - - return buf; -} -#else -static inline void *qt_mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) -{ - return mmap(start, length, prot, flags, fd, offset); -} -#endif - - - -QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) -{ - cache_cost = 1; - - int f = QT_OPEN( QFile::encodeName(fn), O_RDONLY, 0); - Q_ASSERT(f>=0); - QT_STATBUF st; - if ( QT_FSTAT( f, &st ) ) - qFatal("Failed to stat %s",QFile::encodeName(fn).data()); - uchar* data = (uchar*)qt_mmap( 0, // any address - st.st_size, // whole file - PROT_READ, // read-only memory -#if defined(Q_OS_INTEGRITY) - 0, -#elif !defined(Q_OS_SOLARIS) && !defined(Q_OS_QNX4) && !defined(Q_OS_VXWORKS) - MAP_FILE | MAP_PRIVATE, // swap-backed map from file -#else - MAP_PRIVATE, -#endif - f, 0 ); // from offset 0 of f -#if !defined(MAP_FAILED) && (defined(Q_OS_QNX4) || defined(Q_OS_INTEGRITY)) -#define MAP_FAILED ((void *)-1) -#endif - if ( !data || data == (uchar*)MAP_FAILED ) - qFatal("Failed to mmap %s",QFile::encodeName(fn).data()); - QT_CLOSE(f); - - d = new QFontEngineQPF1Data; - d->mmapStart = data; - d->mmapLength = st.st_size; - memcpy(reinterpret_cast<char*>(&d->fm),data,sizeof(d->fm)); - - data += sizeof(d->fm); - d->tree = new QPFGlyphTree(data); - glyphFormat = (d->fm.flags & FM_SMOOTH) ? QFontEngineGlyphCache::Raster_A8 - : QFontEngineGlyphCache::Raster_Mono; -#if 0 - qDebug() << "font file" << fn - << "ascent" << d->fm.ascent << "descent" << d->fm.descent - << "leftbearing" << d->fm.leftbearing - << "rightbearing" << d->fm.rightbearing - << "maxwidth" << d->fm.maxwidth - << "leading" << d->fm.leading - << "flags" << d->fm.flags - << "underlinepos" << d->fm.underlinepos - << "underlinewidth" << d->fm.underlinewidth; -#endif -} - -QFontEngineQPF1::~QFontEngineQPF1() -{ - if (d->mmapStart) - munmap(d->mmapStart, d->mmapLength); - delete d->tree; - delete d; -} - - -bool QFontEngineQPF1::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if(*nglyphs < len) { - *nglyphs = len; - return false; - } - *nglyphs = 0; - - bool mirrored = flags & QTextEngine::RightToLeft; - for(int i = 0; i < len; i++) { - unsigned int uc = getChar(str, i, len); - if (mirrored) - uc = QChar::mirroredChar(uc); - glyphs->glyphs[*nglyphs] = uc < 0x10000 ? uc : 0; - ++*nglyphs; - } - - glyphs->numGlyphs = *nglyphs; - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - recalcAdvances(glyphs, flags); - - return true; -} - -void QFontEngineQPF1::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const -{ - for(int i = 0; i < glyphs->numGlyphs; i++) { - QPFGlyph *glyph = d->tree->get(glyphs->glyphs[i]); - - glyphs->advances_x[i] = glyph ? glyph->metrics->advance : 0; - glyphs->advances_y[i] = 0; - - if (!glyph) - glyphs->glyphs[i] = 0; - } -} - -void QFontEngineQPF1::draw(QPaintEngine *p, qreal _x, qreal _y, const QTextItemInt &si) -{ - QPaintEngineState *pState = p->state; - QRasterPaintEngine *paintEngine = static_cast<QRasterPaintEngine*>(p); - - QTransform matrix = pState->transform(); - matrix.translate(_x, _y); - QFixed x = QFixed::fromReal(matrix.dx()); - QFixed y = QFixed::fromReal(matrix.dy()); - - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - getGlyphPositions(si.glyphs, matrix, si.flags, glyphs, positions); - if (glyphs.size() == 0) - return; - - int depth = (d->fm.flags & FM_SMOOTH) ? 8 : 1; - for(int i = 0; i < glyphs.size(); i++) { - const QPFGlyph *glyph = d->tree->get(glyphs[i]); - if (!glyph) - continue; - - int bpl = glyph->metrics->linestep; - - if(glyph->data) - paintEngine->alphaPenBlt(glyph->data, bpl, depth, - qRound(positions[i].x) + glyph->metrics->bearingx, - qRound(positions[i].y) - glyph->metrics->bearingy, - glyph->metrics->width,glyph->metrics->height); - } -} - - -QImage QFontEngineQPF1::alphaMapForGlyph(glyph_t g) -{ - const QPFGlyph *glyph = d->tree->get(g); - if (!glyph) - return QImage(); - - int mono = !(d->fm.flags & FM_SMOOTH); - - const uchar *bits = glyph->data;//((const uchar *) glyph); - - QImage image; - if (mono) { - image = QImage((glyph->metrics->width+7)&~7, glyph->metrics->height, QImage::Format_Mono); - image.setColor(0, qRgba(0, 0, 0, 0)); - image.setColor(1, qRgba(0, 0, 0, 255)); - } else { - image = QImage(glyph->metrics->width, glyph->metrics->height, QImage::Format_Indexed8); - for (int j=0; j<256; ++j) - image.setColor(j, qRgba(0, 0, 0, j)); - } - for (int i=0; i<glyph->metrics->height; ++i) { - memcpy(image.scanLine(i), bits, glyph->metrics->linestep); - bits += glyph->metrics->linestep; - } - return image; -} - - - -void QFontEngineQPF1::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) -{ - addBitmapFontToPath(x, y, glyphs, path, flags); -} - -glyph_metrics_t QFontEngineQPF1::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); -} - -glyph_metrics_t QFontEngineQPF1::boundingBox(glyph_t glyph) -{ - const QPFGlyph *g = d->tree->get(glyph); - if (!g) - return glyph_metrics_t(); - Q_ASSERT(g); - return glyph_metrics_t(g->metrics->bearingx, -g->metrics->bearingy, - g->metrics->width, g->metrics->height, - g->metrics->advance, 0); -} - -QFixed QFontEngineQPF1::ascent() const -{ - return d->fm.ascent; -} - -QFixed QFontEngineQPF1::descent() const -{ - return d->fm.descent; -} - -QFixed QFontEngineQPF1::leading() const -{ - return d->fm.leading; -} - -qreal QFontEngineQPF1::maxCharWidth() const -{ - return d->fm.maxwidth; -} -/* -const char *QFontEngineQPF1::name() const -{ - return "qt"; -} -*/ -bool QFontEngineQPF1::canRender(const QChar *str, int len) -{ - for(int i = 0; i < len; i++) - if (!d->tree->inFont(str[i].unicode())) - return false; - return true; -} - -QFontEngine::Type QFontEngineQPF1::type() const -{ - return QPF1; -} - -qreal QFontEngineQPF1::minLeftBearing() const -{ - return d->fm.leftbearing; -} - -qreal QFontEngineQPF1::minRightBearing() const -{ - return d->fm.rightbearing; -} - -QFixed QFontEngineQPF1::underlinePosition() const -{ - return d->fm.underlinepos; -} - -QFixed QFontEngineQPF1::lineThickness() const -{ - return d->fm.underlinewidth; -} - -#endif //QT_NO_QWS_QPF - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp deleted file mode 100644 index e9b54e350f..0000000000 --- a/src/gui/text/qfontengine_s60.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qfontengine_s60_p.h" -#include "qtextengine_p.h" -#include "qendian.h" -#include "qglobal.h" -#include <private/qapplication_p.h> -#include "qimage.h" -#include <private/qt_s60_p.h> -#include <private/qpixmap_s60_p.h> - -#include <e32base.h> -#include <e32std.h> -#include <eikenv.h> -#include <gdi.h> -#if defined(Q_SYMBIAN_HAS_GLYPHOUTLINE_API) -#include <graphics/gdi/gdiplatapi.h> -#endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API - -// Replication of TGetFontTableParam & friends. -// There is unfortunately no compile time flag like SYMBIAN_FONT_TABLE_API -// that would help us to only replicate these things for Symbian versions -// that do not yet have the font table Api. Symbian's public SDK does -// generally not define any usable macros. -class QSymbianTGetFontTableParam -{ -public: - TUint32 iTag; - TAny *iContent; - TInt iLength; -}; -const TUid QSymbianKFontGetFontTable = {0x102872C1}; -const TUid QSymbianKFontReleaseFontTable = {0x2002AC24}; - -QT_BEGIN_NAMESPACE - -QSymbianTypeFaceExtras::QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont) - : m_cFont(cFont) - , m_symbolCMap(false) - , m_openFont(openFont) -{ - if (!symbianFontTableApiAvailable()) { - TAny *trueTypeExtension = NULL; - m_openFont->ExtendedInterface(KUidOpenFontTrueTypeExtension, trueTypeExtension); - m_trueTypeExtension = static_cast<MOpenFontTrueTypeExtension*>(trueTypeExtension); - Q_ASSERT(m_trueTypeExtension); - } -} - -QSymbianTypeFaceExtras::~QSymbianTypeFaceExtras() -{ - if (symbianFontTableApiAvailable()) - S60->screenDevice()->ReleaseFont(m_cFont); -} - -QByteArray QSymbianTypeFaceExtras::getSfntTable(uint tag) const -{ - if (symbianFontTableApiAvailable()) { - QSymbianTGetFontTableParam fontTableParams = { tag, 0, 0 }; - if (m_cFont->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { - const char* const fontTableContent = - static_cast<const char *>(fontTableParams.iContent); - const QByteArray fontTable(fontTableContent, fontTableParams.iLength); - m_cFont->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); - return fontTable; - } - return QByteArray(); - } else { - Q_ASSERT(m_trueTypeExtension->HasTrueTypeTable(tag)); - TInt error = KErrNone; - TInt tableByteLength = 0; - TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); - Q_CHECK_PTR(table); - const QByteArray result(static_cast<const char*>(table), tableByteLength); - m_trueTypeExtension->ReleaseTrueTypeTable(table); - return result; - } -} - -bool QSymbianTypeFaceExtras::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - bool result = true; - if (symbianFontTableApiAvailable()) { - QSymbianTGetFontTableParam fontTableParams = { tag, 0, 0 }; - if (m_cFont->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { - if (*length > 0 && *length < fontTableParams.iLength) { - result = false; // Caller did not allocate enough memory - } else { - *length = fontTableParams.iLength; - if (buffer) - memcpy(buffer, fontTableParams.iContent, fontTableParams.iLength); - } - m_cFont->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); - } else { - result = false; - } - } else { - if (!m_trueTypeExtension->HasTrueTypeTable(tag)) - return false; - - TInt error = KErrNone; - TInt tableByteLength; - TAny *table = m_trueTypeExtension->GetTrueTypeTable(error, tag, &tableByteLength); - Q_CHECK_PTR(table); - - if (error != KErrNone) { - return false; - } else if (*length > 0 && *length < tableByteLength) { - result = false; // Caller did not allocate enough memory - } else { - *length = tableByteLength; - if (buffer) - memcpy(buffer, table, tableByteLength); - } - - m_trueTypeExtension->ReleaseTrueTypeTable(table); - } - return result; -} - -const uchar *QSymbianTypeFaceExtras::cmap() const -{ - if (m_cmapTable.isNull()) { - const QByteArray cmapTable = getSfntTable(MAKE_TAG('c', 'm', 'a', 'p')); - int size = 0; - const uchar *cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *> - (cmapTable.constData()), cmapTable.size(), &m_symbolCMap, &size); - m_cmapTable = QByteArray(reinterpret_cast<const char *>(cmap), size); - } - return reinterpret_cast<const uchar *>(m_cmapTable.constData()); -} - -bool QSymbianTypeFaceExtras::isSymbolCMap() const -{ - return m_symbolCMap; -} - -CFont *QSymbianTypeFaceExtras::fontOwner() const -{ - return m_cFont; -} - -QFixed QSymbianTypeFaceExtras::unitsPerEm() const -{ - if (m_unitsPerEm.value() != 0) - return m_unitsPerEm; - const QByteArray head = getSfntTable(MAKE_TAG('h', 'e', 'a', 'd')); - const int unitsPerEmOffset = 18; - if (head.size() > unitsPerEmOffset + sizeof(quint16)) { - const uchar* tableData = reinterpret_cast<const uchar*>(head.constData()); - const uchar* unitsPerEm = tableData + unitsPerEmOffset; - m_unitsPerEm = qFromBigEndian<quint16>(unitsPerEm); - } else { - // Bitmap font? Corrupt font? - // We return -1 and let the QFontEngineS60 return the pixel size. - m_unitsPerEm = -1; - } - return m_unitsPerEm; -} - -bool QSymbianTypeFaceExtras::symbianFontTableApiAvailable() -{ - enum FontTableApiAvailability { - Unknown, - Available, - Unavailable - }; - static FontTableApiAvailability availability = - QSysInfo::symbianVersion() < QSysInfo::SV_SF_3 ? - Unavailable : Unknown; - if (availability == Unknown) { - // Actually, we should ask CFeatureDiscovery::IsFeatureSupportedL() - // with FfFontTable here. But since at the time of writing, the - // FfFontTable flag check either gave false positives or false - // negatives. Here comes an implicit check via CFont::ExtendedFunction. - QSymbianTGetFontTableParam fontTableParams = { - MAKE_TAG('O', 'S', '/', '2'), 0, 0 }; - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - CFont *font; - const TInt getFontErr = S60->screenDevice()->GetNearestFontInTwips(font, TFontSpec()); - Q_ASSERT(getFontErr == KErrNone); - if (font->ExtendedFunction(QSymbianKFontGetFontTable, &fontTableParams) == KErrNone) { - font->ExtendedFunction(QSymbianKFontReleaseFontTable, &fontTableParams); - availability = Available; - } else { - availability = Unavailable; - } - S60->screenDevice()->ReleaseFont(font); - lock.relock(); - } - return availability == Available; -} - -// duplicated from qfontengine_xyz.cpp -static inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { - uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; - ++i; - } - } - return uc; -} - -extern QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName); // qfontdatabase_s60.cpp - -CFont *QFontEngineS60::fontWithSize(qreal size) const -{ - CFont *result = 0; - const QString family = qt_symbian_fontNameWithAppFontMarker(QFontEngine::fontDef.family); - TFontSpec fontSpec(qt_QString2TPtrC(family), TInt(size)); - fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); - fontSpec.iFontStyle.SetPosture(QFontEngine::fontDef.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); - fontSpec.iFontStyle.SetStrokeWeight(QFontEngine::fontDef.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal); - const TInt errorCode = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(result, fontSpec); - Q_ASSERT(result && (errorCode == 0)); - return result; -} - -void QFontEngineS60::setFontScale(qreal scale) -{ - if (qFuzzyCompare(scale, qreal(1))) { - if (!m_originalFont) - m_originalFont = fontWithSize(m_originalFontSizeInPixels); - m_activeFont = m_originalFont; - } else { - const qreal scaledFontSizeInPixels = m_originalFontSizeInPixels * scale; - if (!m_scaledFont || - (TInt(scaledFontSizeInPixels) != TInt(m_scaledFontSizeInPixels))) { - releaseFont(m_scaledFont); - m_scaledFontSizeInPixels = scaledFontSizeInPixels; - m_scaledFont = fontWithSize(m_scaledFontSizeInPixels); - } - m_activeFont = m_scaledFont; - } -} - -void QFontEngineS60::releaseFont(CFont *&font) -{ - if (font) { - S60->screenDevice()->ReleaseFont(font); - font = 0; - } -} - -QFontEngineS60::QFontEngineS60(const QFontDef &request, const QSymbianTypeFaceExtras *extras) - : m_extras(extras) - , m_originalFont(0) - , m_originalFontSizeInPixels((request.pixelSize >= 0)? - request.pixelSize:pointsToPixels(request.pointSize)) - , m_scaledFont(0) - , m_scaledFontSizeInPixels(0) - , m_activeFont(0) -{ - QFontEngine::fontDef = request; - setFontScale(1.0); - cache_cost = sizeof(QFontEngineS60); -} - -QFontEngineS60::~QFontEngineS60() -{ - releaseFont(m_originalFont); - releaseFont(m_scaledFont); -} - -QFixed QFontEngineS60::emSquareSize() const -{ - const QFixed unitsPerEm = m_extras->unitsPerEm(); - return unitsPerEm.toInt() == -1 ? - QFixed::fromReal(m_originalFontSizeInPixels) : unitsPerEm; -} - -bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - HB_Glyph *g = glyphs->glyphs; - const unsigned char* cmap = m_extras->cmap(); - const bool isRtl = (flags & QTextEngine::RightToLeft); - for (int i = 0; i < len; ++i) { - const unsigned int uc = getChar(characters, i, len); - *g++ = QFontEngine::getTrueTypeGlyphIndex(cmap, - (isRtl && !m_extras->isSymbolCMap()) ? QChar::mirroredChar(uc) : uc); - } - - glyphs->numGlyphs = g - glyphs->glyphs; - *nglyphs = glyphs->numGlyphs; - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - recalcAdvances(glyphs, flags); - return true; -} - -void QFontEngineS60::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - Q_UNUSED(flags); - TOpenFontCharMetrics metrics; - const TUint8 *glyphBitmapBytes; - TSize glyphBitmapSize; - for (int i = 0; i < glyphs->numGlyphs; i++) { - getCharacterData(glyphs->glyphs[i], metrics, glyphBitmapBytes, glyphBitmapSize); - glyphs->advances_x[i] = metrics.HorizAdvance(); - glyphs->advances_y[i] = 0; - } -} - -#ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API -static bool parseGlyphPathData(const char *dataStr, const char *dataEnd, QPainterPath &path, - qreal fontPixelSize, const QPointF &offset, bool hinted); -#endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API - -void QFontEngineS60::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, - int nglyphs, QPainterPath *path, - QTextItem::RenderFlags flags) -{ -#ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API - Q_UNUSED(flags) - RGlyphOutlineIterator iterator; - const TInt error = iterator.Open(*m_activeFont, glyphs, nglyphs); - if (KErrNone != error) - return; - const qreal fontSizeInPixels = qreal(m_activeFont->HeightInPixels()); - int count = 0; - do { - const TUint8* outlineUint8 = iterator.Outline(); - const char* const outlineChar = reinterpret_cast<const char*>(outlineUint8); - const char* const outlineEnd = outlineChar + iterator.OutlineLength(); - parseGlyphPathData(outlineChar, outlineEnd, *path, fontSizeInPixels, - positions[count++].toPointF(), false); - } while(KErrNone == iterator.Next() && count <= nglyphs); - iterator.Close(); -#else // Q_SYMBIAN_HAS_GLYPHOUTLINE_API - QFontEngine::addGlyphsToPath(glyphs, positions, nglyphs, path, flags); -#endif //Q_SYMBIAN_HAS_GLYPHOUTLINE_API -} - -QImage QFontEngineS60::alphaMapForGlyph(glyph_t glyph) -{ - // Note: On some Symbian versions (apparently <= Symbian^1), this - // function will return gray values 0x00, 0x10 ... 0xe0, 0xf0 due - // to a bug. The glyphs are nowhere perfectly opaque. - // This has been fixed for Symbian^3. - - TOpenFontCharMetrics metrics; - const TUint8 *glyphBitmapBytes; - TSize glyphBitmapSize; - getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); - QImage result(glyphBitmapBytes, glyphBitmapSize.iWidth, glyphBitmapSize.iHeight, glyphBitmapSize.iWidth, QImage::Format_Indexed8); - result.setColorTable(grayPalette()); - return result; -} - -glyph_metrics_t QFontEngineS60::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -ascent(), w - lastRightBearing(glyphs), ascent()+descent()+1, w, 0); -} - -glyph_metrics_t QFontEngineS60::boundingBox_const(glyph_t glyph) const -{ - TOpenFontCharMetrics metrics; - const TUint8 *glyphBitmapBytes; - TSize glyphBitmapSize; - getCharacterData(glyph, metrics, glyphBitmapBytes, glyphBitmapSize); - const glyph_metrics_t result( - metrics.HorizBearingX(), - -metrics.HorizBearingY(), - metrics.Width(), - metrics.Height(), - metrics.HorizAdvance(), - 0 - ); - return result; -} - -glyph_metrics_t QFontEngineS60::boundingBox(glyph_t glyph) -{ - return boundingBox_const(glyph); -} - -QFixed QFontEngineS60::ascent() const -{ - // Workaround for QTBUG-8013 - // Stroke based fonts may return an incorrect FontMaxAscent of 0. - const QFixed ascent = m_originalFont->FontMaxAscent(); - return (ascent > 0) ? ascent : QFixed::fromReal(m_originalFontSizeInPixels) - descent(); -} - -QFixed QFontEngineS60::descent() const -{ - return m_originalFont->FontMaxDescent(); -} - -QFixed QFontEngineS60::leading() const -{ - return 0; -} - -qreal QFontEngineS60::maxCharWidth() const -{ - return m_originalFont->MaxCharWidthInPixels(); -} - -const char *QFontEngineS60::name() const -{ - return "QFontEngineS60"; -} - -bool QFontEngineS60::canRender(const QChar *string, int len) -{ - const unsigned char *cmap = m_extras->cmap(); - for (int i = 0; i < len; ++i) { - const unsigned int uc = getChar(string, i, len); - if (QFontEngine::getTrueTypeGlyphIndex(cmap, uc) == 0) - return false; - } - return true; -} - -QByteArray QFontEngineS60::getSfntTable(uint tag) const -{ - return m_extras->getSfntTable(tag); -} - -bool QFontEngineS60::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - return m_extras->getSfntTableData(tag, buffer, length); -} - -QFontEngine::Type QFontEngineS60::type() const -{ - return QFontEngine::S60FontEngine; -} - -void QFontEngineS60::getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const -{ - // Setting the most significant bit tells GetCharacterData - // that 'code' is a Glyph ID, rather than a UTF-16 value - const TUint specialCode = (TUint)glyph | 0x80000000; - - const CFont::TCharacterDataAvailability availability = - m_activeFont->GetCharacterData(specialCode, metrics, bitmap, bitmapSize); - const glyph_t fallbackGlyph = '?'; - if (availability != CFont::EAllCharacterData) { - const CFont::TCharacterDataAvailability fallbackAvailability = - m_activeFont->GetCharacterData(fallbackGlyph, metrics, bitmap, bitmapSize); - Q_ASSERT(fallbackAvailability == CFont::EAllCharacterData); - } -} - -#ifdef Q_SYMBIAN_HAS_GLYPHOUTLINE_API -static inline void skipSpacesAndComma(const char* &str, const char* const strEnd) -{ - while (str <= strEnd && (*str == ' ' || *str == ',')) - ++str; -} - -static bool parseGlyphPathData(const char *svgPath, const char *svgPathEnd, QPainterPath &path, - qreal fontPixelSize, const QPointF &offset, bool hinted) -{ - Q_UNUSED(hinted) - QPointF p1, p2, firstSubPathPoint; - qreal *elementValues[] = - {&p1.rx(), &p1.ry(), &p2.rx(), &p2.ry()}; - const int unitsPerEm = 2048; // See: http://en.wikipedia.org/wiki/Em_%28typography%29 - const qreal resizeFactor = fontPixelSize / unitsPerEm; - - while (svgPath < svgPathEnd) { - skipSpacesAndComma(svgPath, svgPathEnd); - const char pathElem = *svgPath++; - skipSpacesAndComma(svgPath, svgPathEnd); - - if (pathElem != 'Z') { - char *endStr = 0; - int elementValuesCount = 0; - for (int i = 0; i < 4; ++i) { // 4 = size of elementValues[] - qreal coordinateValue = strtod(svgPath, &endStr); - if (svgPath == endStr) - break; - if (i % 2) // Flip vertically - coordinateValue = -coordinateValue; - *elementValues[i] = coordinateValue * resizeFactor; - elementValuesCount++; - svgPath = endStr; - skipSpacesAndComma(svgPath, svgPathEnd); - } - p1 += offset; - if (elementValuesCount == 2) - p2 = firstSubPathPoint; - else - p2 += offset; - } - - switch (pathElem) { - case 'M': - firstSubPathPoint = p1; - path.moveTo(p1); - break; - case 'Z': - path.closeSubpath(); - break; - case 'L': - path.lineTo(p1); - break; - case 'Q': - path.quadTo(p1, p2); - break; - default: - return false; - } - } - return true; -} -#endif // Q_SYMBIAN_HAS_GLYPHOUTLINE_API - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h deleted file mode 100644 index c0eeef5264..0000000000 --- a/src/gui/text/qfontengine_s60_p.h +++ /dev/null @@ -1,167 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_S60_P_H -#define QFONTENGINE_S60_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qconfig.h" -#include <private/qfontengine_p.h> -#include "qsize.h" -#include <openfont.h> - -// The glyph outline code is intentionally disabled. It will be reactivated as -// soon as the glyph outline API is backported from Symbian(^4) to Symbian(^3). -#if 0 -#define Q_SYMBIAN_HAS_GLYPHOUTLINE_API -#endif - -class CFont; - -QT_BEGIN_NAMESPACE - -// ..gives us access to truetype tables -class QSymbianTypeFaceExtras -{ -public: - QSymbianTypeFaceExtras(CFont* cFont, COpenFont *openFont = 0); - ~QSymbianTypeFaceExtras(); - - QByteArray getSfntTable(uint tag) const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - const uchar *cmap() const; - CFont *fontOwner() const; - bool isSymbolCMap() const; - QFixed unitsPerEm() const; - static bool symbianFontTableApiAvailable(); - -private: - CFont* m_cFont; - mutable bool m_symbolCMap; - mutable QByteArray m_cmapTable; - mutable QFixed m_unitsPerEm; - - // m_openFont and m_openFont are used if Symbian does not provide - // the Font Table API - COpenFont *m_openFont; - mutable MOpenFontTrueTypeExtension *m_trueTypeExtension; -}; - -class QFontEngineS60 : public QFontEngine -{ -public: - QFontEngineS60(const QFontDef &fontDef, const QSymbianTypeFaceExtras *extras); - ~QFontEngineS60(); - - QFixed emSquareSize() const; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const; - - void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); - - QImage alphaMapForGlyph(glyph_t glyph); - - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - glyph_metrics_t boundingBox_const(glyph_t glyph) const; // Const correctnes quirk. - glyph_metrics_t boundingBox(glyph_t glyph); - - QFixed ascent() const; - QFixed descent() const; - QFixed leading() const; - qreal maxCharWidth() const; - qreal minLeftBearing() const { return 0; } - qreal minRightBearing() const { return 0; } - - QByteArray getSfntTable(uint tag) const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - - static qreal pixelsToPoints(qreal pixels, Qt::Orientation orientation = Qt::Horizontal); - static qreal pointsToPixels(qreal points, Qt::Orientation orientation = Qt::Horizontal); - - const char *name() const; - - bool canRender(const QChar *string, int len); - - Type type() const; - - void getCharacterData(glyph_t glyph, TOpenFontCharMetrics& metrics, const TUint8*& bitmap, TSize& bitmapSize) const; - void setFontScale(qreal scale); - -private: - friend class QFontPrivate; - friend class QSymbianVGFontGlyphCache; - - QFixed glyphAdvance(HB_Glyph glyph) const; - CFont *fontWithSize(qreal size) const; - static void releaseFont(CFont *&font); - - const QSymbianTypeFaceExtras *m_extras; - CFont* m_originalFont; - const qreal m_originalFontSizeInPixels; - CFont* m_scaledFont; - qreal m_scaledFontSizeInPixels; - CFont* m_activeFont; -}; - -class QFontEngineMultiS60 : public QFontEngineMulti -{ -public: - QFontEngineMultiS60(QFontEngine *first, int script, const QStringList &fallbackFamilies); - void loadEngine(int at); - - int m_script; - QStringList m_fallbackFamilies; -}; - -QT_END_NAMESPACE - -#endif // QFONTENGINE_S60_P_H diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp deleted file mode 100644 index 54d7ec2980..0000000000 --- a/src/gui/text/qfontengine_win.cpp +++ /dev/null @@ -1,1339 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#if _WIN32_WINNT < 0x0500 -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0500 -#endif - -#include "qfontengine_p.h" -#include "qtextengine_p.h" -#include <qglobal.h> -#include "qt_windows.h" -#include <private/qapplication_p.h> - -#include <private/qsystemlibrary_p.h> -#include <qpaintdevice.h> -#include <qpainter.h> -#include <limits.h> - -#include <qendian.h> -#include <qmath.h> -#include <qthreadstorage.h> - -#include <private/qunicodetables_p.h> -#include <qbitmap.h> - -#include <private/qpainter_p.h> -#include "qpaintengine.h" -#include "qvarlengtharray.h" -#include <private/qpaintengine_raster_p.h> -#include <private/qnativeimage_p.h> - -#if defined(Q_WS_WINCE) -#include "qguifunctions_wince.h" -#endif - -//### mingw needed define -#ifndef TT_PRIM_CSPLINE -#define TT_PRIM_CSPLINE 3 -#endif - -#ifdef MAKE_TAG -#undef MAKE_TAG -#endif -// GetFontData expects the tags in little endian ;( -#define MAKE_TAG(ch1, ch2, ch3, ch4) (\ - (((quint32)(ch4)) << 24) | \ - (((quint32)(ch3)) << 16) | \ - (((quint32)(ch2)) << 8) | \ - ((quint32)(ch1)) \ - ) - -// common DC for all fonts - -QT_BEGIN_NAMESPACE - -class QtHDC -{ - HDC _hdc; -public: - QtHDC() - { - HDC displayDC = GetDC(0); - _hdc = CreateCompatibleDC(displayDC); - ReleaseDC(0, displayDC); - } - ~QtHDC() - { - if (_hdc) - DeleteDC(_hdc); - } - HDC hdc() const - { - return _hdc; - } -}; - -#ifndef QT_NO_THREAD -Q_GLOBAL_STATIC(QThreadStorage<QtHDC *>, local_shared_dc) -HDC shared_dc() -{ - QtHDC *&hdc = local_shared_dc()->localData(); - if (!hdc) - hdc = new QtHDC; - return hdc->hdc(); -} -#else -HDC shared_dc() -{ - return 0; -} -#endif - -#ifndef Q_WS_WINCE -typedef BOOL (WINAPI *PtrGetCharWidthI)(HDC, UINT, UINT, LPWORD, LPINT); -static PtrGetCharWidthI ptrGetCharWidthI = 0; -static bool resolvedGetCharWidthI = false; - -static void resolveGetCharWidthI() -{ - if (resolvedGetCharWidthI) - return; - resolvedGetCharWidthI = true; - ptrGetCharWidthI = (PtrGetCharWidthI)QSystemLibrary::resolve(QLatin1String("gdi32"), "GetCharWidthI"); -} -#endif // !defined(Q_WS_WINCE) - -// defined in qtextengine_win.cpp -typedef void *SCRIPT_CACHE; -typedef HRESULT (WINAPI *fScriptFreeCache)(SCRIPT_CACHE *); -extern fScriptFreeCache ScriptFreeCache; - -static inline quint32 getUInt(unsigned char *p) -{ - quint32 val; - val = *p++ << 24; - val |= *p++ << 16; - val |= *p++ << 8; - val |= *p; - - return val; -} - -static inline quint16 getUShort(unsigned char *p) -{ - quint16 val; - val = *p++ << 8; - val |= *p; - - return val; -} - -// general font engine - -QFixed QFontEngineWin::lineThickness() const -{ - if(lineWidth > 0) - return lineWidth; - - return QFontEngine::lineThickness(); -} - -static OUTLINETEXTMETRIC *getOutlineTextMetric(HDC hdc) -{ - int size; - size = GetOutlineTextMetrics(hdc, 0, 0); - OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)malloc(size); - GetOutlineTextMetrics(hdc, size, otm); - return otm; -} - -void QFontEngineWin::getCMap() -{ - ttf = (bool)(tm.tmPitchAndFamily & TMPF_TRUETYPE); - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - bool symb = false; - if (ttf) { - cmapTable = getSfntTable(qbswap<quint32>(MAKE_TAG('c', 'm', 'a', 'p'))); - int size = 0; - cmap = QFontEngine::getCMap(reinterpret_cast<const uchar *>(cmapTable.constData()), - cmapTable.size(), &symb, &size); - } - if (!cmap) { - ttf = false; - symb = false; - } - symbol = symb; - designToDevice = 1; - _faceId.index = 0; - if(cmap) { - OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight); - unitsPerEm = otm->otmEMSquare; - x_height = (int)otm->otmsXHeight; - loadKerningPairs(designToDevice); - _faceId.filename = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)).toLatin1(); - lineWidth = otm->otmsUnderscoreSize; - fsType = otm->otmfsType; - free(otm); - } else { - unitsPerEm = tm.tmHeight; - } -} - - -inline unsigned int getChar(const QChar *str, int &i, const int len) -{ - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { - uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; - ++i; - } - } - return uc; -} - -int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs, bool mirrored) const -{ - int i = 0; - int glyph_pos = 0; - if (mirrored) { -#if defined(Q_WS_WINCE) - { -#else - if (symbol) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); - if (!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else if (ttf) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, QChar::mirroredChar(uc)); - } - } else { -#endif - wchar_t first = tm.tmFirstChar; - wchar_t last = tm.tmLastChar; - - for (; i < numChars; ++i, ++glyph_pos) { - uint ucs = QChar::mirroredChar(getChar(str, i, numChars)); - if ( -#ifdef Q_WS_WINCE - tm.tmFirstChar > 60000 || // see line 375 -#endif - ucs >= first && ucs <= last) - glyphs->glyphs[glyph_pos] = ucs; - else - glyphs->glyphs[glyph_pos] = 0; - } - } - } else { -#if defined(Q_WS_WINCE) - { -#else - if (symbol) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[i] = getTrueTypeGlyphIndex(cmap, uc); - if(!glyphs->glyphs[glyph_pos] && uc < 0x100) - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); - } - } else if (ttf) { - for (; i < numChars; ++i, ++glyph_pos) { - unsigned int uc = getChar(str, i, numChars); - glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); - } - } else { -#endif - wchar_t first = tm.tmFirstChar; - wchar_t last = tm.tmLastChar; - - for (; i < numChars; ++i, ++glyph_pos) { - uint uc = getChar(str, i, numChars); - if ( -#ifdef Q_WS_WINCE - tm.tmFirstChar > 60000 || // see comment in QFontEngineWin -#endif - uc >= first && uc <= last) - glyphs->glyphs[glyph_pos] = uc; - else - glyphs->glyphs[glyph_pos] = 0; - } - } - } - glyphs->numGlyphs = glyph_pos; - return glyph_pos; -} - - -QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont, LOGFONT lf) -{ - //qDebug("regular windows font engine created: font='%s', size=%d", name, lf.lfHeight); - - _name = name; - - cmap = 0; - hfont = _hfont; - logfont = lf; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - this->stockFont = stockFont; - fontDef.pixelSize = -lf.lfHeight; - - lbearing = SHRT_MIN; - rbearing = SHRT_MIN; - synthesized_flags = -1; - lineWidth = -1; - x_height = -1; - - BOOL res = GetTextMetrics(hdc, &tm); - fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - if (!res) { - qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); - ZeroMemory(&tm, sizeof(TEXTMETRIC)); - } - - cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000; - getCMap(); - - widthCache = 0; - widthCacheSize = 0; - designAdvances = 0; - designAdvancesSize = 0; - -#ifndef Q_WS_WINCE - if (!resolvedGetCharWidthI) - resolveGetCharWidthI(); -#endif -} - -QFontEngineWin::~QFontEngineWin() -{ - if (designAdvances) - free(designAdvances); - - if (widthCache) - free(widthCache); - - // make sure we aren't by accident still selected - SelectObject(shared_dc(), (HFONT)GetStockObject(SYSTEM_FONT)); - - if (!stockFont) { - if (!DeleteObject(hfont)) - qErrnoWarning("QFontEngineWin: failed to delete non-stock font..."); - } -} - -HGDIOBJ QFontEngineWin::selectDesignFont() const -{ - LOGFONT f = logfont; - f.lfHeight = unitsPerEm; - HFONT designFont = CreateFontIndirect(&f); - return SelectObject(shared_dc(), designFont); -} - -bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - *nglyphs = getGlyphIndexes(str, len, glyphs, flags & QTextEngine::RightToLeft); - - if (flags & QTextEngine::GlyphIndicesOnly) - return true; - - recalcAdvances(glyphs, flags); - return true; -} - -inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width) -{ -#if defined(Q_WS_WINCE) - GetCharWidth32(hdc, glyph, glyph, &width); -#else - if (ptrGetCharWidthI) - ptrGetCharWidthI(hdc, glyph, 1, 0, &width); -#endif -} - -void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const -{ - HGDIOBJ oldFont = 0; - HDC hdc = shared_dc(); - if (ttf && (flags & QTextEngine::DesignMetrics)) { - for(int i = 0; i < glyphs->numGlyphs; i++) { - unsigned int glyph = glyphs->glyphs[i]; - if(int(glyph) >= designAdvancesSize) { - int newSize = (glyph + 256) >> 8 << 8; - designAdvances = q_check_ptr((QFixed *)realloc(designAdvances, - newSize*sizeof(QFixed))); - for(int i = designAdvancesSize; i < newSize; ++i) - designAdvances[i] = -1000000; - designAdvancesSize = newSize; - } - if (designAdvances[glyph] < -999999) { - if (!oldFont) - oldFont = selectDesignFont(); - - int width = 0; - calculateTTFGlyphWidth(hdc, glyph, width); - designAdvances[glyph] = QFixed(width) / designToDevice; - } - glyphs->advances_x[i] = designAdvances[glyph]; - glyphs->advances_y[i] = 0; - } - if(oldFont) - DeleteObject(SelectObject(hdc, oldFont)); - } else { - for(int i = 0; i < glyphs->numGlyphs; i++) { - unsigned int glyph = glyphs->glyphs[i]; - - glyphs->advances_y[i] = 0; - - if (glyph >= widthCacheSize) { - int newSize = (glyph + 256) >> 8 << 8; - widthCache = q_check_ptr((unsigned char *)realloc(widthCache, - newSize*sizeof(QFixed))); - memset(widthCache + widthCacheSize, 0, newSize - widthCacheSize); - widthCacheSize = newSize; - } - glyphs->advances_x[i] = widthCache[glyph]; - // font-width cache failed - if (glyphs->advances_x[i] == 0) { - int width = 0; - if (!oldFont) - oldFont = SelectObject(hdc, hfont); - - if (!ttf) { - QChar ch[2] = { ushort(glyph), 0 }; - int chrLen = 1; - if (glyph > 0xffff) { - ch[0] = QChar::highSurrogate(glyph); - ch[1] = QChar::lowSurrogate(glyph); - ++chrLen; - } - SIZE size = {0, 0}; - GetTextExtentPoint32(hdc, (wchar_t *)ch, chrLen, &size); - width = size.cx; - } else { - calculateTTFGlyphWidth(hdc, glyph, width); - } - glyphs->advances_x[i] = width; - // if glyph's within cache range, store it for later - if (width > 0 && width < 0x100) - widthCache[glyph] = width; - } - } - - if (oldFont) - SelectObject(hdc, oldFont); - } -} - -glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs) -{ - if (glyphs.numGlyphs == 0) - return glyph_metrics_t(); - - QFixed w = 0; - for (int i = 0; i < glyphs.numGlyphs; ++i) - w += glyphs.effectiveAdvance(i); - - return glyph_metrics_t(0, -tm.tmAscent, w - lastRightBearing(glyphs), tm.tmHeight, w, 0); -} - -#ifndef Q_WS_WINCE -bool QFontEngineWin::getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const -{ - Q_ASSERT(metrics != 0); - - HDC hdc = shared_dc(); - - GLYPHMETRICS gm; - DWORD res = 0; - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - - if (t.type() > QTransform::TxTranslate) { - // We need to set the transform using the HDC's world - // matrix rather than using the MAT2 above, because the - // results provided when transforming via MAT2 does not - // match the glyphs that are drawn using a WorldTransform - XFORM xform; - xform.eM11 = t.m11(); - xform.eM12 = t.m12(); - xform.eM21 = t.m21(); - xform.eM22 = t.m22(); - xform.eDx = 0; - xform.eDy = 0; - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - } - - uint format = GGO_METRICS; - if (ttf) - format |= GGO_GLYPH_INDEX; - res = GetGlyphOutline(hdc, glyph, format, &gm, 0, 0, &mat); - - if (t.type() > QTransform::TxTranslate) { - XFORM xform; - xform.eM11 = xform.eM22 = 1; - xform.eM12 = xform.eM21 = xform.eDx = xform.eDy = 0; - SetWorldTransform(hdc, &xform); - SetGraphicsMode(hdc, GM_COMPATIBLE); - } - - if (res != GDI_ERROR) { - *metrics = glyph_metrics_t(gm.gmptGlyphOrigin.x, -gm.gmptGlyphOrigin.y, - (int)gm.gmBlackBoxX, (int)gm.gmBlackBoxY, gm.gmCellIncX, gm.gmCellIncY); - return true; - } else { - return false; - } -} -#endif - -glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t) -{ -#ifndef Q_WS_WINCE - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - - glyph_metrics_t glyphMetrics; - bool success = getOutlineMetrics(glyph, t, &glyphMetrics); - - if (!ttf && !success) { - // Bitmap fonts - wchar_t ch = glyph; - ABCFLOAT abc; - GetCharABCWidthsFloat(hdc, ch, ch, &abc); - int width = qRound(abc.abcfB); - - return glyph_metrics_t(QFixed::fromReal(abc.abcfA), -tm.tmAscent, width, tm.tmHeight, width, 0).transformed(t); - } - - return glyphMetrics; -#else - HDC hdc = shared_dc(); - HGDIOBJ oldFont = SelectObject(hdc, hfont); - - ABC abc; - int width; - int advance; -#ifdef GWES_MGTT // true type fonts - if (GetCharABCWidths(hdc, glyph, glyph, &abc)) { - width = qAbs(abc.abcA) + abc.abcB + qAbs(abc.abcC); - advance = abc.abcA + abc.abcB + abc.abcC; - } - else -#endif -#if defined(GWES_MGRAST) || defined(GWES_MGRAST2) // raster fonts - if (GetCharWidth32(hdc, glyph, glyph, &width)) { - advance = width; - } - else -#endif - { // fallback - width = tm.tmMaxCharWidth; - advance = width; - } - - SelectObject(hdc, oldFont); - return glyph_metrics_t(0, -tm.tmAscent, width, tm.tmHeight, advance, 0).transformed(t); -#endif -} - -QFixed QFontEngineWin::ascent() const -{ - return tm.tmAscent; -} - -QFixed QFontEngineWin::descent() const -{ - // ### we substract 1 to even out the historical +1 in QFontMetrics's - // ### height=asc+desc+1 equation. Fix in Qt5. - return tm.tmDescent - 1; -} - -QFixed QFontEngineWin::leading() const -{ - return tm.tmExternalLeading; -} - - -QFixed QFontEngineWin::xHeight() const -{ - if(x_height >= 0) - return x_height; - return QFontEngine::xHeight(); -} - -QFixed QFontEngineWin::averageCharWidth() const -{ - return tm.tmAveCharWidth; -} - -qreal QFontEngineWin::maxCharWidth() const -{ - return tm.tmMaxCharWidth; -} - -enum { max_font_count = 256 }; -static const ushort char_table[] = { - 40, - 67, - 70, - 75, - 86, - 88, - 89, - 91, - 102, - 114, - 124, - 127, - 205, - 645, - 884, - 922, - 1070, - 12386, - 0 -}; - -static const int char_table_entries = sizeof(char_table)/sizeof(ushort); - -#ifndef Q_CC_MINGW -void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing) -{ - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - -#ifndef Q_WS_WINCE - if (ttf) -#endif - - { - ABC abcWidths; - GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths); - if (leftBearing) - *leftBearing = abcWidths.abcA; - if (rightBearing) - *rightBearing = abcWidths.abcC; - } - -#ifndef Q_WS_WINCE - else { - QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing); - } -#endif -} -#endif // Q_CC_MINGW - -qreal QFontEngineWin::minLeftBearing() const -{ - if (lbearing == SHRT_MIN) - minRightBearing(); // calculates both - - return lbearing; -} - -qreal QFontEngineWin::minRightBearing() const -{ -#ifdef Q_WS_WINCE - if (rbearing == SHRT_MIN) { - int ml = 0; - int mr = 0; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - if (ttf) { - ABC *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar; - if (n <= max_font_count) { - abc = new ABC[n+1]; - GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABC[char_table_entries+1]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidths(hdc, char_table[i], char_table[i], abc+i); - n = char_table_entries; - } - ml = abc[0].abcA; - mr = abc[0].abcC; - for (int i = 1; i < n; i++) { - if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) { - ml = qMin(ml,abc[i].abcA); - mr = qMin(mr,abc[i].abcC); - } - } - delete [] abc; - } - lbearing = ml; - rbearing = mr; - } - - return rbearing; -#else - if (rbearing == SHRT_MIN) { - int ml = 0; - int mr = 0; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - if (ttf) { - ABC *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar; - if (n <= max_font_count) { - abc = new ABC[n+1]; - GetCharABCWidths(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABC[char_table_entries+1]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidths(hdc, char_table[i], char_table[i], abc + i); - n = char_table_entries; - } - ml = abc[0].abcA; - mr = abc[0].abcC; - for (int i = 1; i < n; i++) { - if (abc[i].abcA + abc[i].abcB + abc[i].abcC != 0) { - ml = qMin(ml,abc[i].abcA); - mr = qMin(mr,abc[i].abcC); - } - } - delete [] abc; - } else { - ABCFLOAT *abc = 0; - int n = tm.tmLastChar - tm.tmFirstChar+1; - if (n <= max_font_count) { - abc = new ABCFLOAT[n]; - GetCharABCWidthsFloat(hdc, tm.tmFirstChar, tm.tmLastChar, abc); - } else { - abc = new ABCFLOAT[char_table_entries]; - for(int i = 0; i < char_table_entries; i++) - GetCharABCWidthsFloat(hdc, char_table[i], char_table[i], abc+i); - n = char_table_entries; - } - float fml = abc[0].abcfA; - float fmr = abc[0].abcfC; - for (int i=1; i<n; i++) { - if (abc[i].abcfA + abc[i].abcfB + abc[i].abcfC != 0) { - fml = qMin(fml,abc[i].abcfA); - fmr = qMin(fmr,abc[i].abcfC); - } - } - ml = int(fml - 0.9999); - mr = int(fmr - 0.9999); - delete [] abc; - } - lbearing = ml; - rbearing = mr; - } - - return rbearing; -#endif -} - - -const char *QFontEngineWin::name() const -{ - return 0; -} - -bool QFontEngineWin::canRender(const QChar *string, int len) -{ - if (symbol) { - for (int i = 0; i < len; ++i) { - unsigned int uc = getChar(string, i, len); - if (getTrueTypeGlyphIndex(cmap, uc) == 0) { - if (uc < 0x100) { - if (getTrueTypeGlyphIndex(cmap, uc + 0xf000) == 0) - return false; - } else { - return false; - } - } - } - } else if (ttf) { - for (int i = 0; i < len; ++i) { - unsigned int uc = getChar(string, i, len); - if (getTrueTypeGlyphIndex(cmap, uc) == 0) - return false; - } - } else { - while(len--) { - if (tm.tmFirstChar > string->unicode() || tm.tmLastChar < string->unicode()) - return false; - } - } - return true; -} - -QFontEngine::Type QFontEngineWin::type() const -{ - return QFontEngine::Win; -} - -static inline double qt_fixed_to_double(const FIXED &p) { - return ((p.value << 16) + p.fract) / 65536.0; -} - -static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) { - return QPointF(qt_fixed_to_double(pt.x) * scale, -qt_fixed_to_double(pt.y) * scale); -} - -#ifndef GGO_UNHINTED -#define GGO_UNHINTED 0x0100 -#endif - -static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc, - QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1) -{ -#if defined(Q_WS_WINCE) - Q_UNUSED(glyph); - Q_UNUSED(hdc); -#endif - MAT2 mat; - mat.eM11.value = mat.eM22.value = 1; - mat.eM11.fract = mat.eM22.fract = 0; - mat.eM21.value = mat.eM12.value = 0; - mat.eM21.fract = mat.eM12.fract = 0; - uint glyphFormat = GGO_NATIVE; - - if (ttf) - glyphFormat |= GGO_GLYPH_INDEX; - - GLYPHMETRICS gMetric; - memset(&gMetric, 0, sizeof(GLYPHMETRICS)); - int bufferSize = GDI_ERROR; -#if !defined(Q_WS_WINCE) - bufferSize = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat); -#endif - if ((DWORD)bufferSize == GDI_ERROR) { - return false; - } - - void *dataBuffer = new char[bufferSize]; - DWORD ret = GDI_ERROR; -#if !defined(Q_WS_WINCE) - ret = GetGlyphOutline(hdc, glyph, glyphFormat, &gMetric, bufferSize, dataBuffer, &mat); -#endif - if (ret == GDI_ERROR) { - delete [](char *)dataBuffer; - return false; - } - - if(metric) { - // #### obey scale - *metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y, - (int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY, - gMetric.gmCellIncX, gMetric.gmCellIncY); - } - - int offset = 0; - int headerOffset = 0; - TTPOLYGONHEADER *ttph = 0; - - QPointF oset = position.toPointF(); - while (headerOffset < bufferSize) { - ttph = (TTPOLYGONHEADER*)((char *)dataBuffer + headerOffset); - - QPointF lastPoint(qt_to_qpointf(ttph->pfxStart, scale)); - path->moveTo(lastPoint + oset); - offset += sizeof(TTPOLYGONHEADER); - TTPOLYCURVE *curve; - while (offset<int(headerOffset + ttph->cb)) { - curve = (TTPOLYCURVE*)((char*)(dataBuffer) + offset); - switch (curve->wType) { - case TT_PRIM_LINE: { - for (int i=0; i<curve->cpfx; ++i) { - QPointF p = qt_to_qpointf(curve->apfx[i], scale) + oset; - path->lineTo(p); - } - break; - } - case TT_PRIM_QSPLINE: { - const QPainterPath::Element &elm = path->elementAt(path->elementCount()-1); - QPointF prev(elm.x, elm.y); - QPointF endPoint; - for (int i=0; i<curve->cpfx - 1; ++i) { - QPointF p1 = qt_to_qpointf(curve->apfx[i], scale) + oset; - QPointF p2 = qt_to_qpointf(curve->apfx[i+1], scale) + oset; - if (i < curve->cpfx - 2) { - endPoint = QPointF((p1.x() + p2.x()) / 2, (p1.y() + p2.y()) / 2); - } else { - endPoint = p2; - } - - path->quadTo(p1, endPoint); - prev = endPoint; - } - - break; - } - case TT_PRIM_CSPLINE: { - for (int i=0; i<curve->cpfx; ) { - QPointF p2 = qt_to_qpointf(curve->apfx[i++], scale) + oset; - QPointF p3 = qt_to_qpointf(curve->apfx[i++], scale) + oset; - QPointF p4 = qt_to_qpointf(curve->apfx[i++], scale) + oset; - path->cubicTo(p2, p3, p4); - } - break; - } - default: - qWarning("QFontEngineWin::addOutlineToPath, unhandled switch case"); - } - offset += sizeof(TTPOLYCURVE) + (curve->cpfx-1) * sizeof(POINTFX); - } - path->closeSubpath(); - headerOffset += ttph->cb; - } - delete [] (char*)dataBuffer; - - return true; -} - -void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags) -{ - LOGFONT lf = logfont; - // The sign must be negative here to make sure we match against character height instead of - // hinted cell height. This ensures that we get linear matching, and we need this for - // paths since we later on apply a scaling transform to the glyph outline to get the - // font at the correct pixel size. - lf.lfHeight = -unitsPerEm; - lf.lfWidth = 0; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = shared_dc(); - HGDIOBJ oldfont = SelectObject(hdc, hf); - - for(int i = 0; i < nglyphs; ++i) { - if (!addGlyphToPath(glyphs[i], positions[i], hdc, path, ttf, /*metric*/0, - qreal(fontDef.pixelSize) / unitsPerEm)) { - // Some windows fonts, like "Modern", are vector stroke - // fonts, which are reported as TMPF_VECTOR but do not - // support GetGlyphOutline, and thus we set this bit so - // that addOutLineToPath can check it and return safely... - hasOutline = false; - break; - } - } - DeleteObject(SelectObject(hdc, oldfont)); -} - -void QFontEngineWin::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, - QPainterPath *path, QTextItem::RenderFlags flags) -{ -#if !defined(Q_WS_WINCE) - if(tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) { - hasOutline = true; - QFontEngine::addOutlineToPath(x, y, glyphs, path, flags); - if (hasOutline) { - // has_outline is set to false if addGlyphToPath gets - // false from GetGlyphOutline, meaning its not an outline - // font. - return; - } - } -#endif - QFontEngine::addBitmapFontToPath(x, y, glyphs, path, flags); -} - -QFontEngine::FaceId QFontEngineWin::faceId() const -{ - return _faceId; -} - -QT_BEGIN_INCLUDE_NAMESPACE -#include <qdebug.h> -QT_END_INCLUDE_NAMESPACE - -int QFontEngineWin::synthesized() const -{ - if(synthesized_flags == -1) { - synthesized_flags = 0; - if(ttf) { - const DWORD HEAD = MAKE_TAG('h', 'e', 'a', 'd'); - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - uchar data[4]; - GetFontData(hdc, HEAD, 44, &data, 4); - USHORT macStyle = getUShort(data); - if (tm.tmItalic && !(macStyle & 2)) - synthesized_flags = SynthesizedItalic; - if (fontDef.stretch != 100 && ttf) - synthesized_flags |= SynthesizedStretch; - if (tm.tmWeight >= 500 && !(macStyle & 1)) - synthesized_flags |= SynthesizedBold; - //qDebug() << "font is" << _name << - // "it=" << (macStyle & 2) << fontDef.style << "flags=" << synthesized_flags; - } - } - return synthesized_flags; -} - -QFixed QFontEngineWin::emSquareSize() const -{ - return unitsPerEm; -} - -QFontEngine::Properties QFontEngineWin::properties() const -{ - LOGFONT lf = logfont; - lf.lfHeight = unitsPerEm; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = shared_dc(); - HGDIOBJ oldfont = SelectObject(hdc, hf); - OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - Properties p; - p.emSquare = unitsPerEm; - p.italicAngle = otm->otmItalicAngle; - p.postscriptName = QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFamilyName)).toLatin1(); - p.postscriptName += QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpStyleName)).toLatin1(); - p.postscriptName = QFontEngine::convertToPostscriptFontFamilyName(p.postscriptName); - p.boundingBox = QRectF(otm->otmrcFontBox.left, -otm->otmrcFontBox.top, - otm->otmrcFontBox.right - otm->otmrcFontBox.left, - otm->otmrcFontBox.top - otm->otmrcFontBox.bottom); - p.ascent = otm->otmAscent; - p.descent = -otm->otmDescent; - p.leading = (int)otm->otmLineGap; - p.capHeight = 0; - p.lineWidth = otm->otmsUnderscoreSize; - free(otm); - DeleteObject(SelectObject(hdc, oldfont)); - return p; -} - -void QFontEngineWin::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - LOGFONT lf = logfont; - lf.lfHeight = unitsPerEm; - int flags = synthesized(); - if(flags & SynthesizedItalic) - lf.lfItalic = false; - lf.lfWidth = 0; - HFONT hf = CreateFontIndirect(&lf); - HDC hdc = shared_dc(); - HGDIOBJ oldfont = SelectObject(hdc, hf); - QFixedPoint p; - p.x = 0; - p.y = 0; - addGlyphToPath(glyph, p, hdc, path, ttf, metrics); - DeleteObject(SelectObject(hdc, oldfont)); -} - -bool QFontEngineWin::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ - if (!ttf) - return false; - HDC hdc = shared_dc(); - SelectObject(hdc, hfont); - DWORD t = qbswap<quint32>(tag); - *length = GetFontData(hdc, t, 0, buffer, *length); - return *length != GDI_ERROR; -} - -#if !defined(CLEARTYPE_QUALITY) -# define CLEARTYPE_QUALITY 5 -#endif - -extern bool qt_cleartype_enabled; - -QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin, - const QTransform &t, QImage::Format mask_format) -{ - Q_UNUSED(mask_format) - glyph_metrics_t gm = boundingBox(glyph); - -// printf(" -> for glyph %4x\n", glyph); - - int gx = gm.x.toInt(); - int gy = gm.y.toInt(); - int iw = gm.width.toInt(); - int ih = gm.height.toInt(); - - if (iw <= 0 || iw <= 0) - return 0; - - bool has_transformation = t.type() > QTransform::TxTranslate; - -#ifndef Q_WS_WINCE - unsigned int options = ttf ? ETO_GLYPH_INDEX : 0; - XFORM xform; - - if (has_transformation) { - xform.eM11 = t.m11(); - xform.eM12 = t.m12(); - xform.eM21 = t.m21(); - xform.eM22 = t.m22(); - xform.eDx = margin; - xform.eDy = margin; - - QtHDC qthdc; - HDC hdc = qthdc.hdc(); - - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - HGDIOBJ old_font = SelectObject(hdc, font); - - int ggo_options = GGO_METRICS | (ttf ? GGO_GLYPH_INDEX : 0); - GLYPHMETRICS tgm; - MAT2 mat; - memset(&mat, 0, sizeof(mat)); - mat.eM11.value = mat.eM22.value = 1; - - if (GetGlyphOutline(hdc, glyph, ggo_options, &tgm, 0, 0, &mat) == GDI_ERROR) { - qWarning("QWinFontEngine: unable to query transformed glyph metrics..."); - return 0; - } - - iw = tgm.gmBlackBoxX; - ih = tgm.gmBlackBoxY; - - xform.eDx -= tgm.gmptGlyphOrigin.x; - xform.eDy += tgm.gmptGlyphOrigin.y; - - SetGraphicsMode(hdc, GM_COMPATIBLE); - SelectObject(hdc, old_font); - } -#else // else winc - unsigned int options = 0; -#ifdef DEBUG - Q_ASSERT(!has_transformation); -#else - Q_UNUSED(has_transformation); -#endif -#endif - - QNativeImage *ni = new QNativeImage(iw + 2 * margin + 4, - ih + 2 * margin + 4, - QNativeImage::systemFormat(), !qt_cleartype_enabled); - - /*If cleartype is enabled we use the standard system format even on Windows CE - and not the special textbuffer format we have to use if cleartype is disabled*/ - - ni->image.fill(0xffffffff); - - HDC hdc = ni->hdc; - - SelectObject(hdc, GetStockObject(NULL_BRUSH)); - SelectObject(hdc, GetStockObject(BLACK_PEN)); - SetTextColor(hdc, RGB(0,0,0)); - SetBkMode(hdc, TRANSPARENT); - SetTextAlign(hdc, TA_BASELINE); - - HGDIOBJ old_font = SelectObject(hdc, font); - -#ifndef Q_OS_WINCE - if (has_transformation) { - SetGraphicsMode(hdc, GM_ADVANCED); - SetWorldTransform(hdc, &xform); - ExtTextOut(hdc, 0, 0, options, 0, (LPCWSTR) &glyph, 1, 0); - } else -#endif - { - ExtTextOut(hdc, -gx + margin, -gy + margin, options, 0, (LPCWSTR) &glyph, 1, 0); - } - - SelectObject(hdc, old_font); - return ni; -} - - -extern uint qt_pow_gamma[256]; - -QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform) -{ - HFONT font = hfont; - if (qt_cleartype_enabled) { - LOGFONT lf = logfont; - lf.lfQuality = ANTIALIASED_QUALITY; - font = CreateFontIndirect(&lf); - } - QImage::Format mask_format = QNativeImage::systemFormat(); -#ifndef Q_OS_WINCE - mask_format = QImage::Format_RGB32; -#endif - - QNativeImage *mask = drawGDIGlyph(font, glyph, 0, xform, mask_format); - if (mask == 0) - return QImage(); - - QImage indexed(mask->width(), mask->height(), QImage::Format_Indexed8); - - // ### This part is kinda pointless, but we'll crash later if we don't because some - // code paths expects there to be colortables for index8-bit... - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); - - // Copy data... Cannot use QPainter here as GDI has messed up the - // Alpha channel of the ni.image pixels... - for (int y=0; y<mask->height(); ++y) { - uchar *dest = indexed.scanLine(y); - if (mask->image.format() == QImage::Format_RGB16) { - const qint16 *src = (qint16 *) ((const QImage &) mask->image).scanLine(y); - for (int x=0; x<mask->width(); ++x) - dest[x] = 255 - qGray(src[x]); - } else { - const uint *src = (uint *) ((const QImage &) mask->image).scanLine(y); - for (int x=0; x<mask->width(); ++x) { -#ifdef Q_OS_WINCE - dest[x] = 255 - qGray(src[x]); -#else - if (QNativeImage::systemFormat() == QImage::Format_RGB16) - dest[x] = 255 - qGray(src[x]); - else - dest[x] = 255 - (qt_pow_gamma[qGray(src[x])] * 255. / 2047.); -#endif - } - } - } - - // Cleanup... - delete mask; - if (qt_cleartype_enabled) { - DeleteObject(font); - } - - return indexed; -} - -#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C -#define SPI_SETFONTSMOOTHINGCONTRAST 0x200D - -QImage QFontEngineWin::alphaRGBMapForGlyph(glyph_t glyph, QFixed, int margin, const QTransform &t) -{ - HFONT font = hfont; - - int contrast; - SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &contrast, 0); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) 1000, 0); - - QNativeImage *mask = drawGDIGlyph(font, glyph, margin, t, QImage::Format_RGB32); - SystemParametersInfo(SPI_SETFONTSMOOTHINGCONTRAST, 0, (void *) contrast, 0); - - if (mask == 0) - return QImage(); - - // Gracefully handle the odd case when the display is 16-bit - const QImage source = mask->image.depth() == 32 - ? mask->image - : mask->image.convertToFormat(QImage::Format_RGB32); - - QImage rgbMask(mask->width(), mask->height(), QImage::Format_RGB32); - for (int y=0; y<mask->height(); ++y) { - uint *dest = (uint *) rgbMask.scanLine(y); - const uint *src = (uint *) source.scanLine(y); - for (int x=0; x<mask->width(); ++x) { - dest[x] = 0xffffffff - (0x00ffffff & src[x]); - } - } - - delete mask; - - return rgbMask; -} - -// From qfontdatabase_win.cpp -extern QFontEngine *qt_load_font_engine_win(const QFontDef &request); -QFontEngine *QFontEngineWin::cloneWithSize(qreal pixelSize) const -{ - QFontDef request = fontDef; - QString actualFontName = request.family; - if (!uniqueFamilyName.isEmpty()) - request.family = uniqueFamilyName; - request.pixelSize = pixelSize; - - QFontEngine *fontEngine = qt_load_font_engine_win(request); - if (fontEngine != NULL) - fontEngine->fontDef.family = actualFontName; - - return fontEngine; -} - -// -------------------------------------- Multi font engine - -QFontEngineMultiWin::QFontEngineMultiWin(QFontEngine *first, const QStringList &fallbacks) - : QFontEngineMulti(fallbacks.size()+1), - fallbacks(fallbacks) -{ - engines[0] = first; - first->ref.ref(); - fontDef = engines[0]->fontDef; - cache_cost = first->cache_cost; -} - -void QFontEngineMultiWin::loadEngine(int at) -{ - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - QString fam = fallbacks.at(at-1); - - LOGFONT lf = static_cast<QFontEngineWin *>(engines.at(0))->logfont; - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded - HFONT hfont = CreateFontIndirect(&lf); - - bool stockFont = false; - if (hfont == 0) { - hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); - stockFont = true; - } - engines[at] = new QFontEngineWin(fam, hfont, stockFont, lf); - engines[at]->ref.ref(); - engines[at]->fontDef = fontDef; - - // TODO: increase cost in QFontCache for the font engine loaded here -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h deleted file mode 100644 index 114149d61f..0000000000 --- a/src/gui/text/qfontengine_win_p.h +++ /dev/null @@ -1,164 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_WIN_P_H -#define QFONTENGINE_WIN_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qconfig.h> - -QT_BEGIN_NAMESPACE - -class QNativeImage; - -class QFontEngineWin : public QFontEngine -{ -public: - QFontEngineWin(const QString &name, HFONT, bool, LOGFONT); - ~QFontEngineWin(); - - virtual QFixed lineThickness() const; - virtual Properties properties() const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual FaceId faceId() const; - virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - virtual int synthesized() const; - virtual QFixed emSquareSize() const; - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const; - - virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); - virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); - - HGDIOBJ selectDesignFont() const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t g) { return boundingBox(g, QTransform()); } - virtual glyph_metrics_t boundingBox(glyph_t g, const QTransform &t); - - - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual QFixed xHeight() const; - virtual QFixed averageCharWidth() const; - virtual qreal maxCharWidth() const; - virtual qreal minLeftBearing() const; - virtual qreal minRightBearing() const; - - virtual const char *name() const; - - bool canRender(const QChar *string, int len); - - Type type() const; - - virtual QImage alphaMapForGlyph(glyph_t t) { return alphaMapForGlyph(t, QTransform()); } - virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform); - virtual QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, int margin, const QTransform &xform); - - virtual QFontEngine *cloneWithSize(qreal pixelSize) const; - -#ifndef Q_CC_MINGW - virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0); -#endif - - int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const; - void getCMap(); - -#ifndef Q_WS_WINCE - bool getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const; -#endif - - QString _name; - QString uniqueFamilyName; - HFONT hfont; - LOGFONT logfont; - uint stockFont : 1; - uint ttf : 1; - uint hasOutline : 1; - TEXTMETRIC tm; - int lw; - const unsigned char *cmap; - QByteArray cmapTable; - mutable qreal lbearing; - mutable qreal rbearing; - QFixed designToDevice; - int unitsPerEm; - QFixed x_height; - FaceId _faceId; - - mutable int synthesized_flags; - mutable QFixed lineWidth; - mutable unsigned char *widthCache; - mutable uint widthCacheSize; - mutable QFixed *designAdvances; - mutable int designAdvancesSize; - -private: - QNativeImage *drawGDIGlyph(HFONT font, glyph_t, int margin, const QTransform &xform, - QImage::Format mask_format); - -}; - -class QFontEngineMultiWin : public QFontEngineMulti -{ -public: - QFontEngineMultiWin(QFontEngine *first, const QStringList &fallbacks); - void loadEngine(int at); - - QStringList fallbacks; -}; - -QT_END_NAMESPACE - -#endif // QFONTENGINE_WIN_P_H diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp deleted file mode 100644 index 4260b85b11..0000000000 --- a/src/gui/text/qfontengine_x11.cpp +++ /dev/null @@ -1,1215 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qbitmap.h" - -// #define FONTENGINE_DEBUG - -#include <qapplication.h> -#include <qbytearray.h> -#include <qdebug.h> -#include <qtextcodec.h> -#include <qthread.h> - -#include "qfontdatabase.h" -#include "qpaintdevice.h" -#include "qpainter.h" -#include "qvarlengtharray.h" -#include "qwidget.h" -#include "qsettings.h" -#include "qfile.h" - -#include <private/qpaintengine_x11_p.h> -#include "qfont.h" -#include "qfont_p.h" -#include "qfontengine_p.h" -#include <qhash.h> - -#include <private/qpainter_p.h> -#include <private/qunicodetables_p.h> - -#include <private/qt_x11_p.h> -#include <private/qpixmap_x11_p.h> -#include "qx11info_x11.h" -#include "qfontengine_x11_p.h" - -#include <limits.h> - -#include <ft2build.h> -#if defined(FT_LCD_FILTER_H) -#include FT_LCD_FILTER_H -#endif - -#if defined(FC_LCD_FILTER) - -#ifndef FC_LCD_FILTER_NONE -#define FC_LCD_FILTER_NONE FC_LCD_NONE -#endif - -#ifndef FC_LCD_FILTER_DEFAULT -#define FC_LCD_FILTER_DEFAULT FC_LCD_DEFAULT -#endif - -#ifndef FC_LCD_FILTER_LIGHT -#define FC_LCD_FILTER_LIGHT FC_LCD_LIGHT -#endif - -#ifndef FC_LCD_FILTER_LEGACY -#define FC_LCD_FILTER_LEGACY FC_LCD_LEGACY -#endif - -#endif - -QT_BEGIN_NAMESPACE - - -// ------------------------------------------------------------------ -// Multi XLFD engine -// ------------------------------------------------------------------ - -QFontEngineMultiXLFD::QFontEngineMultiXLFD(const QFontDef &r, const QList<int> &l, int s) - : QFontEngineMulti(l.size()), encodings(l), screen(s), request(r) -{ - loadEngine(0); - fontDef = engines[0]->fontDef; -} - -QFontEngineMultiXLFD::~QFontEngineMultiXLFD() -{ } - -void QFontEngineMultiXLFD::loadEngine(int at) -{ - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - const int encoding = encodings.at(at); - QFontEngine *fontEngine = QFontDatabase::loadXlfd(0, QUnicodeTables::Common, request, encoding); - Q_ASSERT(fontEngine != 0); - fontEngine->ref.ref(); - engines[at] = fontEngine; -} - -// ------------------------------------------------------------------ -// Xlfd font engine -// ------------------------------------------------------------------ - -#ifndef QT_NO_FREETYPE - -static QStringList *qt_fontpath = 0; - -static QStringList fontPath() -{ - if (qt_fontpath) - return *qt_fontpath; - - // append qsettings fontpath - QSettings settings(QSettings::UserScope, QLatin1String("Trolltech")); - settings.beginGroup(QLatin1String("Qt")); - - QStringList fontpath; - - int npaths; - char** font_path; - font_path = XGetFontPath(X11->display, &npaths); - bool xfsconfig_read = false; - for (int i=0; i<npaths; i++) { - // If we're using xfs, append font paths from /etc/X11/fs/config - // can't hurt, and chances are we'll get all fonts that way. - if (((font_path[i])[0] != '/') && !xfsconfig_read) { - // We're using xfs -> read its config - bool finished = false; - QFile f(QLatin1String("/etc/X11/fs/config")); - if (!f.exists()) - f.setFileName(QLatin1String("/usr/X11R6/lib/X11/fs/config")); - if (!f.exists()) - f.setFileName(QLatin1String("/usr/X11/lib/X11/fs/config")); - if (f.exists()) { - f.open(QIODevice::ReadOnly); - while (f.error()==QFile::NoError && !finished) { - QString fs = QString::fromLocal8Bit(f.readLine(1024)); - fs=fs.trimmed(); - if (fs.left(9)==QLatin1String("catalogue") && fs.contains(QLatin1Char('='))) { - fs = fs.mid(fs.indexOf(QLatin1Char('=')) + 1).trimmed(); - bool end = false; - while (f.error()==QFile::NoError && !end) { - if (fs[int(fs.length())-1] == QLatin1Char(',')) - fs = fs.left(fs.length()-1); - else - end = true; - - fs = fs.left(fs.indexOf(QLatin1String(":unscaled"))); - if (fs[0] != QLatin1Char('#')) - fontpath += fs; - fs = QLatin1String(f.readLine(1024)); - fs = fs.trimmed(); - if (fs.isEmpty()) - end = true; - } - finished = true; - } - } - f.close(); - } - xfsconfig_read = true; - } else { - QString fs = QString::fromLocal8Bit(font_path[i]); - fontpath += fs.left(fs.indexOf(QLatin1String(":unscaled"))); - } - } - XFreeFontPath(font_path); - - // append qsettings fontpath - QStringList fp = settings.value(QLatin1String("fontPath")).toStringList(); - if (!fp.isEmpty()) - fontpath += fp; - - qt_fontpath = new QStringList(fontpath); - return fontpath; -} - -static QFontEngine::FaceId fontFile(const QByteArray &_xname, QFreetypeFace **freetype, int *synth) -{ - *freetype = 0; - *synth = 0; - - QByteArray xname = _xname.toLower(); - - int pos = 0; - int minus = 0; - while (minus < 5 && (pos = xname.indexOf('-', pos + 1))) - ++minus; - QByteArray searchname = xname.left(pos); - while (minus < 12 && (pos = xname.indexOf('-', pos + 1))) - ++minus; - QByteArray encoding = xname.mid(pos + 1); - //qDebug("xname='%s', searchname='%s', encoding='%s'", xname.data(), searchname.data(), encoding.data()); - QStringList fontpath = fontPath(); - QFontEngine::FaceId face_id; - face_id.index = 0; - - QByteArray best_mapping; - - for (QStringList::ConstIterator it = fontpath.constBegin(); it != fontpath.constEnd(); ++it) { - if (!(*it).startsWith(QLatin1Char('/'))) - continue; // not a path name, a font server - QString fontmapname; - int num = 0; - // search font.dir and font.scale for the right file - while (num < 2) { - if (num == 0) - fontmapname = (*it) + QLatin1String("/fonts.scale"); - else - fontmapname = (*it) + QLatin1String("/fonts.dir"); - ++num; - //qWarning(fontmapname); - QFile fontmap(fontmapname); - if (!fontmap.open(QIODevice::ReadOnly)) - continue; - while (!fontmap.atEnd()) { - QByteArray mapping = fontmap.readLine(); - QByteArray lmapping = mapping.toLower(); - - //qWarning(xfontname); - //qWarning(mapping); - if (!lmapping.contains(searchname)) - continue; - int index = mapping.indexOf(' '); - QByteArray ffn = mapping.mid(0,index); - // remove bitmap formats freetype can't handle - if (ffn.contains(".spd") || ffn.contains(".phont")) - continue; - bool best_match = false; - if (!best_mapping.isEmpty()) { - if (lmapping.contains("-0-0-0-0-")) { // scalable font - best_match = true; - goto found; - } - if (lmapping.contains(encoding) && !best_mapping.toLower().contains(encoding)) - goto found; - continue; - } - - found: - int colon = ffn.lastIndexOf(':'); - if (colon != -1) { - QByteArray s = ffn.left(colon); - ffn = ffn.mid(colon + 1); - if (s.contains("ds=")) - *synth |= QFontEngine::SynthesizedBold; - if (s.contains("ai=")) - *synth |= QFontEngine::SynthesizedItalic; - } - face_id.filename = (*it).toLocal8Bit() + '/' + ffn; - best_mapping = mapping; - if (best_match) - goto end; - } - } - } -end: -// qDebug("fontfile for %s is from '%s'\n got %s synth=%d", xname.data(), -// best_mapping.data(), face_id.filename.data(), *synth); - *freetype = QFreetypeFace::getFace(face_id); - if (!*freetype) { - face_id.index = 0; - face_id.filename = QByteArray(); - } - return face_id; -} - -#endif // QT_NO_FREETYPE - -// defined in qfontdatabase_x11.cpp -extern int qt_mib_for_xlfd_encoding(const char *encoding); -extern int qt_xlfd_encoding_id(const char *encoding); - -static inline XCharStruct *charStruct(XFontStruct *xfs, uint ch) -{ - XCharStruct *xcs = 0; - unsigned char r = ch>>8; - unsigned char c = ch&0xff; - if (xfs->per_char && - r >= xfs->min_byte1 && - r <= xfs->max_byte1 && - c >= xfs->min_char_or_byte2 && - c <= xfs->max_char_or_byte2) { - xcs = xfs->per_char + ((r - xfs->min_byte1) * - (xfs->max_char_or_byte2 - - xfs->min_char_or_byte2 + 1)) + - (c - xfs->min_char_or_byte2); - if (xcs->width == 0 && xcs->ascent == 0 && xcs->descent == 0) - xcs = 0; - } - return xcs; -} - -QFontEngineXLFD::QFontEngineXLFD(XFontStruct *fs, const QByteArray &name, int mib) - : _fs(fs), _name(name), _codec(0), _cmap(mib) -{ - if (_cmap) _codec = QTextCodec::codecForMib(_cmap); - - cache_cost = (((fs->max_byte1 - fs->min_byte1) * - (fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1)) + - fs->max_char_or_byte2 - fs->min_char_or_byte2); - cache_cost = ((fs->max_bounds.ascent + fs->max_bounds.descent) * - (fs->max_bounds.width * cache_cost / 8)); - lbearing = SHRT_MIN; - rbearing = SHRT_MIN; - face_id.index = -1; - freetype = 0; - synth = 0; -} - -QFontEngineXLFD::~QFontEngineXLFD() -{ - XFreeFont(QX11Info::display(), _fs); - _fs = 0; -#ifndef QT_NO_FREETYPE - if (freetype) - freetype->release(face_id); -#endif -} - -bool QFontEngineXLFD::stringToCMap(const QChar *s, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const -{ - if (*nglyphs < len) { - *nglyphs = len; - return false; - } - - // filter out surrogates, we can't handle them anyway with XLFD fonts - QVarLengthArray<ushort> _s(len); - QChar *str = (QChar *)_s.data(); - for (int i = 0; i < len; ++i) { - if (i < len - 1 - && s[i].unicode() >= 0xd800 && s[i].unicode() < 0xdc00 - && s[i+1].unicode() >= 0xdc00 && s[i].unicode() < 0xe000) { - *str = QChar(); - ++i; - } else { - *str = s[i]; - } - ++str; - } - - len = str - (QChar *)_s.data(); - str = (QChar *)_s.data(); - - bool mirrored = flags & QTextEngine::RightToLeft; - if (_codec) { - bool haveNbsp = false; - for (int i = 0; i < len; i++) - if (str[i].unicode() == 0xa0) { - haveNbsp = true; - break; - } - - QVarLengthArray<unsigned short> ch(len); - QChar *chars = (QChar *)ch.data(); - if (haveNbsp || mirrored) { - for (int i = 0; i < len; i++) - chars[i] = (str[i].unicode() == 0xa0 ? 0x20 : - (mirrored ? QChar::mirroredChar(str[i].unicode()) : str[i].unicode())); - } else { - for (int i = 0; i < len; i++) - chars[i] = str[i].unicode(); - } - QTextCodec::ConverterState state; - state.flags = QTextCodec::ConvertInvalidToNull; - QByteArray ba = _codec->fromUnicode(chars, len, &state); - if (ba.length() == 2*len) { - // double byte encoding - const uchar *data = (const uchar *)ba.constData(); - for (int i = 0; i < len; i++) { - glyphs->glyphs[i] = ((ushort)data[0] << 8) + data[1]; - data += 2; - } - } else { - const uchar *data = (const uchar *)ba.constData(); - for (int i = 0; i < len; i++) - glyphs->glyphs[i] = (ushort)data[i]; - } - } else { - int i = len; - const QChar *c = str + len; - if (mirrored) { - while (c != str) - glyphs->glyphs[--i] = (--c)->unicode() == 0xa0 ? 0x20 : QChar::mirroredChar(c->unicode()); - } else { - while (c != str) - glyphs->glyphs[--i] = (--c)->unicode() == 0xa0 ? 0x20 : c->unicode(); - } - } - *nglyphs = len; - glyphs->numGlyphs = len; - - if (!(flags & QTextEngine::GlyphIndicesOnly)) - recalcAdvances(glyphs, flags); - return true; -} - -void QFontEngineXLFD::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags /*flags*/) const -{ - int i = glyphs->numGlyphs; - XCharStruct *xcs; - // inlined for better performance - if (!_fs->per_char) { - xcs = &_fs->min_bounds; - while (i != 0) { - --i; - const unsigned char r = glyphs->glyphs[i] >> 8; - const unsigned char c = glyphs->glyphs[i] & 0xff; - if (r >= _fs->min_byte1 && - r <= _fs->max_byte1 && - c >= _fs->min_char_or_byte2 && - c <= _fs->max_char_or_byte2) { - glyphs->advances_x[i] = xcs->width; - } else { - glyphs->glyphs[i] = 0; - } - } - } - else if (!_fs->max_byte1) { - XCharStruct *base = _fs->per_char - _fs->min_char_or_byte2; - while (i != 0) { - unsigned int gl = glyphs->glyphs[--i]; - xcs = (gl >= _fs->min_char_or_byte2 && gl <= _fs->max_char_or_byte2) ? - base + gl : 0; - if (!xcs || (!xcs->width && !xcs->ascent && !xcs->descent)) { - glyphs->glyphs[i] = 0; - } else { - glyphs->advances_x[i] = xcs->width; - } - } - } - else { - while (i != 0) { - xcs = charStruct(_fs, glyphs->glyphs[--i]); - if (!xcs) { - glyphs->glyphs[i] = 0; - } else { - glyphs->advances_x[i] = xcs->width; - } - } - } -} - -glyph_metrics_t QFontEngineXLFD::boundingBox(const QGlyphLayout &glyphs) -{ - int i; - - glyph_metrics_t overall; - // initialize with line height, we get the same behaviour on all platforms - overall.y = -ascent(); - overall.height = ascent() + descent() + 1; - QFixed ymax; - QFixed xmax; - for (i = 0; i < glyphs.numGlyphs; i++) { - XCharStruct *xcs = charStruct(_fs, glyphs.glyphs[i]); - if (xcs) { - QFixed x = overall.xoff + glyphs.offsets[i].x + xcs->lbearing; - QFixed y = overall.yoff + glyphs.offsets[i].y - xcs->ascent; - overall.x = qMin(overall.x, x); - overall.y = qMin(overall.y, y); - // XCharStruct::rbearing is defined as distance from left edge to rightmost pixel - xmax = qMax(xmax, overall.xoff + glyphs.offsets[i].x + xcs->rbearing); - ymax = qMax(ymax, y + xcs->ascent + xcs->descent); - overall.xoff += glyphs.advances_x[i] + QFixed::fromFixed(glyphs.justifications[i].space_18d6); - } else { - QFixed size = _fs->ascent; - overall.x = qMin(overall.x, overall.xoff); - overall.y = qMin(overall.y, overall.yoff - size); - ymax = qMax(ymax, overall.yoff); - overall.xoff += size; - xmax = qMax(xmax, overall.xoff); - } - } - overall.height = qMax(overall.height, ymax - overall.y); - overall.width = xmax - overall.x; - - return overall; -} - -glyph_metrics_t QFontEngineXLFD::boundingBox(glyph_t glyph) -{ - glyph_metrics_t gm; - XCharStruct *xcs = charStruct(_fs, glyph); - if (xcs) { - // XCharStruct::rbearing is defined as distance from left edge to rightmost pixel - // XCharStruct::width is defined as the advance - gm = glyph_metrics_t(xcs->lbearing, -xcs->ascent, xcs->rbearing- xcs->lbearing, xcs->ascent + xcs->descent, - xcs->width, 0); - } else { - QFixed size = ascent(); - gm = glyph_metrics_t(0, size, size, size, size, 0); - } - return gm; -} - -QFixed QFontEngineXLFD::ascent() const -{ - return _fs->ascent; -} - -QFixed QFontEngineXLFD::descent() const -{ - return (_fs->descent-1); -} - -QFixed QFontEngineXLFD::leading() const -{ - QFixed l = QFixed(qMin<int>(_fs->ascent, _fs->max_bounds.ascent) - + qMin<int>(_fs->descent, _fs->max_bounds.descent)) * QFixed::fromReal(0.15); - return l.ceil(); -} - -qreal QFontEngineXLFD::maxCharWidth() const -{ - return _fs->max_bounds.width; -} - - -// Loads the font for the specified script -static inline int maxIndex(XFontStruct *f) { - return (((f->max_byte1 - f->min_byte1) * - (f->max_char_or_byte2 - f->min_char_or_byte2 + 1)) + - f->max_char_or_byte2 - f->min_char_or_byte2); -} - -qreal QFontEngineXLFD::minLeftBearing() const -{ - if (lbearing == SHRT_MIN) { - if (_fs->per_char) { - XCharStruct *cs = _fs->per_char; - int nc = maxIndex(_fs) + 1; - int mx = cs->lbearing; - - for (int c = 1; c < nc; c++) { - // ignore the bearings for characters whose ink is - // completely outside the normal bounding box - if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) || - (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width)) - continue; - - int nmx = cs[c].lbearing; - - if (nmx < mx) - mx = nmx; - } - - ((QFontEngineXLFD *)this)->lbearing = mx; - } else - ((QFontEngineXLFD *)this)->lbearing = _fs->min_bounds.lbearing; - } - return lbearing; -} - -qreal QFontEngineXLFD::minRightBearing() const -{ - if (rbearing == SHRT_MIN) { - if (_fs->per_char) { - XCharStruct *cs = _fs->per_char; - int nc = maxIndex(_fs) + 1; - int mx = cs->rbearing; - - for (int c = 1; c < nc; c++) { - // ignore the bearings for characters whose ink is - // completely outside the normal bounding box - if ((cs[c].lbearing <= 0 && cs[c].rbearing <= 0) || - (cs[c].lbearing >= cs[c].width && cs[c].rbearing >= cs[c].width)) - continue; - - int nmx = cs[c].rbearing; - - if (nmx < mx) - mx = nmx; - } - - ((QFontEngineXLFD *)this)->rbearing = mx; - } else - ((QFontEngineXLFD *)this)->rbearing = _fs->min_bounds.rbearing; - } - return rbearing; -} - -const char *QFontEngineXLFD::name() const -{ - return _name; -} - -bool QFontEngineXLFD::canRender(const QChar *string, int len) -{ - QVarLengthGlyphLayoutArray glyphs(len); - int nglyphs = len; - if (stringToCMap(string, len, &glyphs, &nglyphs, 0) == false) { - glyphs.resize(nglyphs); - stringToCMap(string, len, &glyphs, &nglyphs, 0); - } - - bool allExist = true; - for (int i = 0; i < nglyphs; i++) { - if (!glyphs.glyphs[i] || !charStruct(_fs, glyphs.glyphs[i])) { - allExist = false; - break; - } - } - - return allExist; -} - -QBitmap QFontEngineXLFD::bitmapForGlyphs(const QGlyphLayout &glyphs, const glyph_metrics_t &metrics, QTextItem::RenderFlags flags) -{ - int w = metrics.width.toInt(); - int h = metrics.height.toInt(); - if (w <= 0 || h <= 0) - return QBitmap(); - - QPixmapData *data = new QX11PixmapData(QPixmapData::BitmapType); - data->resize(w, h); - QPixmap bm(data); - QPainter p(&bm); - p.fillRect(0, 0, w, h, Qt::color0); - p.setPen(Qt::color1); - - QTextItemInt item; - item.flags = flags; - item.ascent = -metrics.y; - item.descent = metrics.height - item.ascent; - item.width = metrics.width; - item.chars = 0; - item.num_chars = 0; - item.logClusters = 0; - item.glyphs = glyphs; - item.fontEngine = this; - item.f = 0; - - p.drawTextItem(QPointF(-metrics.x.toReal(), item.ascent.toReal()), item); - p.end(); - - return QBitmap(bm); -} - -void QFontEngineXLFD::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) -{ - // cannot use QFontEngine::addBitmapFontToPath(), since we don't - // have direct access to the glyph bitmaps, so we have to draw - // onto a QBitmap, then convert to QImage, then to path - glyph_metrics_t metrics = boundingBox(glyphs); - - QImage image = bitmapForGlyphs(glyphs, metrics, flags).toImage(); - if (image.isNull()) - return; - - image = image.convertToFormat(QImage::Format_Mono); - const uchar *image_data = image.bits(); - uint bpl = image.bytesPerLine(); - // from qfontengine.cpp - extern void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, - int bpl, int w, int h, QPainterPath *path); - qt_addBitmapToPath(x, y + metrics.y.toReal(), image_data, bpl, image.width(), image.height(), path); -} - -QFontEngine::FaceId QFontEngineXLFD::faceId() const -{ -#ifndef QT_NO_FREETYPE - if (face_id.index == -1) { - face_id = fontFile(_name, &freetype, &synth); - if (_codec) - face_id.encoding = _codec->mibEnum(); - if (freetype) { - const_cast<QFontEngineXLFD *>(this)->fsType = freetype->fsType(); - } else { - face_id.index = 0; - face_id.filename = '-' + QFontEngine::properties().postscriptName; - } - } -#endif - - return face_id; -} - -QFontEngine::Properties QFontEngineXLFD::properties() const -{ - if (face_id.index == -1) - (void)faceId(); - -#ifndef QT_NO_FREETYPE - if (freetype) - return freetype->properties(); -#endif - return QFontEngine::properties(); -} - -void QFontEngineXLFD::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) -{ - if (face_id.index == -1) - (void)faceId(); -#ifndef QT_NO_FREETYPE - if (!freetype) -#endif - { - QFontEngine::getUnscaledGlyph(glyph, path, metrics); - return; - } - -#ifndef QT_NO_FREETYPE - freetype->lock(); - - FT_Face face = freetype->face; - FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0); - freetype->xsize = face->units_per_EM << 6; - freetype->ysize = face->units_per_EM << 6; - FT_Set_Transform(face, 0, 0); - glyph = glyphIndexToFreetypeGlyphIndex(glyph); - FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); - - int left = face->glyph->metrics.horiBearingX; - int right = face->glyph->metrics.horiBearingX + face->glyph->metrics.width; - int top = face->glyph->metrics.horiBearingY; - int bottom = face->glyph->metrics.horiBearingY - face->glyph->metrics.height; - - QFixedPoint p; - p.x = 0; - p.y = 0; - metrics->width = QFixed::fromFixed(right-left); - metrics->height = QFixed::fromFixed(top-bottom); - metrics->x = QFixed::fromFixed(left); - metrics->y = QFixed::fromFixed(-top); - metrics->xoff = QFixed::fromFixed(face->glyph->advance.x); - - if (!FT_IS_SCALABLE(freetype->face)) - QFreetypeFace::addBitmapToPath(face->glyph, p, path); - else - QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6); - - FT_Set_Transform(face, &freetype->matrix, 0); - freetype->unlock(); -#endif // QT_NO_FREETYPE -} - - -bool QFontEngineXLFD::getSfntTableData(uint tag, uchar *buffer, uint *length) const -{ -#ifndef QT_NO_FREETYPE - if (face_id.index == -1) - (void)faceId(); - if (!freetype) - return false; - return freetype->getSfntTable(tag, buffer, length); -#else - Q_UNUSED(tag); - Q_UNUSED(buffer); - Q_UNUSED(length); - return false; -#endif -} - -int QFontEngineXLFD::synthesized() const -{ - return synth; -} - -QImage QFontEngineXLFD::alphaMapForGlyph(glyph_t glyph) -{ - glyph_metrics_t metrics = boundingBox(glyph); - -/* - printf("a) w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n", - metrics.width.toReal(), - metrics.height.toReal(), - metrics.xoff.toReal(), - metrics.yoff.toReal(), - metrics.x.toReal(), - metrics.y.toReal()); -*/ - - QGlyphLayoutArray<1> glyphs; - glyphs.glyphs[0] = glyph; - - QImage image = bitmapForGlyphs(glyphs, metrics).toImage(); -//image.save(QString::fromLatin1("x11cache-%1.png").arg((int)glyph)); - - image = image.convertToFormat(QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i = 0; i < 256; ++i) - colors[i] = qRgba(0, 0, 0, i); - image.setColorTable(colors); - - int width = image.width(); - int height = image.height(); - for (int y = 0; y < height; ++y) { - uchar *bits = image.scanLine(y); - for (int x = 0; x < width; ++x) - bits[x] = ~(bits[x]-1); - } - - return image; -} - -#ifndef QT_NO_FREETYPE - -FT_Face QFontEngineXLFD::non_locked_face() const -{ - return freetype ? freetype->face : 0; -} - -uint QFontEngineXLFD::toUnicode(glyph_t g) const -{ - if (_codec) { - QTextCodec::ConverterState state; - state.flags = QTextCodec::ConvertInvalidToNull; - uchar data[2]; - int l = 1; - if (g > 255) { - data[0] = (g >> 8); - data[1] = (g & 255); - l = 2; - } else { - data[0] = g; - } - QString s = _codec->toUnicode((char *)data, l, &state); - Q_ASSERT(s.length() == 1); - g = s.at(0).unicode(); - } - return g; -} - -glyph_t QFontEngineXLFD::glyphIndexToFreetypeGlyphIndex(glyph_t g) const -{ - return FT_Get_Char_Index(freetype->face, toUnicode(g)); -} -#endif - -#ifndef QT_NO_FONTCONFIG - -// ------------------------------------------------------------------ -// Multi FT engine -// ------------------------------------------------------------------ - -static QFontEngine *engineForPattern(FcPattern *pattern, const QFontDef &request, - int screen) -{ - FcResult res; - FcPattern *match = FcFontMatch(0, pattern, &res); - QFontEngineX11FT *engine = new QFontEngineX11FT(match, request, screen); - if (!engine->invalid()) - return engine; - - delete engine; - QFontEngine *fe = new QFontEngineBox(request.pixelSize); - fe->fontDef = request; - return fe; -} - -QFontEngineMultiFT::QFontEngineMultiFT(QFontEngine *fe, FcPattern *matchedPattern, FcPattern *p, int s, const QFontDef &req) - : QFontEngineMulti(2), request(req), pattern(p), firstEnginePattern(matchedPattern), fontSet(0), screen(s) -{ - - engines[0] = fe; - engines.at(0)->ref.ref(); - fontDef = engines[0]->fontDef; - cache_cost = 100; - firstFontIndex = 1; -} - -QFontEngineMultiFT::~QFontEngineMultiFT() -{ - extern QMutex *qt_fontdatabase_mutex(); - QMutexLocker locker(qt_fontdatabase_mutex()); - - FcPatternDestroy(pattern); - if (firstEnginePattern) - FcPatternDestroy(firstEnginePattern); - if (fontSet) - FcFontSetDestroy(fontSet); -} - - -void QFontEngineMultiFT::loadEngine(int at) -{ - extern QMutex *qt_fontdatabase_mutex(); - QMutexLocker locker(qt_fontdatabase_mutex()); - - extern void qt_addPatternProps(FcPattern *pattern, int screen, int script, - const QFontDef &request); - extern QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &); - extern FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request); - - Q_ASSERT(at > 0); - if (!fontSet) { - fontSet = qt_fontSetForPattern(pattern, request); - - // it may happen that the fontset of fallbacks consists of only one font. In this case we - // have to fall back to the box fontengine as we cannot render the glyph. - if (fontSet->nfont == 1 && at == 1 && engines.size() == 2) { - Q_ASSERT(engines.at(at) == 0); - QFontEngine *fe = new QFontEngineBox(request.pixelSize); - fe->fontDef = request; - engines[at] = fe; - return; - } - - if (firstEnginePattern) { - - if (!FcPatternEqual(firstEnginePattern, fontSet->fonts[0])) - firstFontIndex = 0; - - FcPatternDestroy(firstEnginePattern); - firstEnginePattern = 0; - } - - engines.resize(fontSet->nfont + 1 - firstFontIndex); - } - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - FcPattern *pattern = FcPatternDuplicate(fontSet->fonts[at + firstFontIndex - 1]); - qt_addPatternProps(pattern, screen, QUnicodeTables::Common, request); - - QFontDef fontDef = qt_FcPatternToQFontDef(pattern, this->request); - - // note: we use -1 for the script to make sure that we keep real - // FT engines separate from Multi engines in the font cache - QFontCache::Key key(fontDef, -1, screen); - QFontEngine *fontEngine = QFontCache::instance()->findEngine(key); - if (!fontEngine) { - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - fontEngine = engineForPattern(pattern, request, screen); - QFontCache::instance()->insertEngine(key, fontEngine); - } - FcPatternDestroy(pattern); - fontEngine->ref.ref(); - engines[at] = fontEngine; -} - -// ------------------------------------------------------------------ -// X11 FT engine -// ------------------------------------------------------------------ - - - -Q_GUI_EXPORT void qt_x11ft_convert_pattern(FcPattern *pattern, QByteArray *file_name, int *index, bool *antialias) -{ - FcChar8 *fileName; - FcPatternGetString(pattern, FC_FILE, 0, &fileName); - *file_name = (const char *)fileName; - if (!FcPatternGetInteger(pattern, FC_INDEX, 0, index)) - index = 0; - FcBool b; - if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &b) == FcResultMatch) - *antialias = b; -} - - -QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int screen) - : QFontEngineFT(fd) -{ -// FcPatternPrint(pattern); - - bool antialias = X11->fc_antialias; - QByteArray file_name; - int face_index; - qt_x11ft_convert_pattern(pattern, &file_name, &face_index, &antialias); - QFontEngine::FaceId face_id; - face_id.filename = file_name; - face_id.index = face_index; - - canUploadGlyphsToServer = QApplication::testAttribute(Qt::AA_X11InitThreads) || (qApp->thread() == QThread::currentThread()); - - subpixelType = Subpixel_None; - if (antialias) { - int subpixel = X11->display ? X11->screens[screen].subpixel : FC_RGBA_UNKNOWN; - if (subpixel == FC_RGBA_UNKNOWN) - (void) FcPatternGetInteger(pattern, FC_RGBA, 0, &subpixel); - if (!antialias || subpixel == FC_RGBA_UNKNOWN) - subpixel = FC_RGBA_NONE; - - switch (subpixel) { - case FC_RGBA_NONE: subpixelType = Subpixel_None; break; - case FC_RGBA_RGB: subpixelType = Subpixel_RGB; break; - case FC_RGBA_BGR: subpixelType = Subpixel_BGR; break; - case FC_RGBA_VRGB: subpixelType = Subpixel_VRGB; break; - case FC_RGBA_VBGR: subpixelType = Subpixel_VBGR; break; - default: break; - } - } - - if (fd.hintingPreference != QFont::PreferDefaultHinting) { - switch (fd.hintingPreference) { - case QFont::PreferNoHinting: - default_hint_style = HintNone; - break; - case QFont::PreferVerticalHinting: - default_hint_style = HintLight; - break; - case QFont::PreferFullHinting: - default: - default_hint_style = HintFull; - break; - } - } -#ifdef FC_HINT_STYLE - else { - int hint_style = 0; - // Try to use Xft.hintstyle from XDefaults first if running in GNOME, to match - // the behavior of cairo - if (X11->fc_hint_style > -1 && X11->desktopEnvironment == DE_GNOME) - hint_style = X11->fc_hint_style; - else if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch - && X11->fc_hint_style > -1) - hint_style = X11->fc_hint_style; - - switch (hint_style) { - case FC_HINT_NONE: - default_hint_style = HintNone; - break; - case FC_HINT_SLIGHT: - default_hint_style = HintLight; - break; - case FC_HINT_MEDIUM: - default_hint_style = HintMedium; - break; - default: - default_hint_style = HintFull; - break; - } - } -#endif - -#if defined(FC_AUTOHINT) && defined(FT_LOAD_FORCE_AUTOHINT) - { - bool autohint = false; - - FcBool b; - if (FcPatternGetBool(pattern, FC_AUTOHINT, 0, &b) == FcResultMatch) - autohint = b; - - if (autohint) - default_load_flags |= FT_LOAD_FORCE_AUTOHINT; - } -#endif - -#if defined(FC_LCD_FILTER) && defined(FT_LCD_FILTER_H) - { - int filter = FC_LCD_FILTER_NONE; - if (FcPatternGetInteger(pattern, FC_LCD_FILTER, 0, &filter) == FcResultMatch) { - switch (filter) { - case FC_LCD_FILTER_NONE: - lcdFilterType = FT_LCD_FILTER_NONE; - break; - case FC_LCD_FILTER_DEFAULT: - lcdFilterType = FT_LCD_FILTER_DEFAULT; - break; - case FC_LCD_FILTER_LIGHT: - lcdFilterType = FT_LCD_FILTER_LIGHT; - break; - case FC_LCD_FILTER_LEGACY: - lcdFilterType = FT_LCD_FILTER_LEGACY; - break; - default: - // new unknown lcd filter type?! - break; - } - } - } -#endif - -#ifdef FC_EMBEDDED_BITMAP - { - FcBool b; - if (FcPatternGetBool(pattern, FC_EMBEDDED_BITMAP, 0, &b) == FcResultMatch) - embeddedbitmap = b; - } -#endif - - GlyphFormat defaultFormat = Format_None; - -#ifndef QT_NO_XRENDER - if (X11->use_xrender) { - int format = PictStandardA8; - if (!antialias) - format = PictStandardA1; - else if (subpixelType == Subpixel_RGB - || subpixelType == Subpixel_BGR - || subpixelType == Subpixel_VRGB - || subpixelType == Subpixel_VBGR) - format = PictStandardARGB32; - xglyph_format = format; - - if (subpixelType != QFontEngineFT::Subpixel_None) - defaultFormat = Format_A32; - else if (antialias) - defaultFormat = Format_A8; - else - defaultFormat = Format_Mono; - } -#endif - - if (!init(face_id, antialias, defaultFormat)) { - FcPatternDestroy(pattern); - return; - } - - if (!freetype->charset) { - FcCharSet *cs; - FcPatternGetCharSet (pattern, FC_CHARSET, 0, &cs); - freetype->charset = FcCharSetCopy(cs); - } - FcPatternDestroy(pattern); -} - -QFontEngineX11FT::~QFontEngineX11FT() -{ - freeGlyphSets(); -} - -unsigned long QFontEngineX11FT::allocateServerGlyphSet() -{ -#ifndef QT_NO_XRENDER - if (!canUploadGlyphsToServer || !X11->use_xrender) - return 0; - return XRenderCreateGlyphSet(X11->display, XRenderFindStandardFormat(X11->display, xglyph_format)); -#else - return 0; -#endif -} - -void QFontEngineX11FT::freeServerGlyphSet(unsigned long id) -{ -#ifndef QT_NO_XRENDER - if (!id) - return; - XRenderFreeGlyphSet(X11->display, id); -#endif -} - -bool QFontEngineX11FT::uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const -{ -#ifndef QT_NO_XRENDER - if (!canUploadGlyphsToServer) - return false; - if (g->format == Format_Mono) { - /* - * swap bit order around; FreeType is always MSBFirst - */ - if (BitmapBitOrder(X11->display) != MSBFirst) { - unsigned char *line = g->data; - int i = glyphDataSize; - while (i--) { - unsigned char c; - c = *line; - c = ((c << 1) & 0xaa) | ((c >> 1) & 0x55); - c = ((c << 2) & 0xcc) | ((c >> 2) & 0x33); - c = ((c << 4) & 0xf0) | ((c >> 4) & 0x0f); - *line++ = c; - } - } - } - - ::Glyph xglyph = glyphid; - XRenderAddGlyphs (X11->display, set->id, &xglyph, info, 1, (const char *)g->data, glyphDataSize); - delete [] g->data; - g->data = 0; - g->format = Format_None; - g->uploadedToServer = true; - return true; -#else - return false; -#endif -} - -QFontEngine *QFontEngineX11FT::cloneWithSize(qreal pixelSize) const -{ - QFontDef fontDef; - fontDef.pixelSize = pixelSize; - QFontEngineX11FT *fe = new QFontEngineX11FT(fontDef); - if (!fe->initFromFontEngine(this)) { - delete fe; - return 0; - } else { - fe->xglyph_format = xglyph_format; - return fe; - } -} - -#endif // QT_NO_FONTCONFIG - -QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_x11_p.h b/src/gui/text/qfontengine_x11_p.h deleted file mode 100644 index d7eb39daaa..0000000000 --- a/src/gui/text/qfontengine_x11_p.h +++ /dev/null @@ -1,180 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QFONTENGINE_X11_P_H -#define QFONTENGINE_X11_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// -#include <private/qt_x11_p.h> - -#include <private/qfontengine_ft_p.h> - -QT_BEGIN_NAMESPACE - -class QFreetypeFace; - -// -------------------------------------------------------------------------- - -class QFontEngineMultiXLFD : public QFontEngineMulti -{ -public: - QFontEngineMultiXLFD(const QFontDef &r, const QList<int> &l, int s); - ~QFontEngineMultiXLFD(); - - void loadEngine(int at); - -private: - QList<int> encodings; - int screen; - QFontDef request; -}; - -/** - * \internal The font engine for X Logical Font Description (XLFD) fonts, which is for X11 systems without freetype. - */ -class QFontEngineXLFD : public QFontEngine -{ -public: - QFontEngineXLFD(XFontStruct *f, const QByteArray &name, int mib); - ~QFontEngineXLFD(); - - virtual QFontEngine::FaceId faceId() const; - QFontEngine::Properties properties() const; - virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics); - virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - virtual int synthesized() const; - - virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, - QTextEngine::ShaperFlags flags) const; - virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; - - virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - virtual glyph_metrics_t boundingBox(glyph_t glyph); - - virtual void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags); - virtual QFixed ascent() const; - virtual QFixed descent() const; - virtual QFixed leading() const; - virtual qreal maxCharWidth() const; - virtual qreal minLeftBearing() const; - virtual qreal minRightBearing() const; - virtual QImage alphaMapForGlyph(glyph_t); - - virtual inline Type type() const - { return QFontEngine::XLFD; } - - virtual bool canRender(const QChar *string, int len); - virtual const char *name() const; - - inline XFontStruct *fontStruct() const - { return _fs; } - -#ifndef QT_NO_FREETYPE - FT_Face non_locked_face() const; - glyph_t glyphIndexToFreetypeGlyphIndex(glyph_t g) const; -#endif - uint toUnicode(glyph_t g) const; - -private: - QBitmap bitmapForGlyphs(const QGlyphLayout &glyphs, const glyph_metrics_t &metrics, QTextItem::RenderFlags flags = 0); - - XFontStruct *_fs; - QByteArray _name; - QTextCodec *_codec; - int _cmap; - int lbearing, rbearing; - mutable QFontEngine::FaceId face_id; - mutable QFreetypeFace *freetype; - mutable int synth; -}; - -#ifndef QT_NO_FONTCONFIG - -class Q_GUI_EXPORT QFontEngineMultiFT : public QFontEngineMulti -{ -public: - QFontEngineMultiFT(QFontEngine *fe, FcPattern *firstEnginePattern, FcPattern *p, int s, const QFontDef &request); - ~QFontEngineMultiFT(); - - void loadEngine(int at); - -private: - QFontDef request; - FcPattern *pattern; - FcPattern *firstEnginePattern; - FcFontSet *fontSet; - int screen; - int firstFontIndex; // first font in fontset -}; - -class Q_GUI_EXPORT QFontEngineX11FT : public QFontEngineFT -{ -public: - explicit QFontEngineX11FT(const QFontDef &fontDef) : QFontEngineFT(fontDef) {} - explicit QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int screen); - ~QFontEngineX11FT(); - - QFontEngine *cloneWithSize(qreal pixelSize) const; - -#ifndef QT_NO_XRENDER - int xglyph_format; -#endif - -protected: - virtual bool uploadGlyphToServer(QGlyphSet *set, uint glyphid, Glyph *g, GlyphInfo *info, int glyphDataSize) const; - virtual unsigned long allocateServerGlyphSet(); - virtual void freeServerGlyphSet(unsigned long id); -}; - -#endif // QT_NO_FONTCONFIG - -QT_END_NAMESPACE - -#endif // QFONTENGINE_X11_P_H diff --git a/src/gui/text/qfontmetrics.h b/src/gui/text/qfontmetrics.h index 5fe8676993..56e5a5c6bb 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -122,15 +122,6 @@ public: inline bool operator !=(const QFontMetrics &other) { return !operator==(other); } // 5.0 - remove me inline bool operator !=(const QFontMetrics &other) const { return !operator==(other); } -#ifdef QT3_SUPPORT - inline QRect boundingRect(const QString &text, int len) const - { return boundingRect(text.left(len)); } - inline QRect boundingRect(int x, int y, int w, int h, int flags, const QString& str, int len, - int tabstops=0, int *tabarray=0) const - { return boundingRect(QRect(x, y, w, h), flags, str.left(len), tabstops, tabarray); } - inline QSize size(int flags, const QString& str, int len, int tabstops=0, int *tabarray=0) const - { return size(flags, str.left(len), tabstops, tabarray); } -#endif private: #if defined(Q_WS_MAC) friend class QFontPrivate; diff --git a/src/gui/text/qrawfont_mac.cpp b/src/gui/text/qrawfont_mac.cpp deleted file mode 100644 index 1ed4185a5d..0000000000 --- a/src/gui/text/qrawfont_mac.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtCore/qglobal.h> - -#if !defined(QT_NO_RAWFONT) - -#include "qrawfont_p.h" -#include "qfontengine_coretext_p.h" - -QT_BEGIN_NAMESPACE - -void QRawFontPrivate::platformCleanUp() -{ -} - -extern int qt_defaultDpi(); - -void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, - int pixelSize, - QFont::HintingPreference hintingPreference) -{ - // Mac OS X ignores it - Q_UNUSED(hintingPreference); - - QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(NULL, - fontData.constData(), fontData.size(), NULL); - - CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider); - - if (cgFont == NULL) { - qWarning("QRawFont::platformLoadFromData: CGFontCreateWithDataProvider failed"); - } else { - QFontDef def; - def.pixelSize = pixelSize; - def.pointSize = pixelSize * 72.0 / qt_defaultDpi(); - fontEngine = new QCoreTextFontEngine(cgFont, def); - CFRelease(cgFont); - fontEngine->ref.ref(); - } -} - -QT_END_NAMESPACE - -#endif // QT_NO_RAWFONT diff --git a/src/gui/text/qrawfont_qpa.cpp b/src/gui/text/qrawfont_qpa.cpp index 103619c37d..6c8befec60 100644 --- a/src/gui/text/qrawfont_qpa.cpp +++ b/src/gui/text/qrawfont_qpa.cpp @@ -45,7 +45,7 @@ #include "qrawfont_p.h" #include <QtGui/qplatformfontdatabase_qpa.h> -#include <private/qapplication_p.h> +#include <private/qguiapplication_p.h> QT_BEGIN_NAMESPACE @@ -58,7 +58,7 @@ void QRawFontPrivate::platformLoadFromData(const QByteArray &fontData, int pixel { Q_ASSERT(fontEngine == 0); - QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase(); + QPlatformFontDatabase *pfdb = QGuiApplicationPrivate::platformIntegration()->fontDatabase(); fontEngine = pfdb->fontEngine(fontData, pixelSize, hintingPreference); if (fontEngine != 0) fontEngine->ref.ref(); diff --git a/src/gui/text/qrawfont_win.cpp b/src/gui/text/qrawfont_win.cpp deleted file mode 100644 index d8acf57431..0000000000 --- a/src/gui/text/qrawfont_win.cpp +++ /dev/null @@ -1,707 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qrawfont_p.h" -#include <private/qsystemlibrary_p.h> - -#if !defined(QT_NO_DIRECTWRITE) -# include "qfontenginedirectwrite_p.h" -# include <dwrite.h> -#endif - -#if !defined(QT_NO_RAWFONT) - -QT_BEGIN_NAMESPACE - -namespace { - - template<typename T> - struct BigEndian - { - quint8 data[sizeof(T)]; - - operator T() const - { - T littleEndian = 0; - for (int i=0; i<sizeof(T); ++i) { - littleEndian |= data[i] << ((sizeof(T) - i - 1) * 8); - } - - return littleEndian; - } - - BigEndian<T> &operator=(const T &t) - { - for (int i=0; i<sizeof(T); ++i) { - data[i] = ((t >> (sizeof(T) - i - 1) * 8) & 0xff); - } - - return *this; - } - }; - -# pragma pack(1) - - // Common structure for all formats of the "name" table - struct NameTable - { - BigEndian<quint16> format; - BigEndian<quint16> count; - BigEndian<quint16> stringOffset; - }; - - struct NameRecord - { - BigEndian<quint16> platformID; - BigEndian<quint16> encodingID; - BigEndian<quint16> languageID; - BigEndian<quint16> nameID; - BigEndian<quint16> length; - BigEndian<quint16> offset; - }; - - struct OffsetSubTable - { - BigEndian<quint32> scalerType; - BigEndian<quint16> numTables; - BigEndian<quint16> searchRange; - BigEndian<quint16> entrySelector; - BigEndian<quint16> rangeShift; - }; - - struct TableDirectory - { - BigEndian<quint32> identifier; - BigEndian<quint32> checkSum; - BigEndian<quint32> offset; - BigEndian<quint32> length; - }; - - struct OS2Table - { - BigEndian<quint16> version; - BigEndian<qint16> avgCharWidth; - BigEndian<quint16> weightClass; - BigEndian<quint16> widthClass; - BigEndian<quint16> type; - BigEndian<qint16> subscriptXSize; - BigEndian<qint16> subscriptYSize; - BigEndian<qint16> subscriptXOffset; - BigEndian<qint16> subscriptYOffset; - BigEndian<qint16> superscriptXSize; - BigEndian<qint16> superscriptYSize; - BigEndian<qint16> superscriptXOffset; - BigEndian<qint16> superscriptYOffset; - BigEndian<qint16> strikeOutSize; - BigEndian<qint16> strikeOutPosition; - BigEndian<qint16> familyClass; - quint8 panose[10]; - BigEndian<quint32> unicodeRanges[4]; - quint8 vendorID[4]; - BigEndian<quint16> selection; - BigEndian<quint16> firstCharIndex; - BigEndian<quint16> lastCharIndex; - BigEndian<qint16> typoAscender; - BigEndian<qint16> typoDescender; - BigEndian<qint16> typoLineGap; - BigEndian<quint16> winAscent; - BigEndian<quint16> winDescent; - BigEndian<quint32> codepageRanges[2]; - BigEndian<qint16> height; - BigEndian<qint16> capHeight; - BigEndian<quint16> defaultChar; - BigEndian<quint16> breakChar; - BigEndian<quint16> maxContext; - }; - -# pragma pack() - - class EmbeddedFont - { - public: - EmbeddedFont(const QByteArray &fontData); - - QString changeFamilyName(const QString &newFamilyName); - QByteArray data() const { return m_fontData; } - TableDirectory *tableDirectoryEntry(const QByteArray &tagName); - QString familyName(TableDirectory *nameTableDirectory = 0); - - private: - QByteArray m_fontData; - }; - - EmbeddedFont::EmbeddedFont(const QByteArray &fontData) : m_fontData(fontData) - { - } - - TableDirectory *EmbeddedFont::tableDirectoryEntry(const QByteArray &tagName) - { - Q_ASSERT(tagName.size() == 4); - - const BigEndian<quint32> *tagIdPtr = - reinterpret_cast<const BigEndian<quint32> *>(tagName.constData()); - quint32 tagId = *tagIdPtr; - - OffsetSubTable *offsetSubTable = reinterpret_cast<OffsetSubTable *>(m_fontData.data()); - TableDirectory *tableDirectory = reinterpret_cast<TableDirectory *>(offsetSubTable + 1); - - TableDirectory *nameTableDirectoryEntry = 0; - for (int i=0; i<offsetSubTable->numTables; ++i, ++tableDirectory) { - if (tableDirectory->identifier == tagId) { - nameTableDirectoryEntry = tableDirectory; - break; - } - } - - return nameTableDirectoryEntry; - } - - QString EmbeddedFont::familyName(TableDirectory *nameTableDirectoryEntry) - { - QString name; - - if (nameTableDirectoryEntry == 0) - nameTableDirectoryEntry = tableDirectoryEntry("name"); - - if (nameTableDirectoryEntry != 0) { - NameTable *nameTable = reinterpret_cast<NameTable *>(m_fontData.data() - + nameTableDirectoryEntry->offset); - NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1); - for (int i=0; i<nameTable->count; ++i, ++nameRecord) { - if (nameRecord->nameID == 1 - && nameRecord->platformID == 3 // Windows - && nameRecord->languageID == 0x0409) { // US English - const void *ptr = reinterpret_cast<const quint8 *>(nameTable) - + nameTable->stringOffset - + nameRecord->offset; - - const BigEndian<quint16> *s = reinterpret_cast<const BigEndian<quint16> *>(ptr); - for (int j=0; j<nameRecord->length / sizeof(quint16); ++j) - name += QChar(s[j]); - - break; - } - } - } - - return name; - } - - QString EmbeddedFont::changeFamilyName(const QString &newFamilyName) - { - TableDirectory *nameTableDirectoryEntry = tableDirectoryEntry("name"); - if (nameTableDirectoryEntry == 0) - return QString(); - - QString oldFamilyName = familyName(nameTableDirectoryEntry); - - // Reserve size for name table header, five required name records and string - const int requiredRecordCount = 5; - quint16 nameIds[requiredRecordCount] = { 1, 2, 3, 4, 6 }; - - int sizeOfHeader = sizeof(NameTable) + sizeof(NameRecord) * requiredRecordCount; - int newFamilyNameSize = newFamilyName.size() * sizeof(quint16); - - const QString regularString = QString::fromLatin1("Regular"); - int regularStringSize = regularString.size() * sizeof(quint16); - - // Align table size of table to 32 bits (pad with 0) - int fullSize = ((sizeOfHeader + newFamilyNameSize + regularStringSize) & ~3) + 4; - - QByteArray newNameTable(fullSize, char(0)); - - { - NameTable *nameTable = reinterpret_cast<NameTable *>(newNameTable.data()); - nameTable->count = requiredRecordCount; - nameTable->stringOffset = sizeOfHeader; - - NameRecord *nameRecord = reinterpret_cast<NameRecord *>(nameTable + 1); - for (int i=0; i<requiredRecordCount; ++i, nameRecord++) { - nameRecord->nameID = nameIds[i]; - nameRecord->encodingID = 1; - nameRecord->languageID = 0x0409; - nameRecord->platformID = 3; - nameRecord->length = newFamilyNameSize; - - // Special case for sub-family - if (nameIds[i] == 4) { - nameRecord->offset = newFamilyNameSize; - nameRecord->length = regularStringSize; - } - } - - // nameRecord now points to string data - BigEndian<quint16> *stringStorage = reinterpret_cast<BigEndian<quint16> *>(nameRecord); - const quint16 *sourceString = newFamilyName.utf16(); - for (int i=0; i<newFamilyName.size(); ++i) - stringStorage[i] = sourceString[i]; - stringStorage += newFamilyName.size(); - - sourceString = regularString.utf16(); - for (int i=0; i<regularString.size(); ++i) - stringStorage[i] = sourceString[i]; - } - - quint32 *p = reinterpret_cast<quint32 *>(newNameTable.data()); - quint32 *tableEnd = reinterpret_cast<quint32 *>(newNameTable.data() + fullSize); - - quint32 checkSum = 0; - while (p < tableEnd) - checkSum += *(p++); - - nameTableDirectoryEntry->checkSum = checkSum; - nameTableDirectoryEntry->offset = m_fontData.size(); - nameTableDirectoryEntry->length = fullSize; - - m_fontData.append(newNameTable); - - return oldFamilyName; - } - -#if !defined(QT_NO_DIRECTWRITE) - - class DirectWriteFontFileStream: public IDWriteFontFileStream - { - public: - DirectWriteFontFileStream(const QByteArray &fontData) - : m_fontData(fontData) - , m_referenceCount(0) - { - } - - ~DirectWriteFontFileStream() - { - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE ReadFileFragment(const void **fragmentStart, UINT64 fileOffset, - UINT64 fragmentSize, OUT void **fragmentContext); - void STDMETHODCALLTYPE ReleaseFileFragment(void *fragmentContext); - HRESULT STDMETHODCALLTYPE GetFileSize(OUT UINT64 *fileSize); - HRESULT STDMETHODCALLTYPE GetLastWriteTime(OUT UINT64 *lastWriteTime); - - private: - QByteArray m_fontData; - ULONG m_referenceCount; - }; - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::QueryInterface(REFIID iid, void **object) - { - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileStream)) { - *object = this; - AddRef(); - return S_OK; - } else { - *object = NULL; - return E_NOINTERFACE; - } - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::AddRef() - { - return InterlockedIncrement(&m_referenceCount); - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileStream::Release() - { - ULONG newCount = InterlockedDecrement(&m_referenceCount); - if (newCount == 0) - delete this; - return newCount; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::ReadFileFragment( - const void **fragmentStart, - UINT64 fileOffset, - UINT64 fragmentSize, - OUT void **fragmentContext) - { - *fragmentContext = NULL; - if (fragmentSize + fileOffset <= m_fontData.size()) { - *fragmentStart = m_fontData.data() + fileOffset; - return S_OK; - } else { - *fragmentStart = NULL; - return E_FAIL; - } - } - - void STDMETHODCALLTYPE DirectWriteFontFileStream::ReleaseFileFragment(void *) - { - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetFileSize(UINT64 *fileSize) - { - *fileSize = m_fontData.size(); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileStream::GetLastWriteTime(UINT64 *lastWriteTime) - { - *lastWriteTime = 0; - return E_NOTIMPL; - } - - class DirectWriteFontFileLoader: public IDWriteFontFileLoader - { - public: - DirectWriteFontFileLoader() : m_referenceCount(0) {} - - ~DirectWriteFontFileLoader() - { - } - - inline void addKey(const void *key, const QByteArray &fontData) - { - Q_ASSERT(!m_fontDatas.contains(key)); - m_fontDatas.insert(key, fontData); - } - - inline void removeKey(const void *key) - { - m_fontDatas.remove(key); - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **object); - ULONG STDMETHODCALLTYPE AddRef(); - ULONG STDMETHODCALLTYPE Release(); - - HRESULT STDMETHODCALLTYPE CreateStreamFromKey(void const *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - OUT IDWriteFontFileStream **fontFileStream); - - private: - ULONG m_referenceCount; - QHash<const void *, QByteArray> m_fontDatas; - }; - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::QueryInterface(const IID &iid, - void **object) - { - if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { - *object = this; - AddRef(); - return S_OK; - } else { - *object = NULL; - return E_NOINTERFACE; - } - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::AddRef() - { - return InterlockedIncrement(&m_referenceCount); - } - - ULONG STDMETHODCALLTYPE DirectWriteFontFileLoader::Release() - { - ULONG newCount = InterlockedDecrement(&m_referenceCount); - if (newCount == 0) - delete this; - return newCount; - } - - HRESULT STDMETHODCALLTYPE DirectWriteFontFileLoader::CreateStreamFromKey( - void const *fontFileReferenceKey, - UINT32 fontFileReferenceKeySize, - IDWriteFontFileStream **fontFileStream) - { - Q_UNUSED(fontFileReferenceKeySize); - - if (fontFileReferenceKeySize != sizeof(const void *)) { - qWarning("DirectWriteFontFileLoader::CreateStreamFromKey: Wrong key size"); - return E_FAIL; - } - - const void *key = *reinterpret_cast<void * const *>(fontFileReferenceKey); - *fontFileStream = NULL; - if (!m_fontDatas.contains(key)) - return E_FAIL; - - QByteArray fontData = m_fontDatas.value(key); - DirectWriteFontFileStream *stream = new DirectWriteFontFileStream(fontData); - stream->AddRef(); - *fontFileStream = stream; - - return S_OK; - } - - class CustomFontFileLoader - { - public: - CustomFontFileLoader() : m_directWriteFactory(0), m_directWriteFontFileLoader(0) - { - HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast<IUnknown **>(&m_directWriteFactory)); - if (FAILED(hres)) { - qErrnoWarning(hres, "CustomFontFileLoader::CustomFontFileLoader: " - "DWriteCreateFactory failed."); - } else { - m_directWriteFontFileLoader = new DirectWriteFontFileLoader(); - m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader); - } - } - - ~CustomFontFileLoader() - { - if (m_directWriteFactory != 0 && m_directWriteFontFileLoader != 0) - m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader); - - if (m_directWriteFactory != 0) - m_directWriteFactory->Release(); - } - - void addKey(const void *key, const QByteArray &fontData) - { - if (m_directWriteFontFileLoader != 0) - m_directWriteFontFileLoader->addKey(key, fontData); - } - - void removeKey(const void *key) - { - if (m_directWriteFontFileLoader != 0) - m_directWriteFontFileLoader->removeKey(key); - } - - IDWriteFontFileLoader *loader() const - { - return m_directWriteFontFileLoader; - } - - private: - IDWriteFactory *m_directWriteFactory; - DirectWriteFontFileLoader *m_directWriteFontFileLoader; - }; - -#endif - -} // Anonymous namespace - - -// From qfontdatabase_win.cpp -extern QFontEngine *qt_load_font_engine_win(const QFontDef &request); -// From qfontdatabase.cpp -extern QFont::Weight weightFromInteger(int weight); - -void QRawFontPrivate::platformCleanUp() -{ - if (fontHandle != NULL) { - if (ptrRemoveFontMemResourceEx == NULL) { - void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx"); - ptrRemoveFontMemResourceEx = - reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func); - } - - if (ptrRemoveFontMemResourceEx == NULL) { - qWarning("QRawFont::platformCleanUp: Can't find RemoveFontMemResourceEx in gdi32"); - fontHandle = NULL; - } else { - ptrRemoveFontMemResourceEx(fontHandle); - fontHandle = NULL; - } - } -} - -void QRawFontPrivate::platformLoadFromData(const QByteArray &_fontData, - int pixelSize, - QFont::HintingPreference hintingPreference) -{ - QByteArray fontData(_fontData); - EmbeddedFont font(fontData); - -#if !defined(QT_NO_DIRECTWRITE) - if (hintingPreference == QFont::PreferDefaultHinting - || hintingPreference == QFont::PreferFullHinting) -#endif - { - GUID guid; - CoCreateGuid(&guid); - - QString uniqueFamilyName = QString::fromLatin1("f") - + QString::number(guid.Data1, 36) + QLatin1Char('-') - + QString::number(guid.Data2, 36) + QLatin1Char('-') - + QString::number(guid.Data3, 36) + QLatin1Char('-') - + QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36); - - QString actualFontName = font.changeFamilyName(uniqueFamilyName); - if (actualFontName.isEmpty()) { - qWarning("QRawFont::platformLoadFromData: Can't change family name of font"); - return; - } - - if (ptrAddFontMemResourceEx == NULL || ptrRemoveFontMemResourceEx == NULL) { - void *func = QSystemLibrary::resolve(QLatin1String("gdi32"), "RemoveFontMemResourceEx"); - ptrRemoveFontMemResourceEx = - reinterpret_cast<QRawFontPrivate::PtrRemoveFontMemResourceEx>(func); - - func = QSystemLibrary::resolve(QLatin1String("gdi32"), "AddFontMemResourceEx"); - ptrAddFontMemResourceEx = - reinterpret_cast<QRawFontPrivate::PtrAddFontMemResourceEx>(func); - } - - Q_ASSERT(fontHandle == NULL); - if (ptrAddFontMemResourceEx != NULL && ptrRemoveFontMemResourceEx != NULL) { - DWORD count = 0; - fontData = font.data(); - fontHandle = ptrAddFontMemResourceEx(fontData.data(), fontData.size(), 0, &count); - - if (count == 0 && fontHandle != NULL) { - ptrRemoveFontMemResourceEx(fontHandle); - fontHandle = NULL; - } - } - - if (fontHandle == NULL) { - qWarning("QRawFont::platformLoadFromData: AddFontMemResourceEx failed"); - } else { - QFontDef request; - request.family = uniqueFamilyName; - request.pixelSize = pixelSize; - request.styleStrategy = QFont::NoFontMerging | QFont::PreferMatch; - request.hintingPreference = hintingPreference; - - fontEngine = qt_load_font_engine_win(request); - if (request.family != fontEngine->fontDef.family) { - qWarning("QRawFont::platformLoadFromData: Failed to load font. " - "Got fallback instead: %s", qPrintable(fontEngine->fontDef.family)); - if (fontEngine->cache_count == 0 && fontEngine->ref == 0) - delete fontEngine; - fontEngine = 0; - } else { - Q_ASSERT(fontEngine->cache_count == 0 && fontEngine->ref == 0); - - // Override the generated font name - static_cast<QFontEngineWin *>(fontEngine)->uniqueFamilyName = uniqueFamilyName; - fontEngine->fontDef.family = actualFontName; - fontEngine->ref.ref(); - } - } - } -#if !defined(QT_NO_DIRECTWRITE) - else { - CustomFontFileLoader fontFileLoader; - fontFileLoader.addKey(this, fontData); - - IDWriteFactory *factory = NULL; - HRESULT hres = DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, - __uuidof(IDWriteFactory), - reinterpret_cast<IUnknown **>(&factory)); - if (FAILED(hres)) { - qErrnoWarning(hres, "QRawFont::platformLoadFromData: DWriteCreateFactory failed"); - return; - } - - IDWriteFontFile *fontFile = NULL; - void *key = this; - - hres = factory->CreateCustomFontFileReference(&key, sizeof(void *), - fontFileLoader.loader(), &fontFile); - if (FAILED(hres)) { - qErrnoWarning(hres, "QRawFont::platformLoadFromData: " - "CreateCustomFontFileReference failed"); - factory->Release(); - return; - } - - BOOL isSupportedFontType; - DWRITE_FONT_FILE_TYPE fontFileType; - DWRITE_FONT_FACE_TYPE fontFaceType; - UINT32 numberOfFaces; - fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces); - if (!isSupportedFontType) { - fontFile->Release(); - factory->Release(); - return; - } - - IDWriteFontFace *directWriteFontFace = NULL; - hres = factory->CreateFontFace(fontFaceType, 1, &fontFile, 0, DWRITE_FONT_SIMULATIONS_NONE, - &directWriteFontFace); - if (FAILED(hres)) { - qErrnoWarning(hres, "QRawFont::platformLoadFromData: CreateFontFace failed"); - fontFile->Release(); - factory->Release(); - return; - } - - fontFile->Release(); - - fontEngine = new QFontEngineDirectWrite(factory, directWriteFontFace, pixelSize); - - // Get font family from font data - fontEngine->fontDef.family = font.familyName(); - fontEngine->ref.ref(); - - directWriteFontFace->Release(); - factory->Release(); - } -#endif - - // Get style and weight info - if (fontEngine != 0) { - TableDirectory *os2TableEntry = font.tableDirectoryEntry("OS/2"); - if (os2TableEntry != 0) { - const OS2Table *os2Table = - reinterpret_cast<const OS2Table *>(fontData.constData() - + os2TableEntry->offset); - - bool italic = os2Table->selection & 1; - bool oblique = os2Table->selection & 128; - - if (italic) - fontEngine->fontDef.style = QFont::StyleItalic; - else if (oblique) - fontEngine->fontDef.style = QFont::StyleOblique; - else - fontEngine->fontDef.style = QFont::StyleNormal; - - fontEngine->fontDef.weight = weightFromInteger(os2Table->weightClass); - } - } -} - -QT_END_NAMESPACE - -#endif // QT_NO_RAWFONT diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index 5bee497a3e..397180cb2a 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -45,8 +45,6 @@ #include <private/qfontengine_p.h> #include <qabstracttextdocumentlayout.h> -#include <QtGui/qapplication.h> - QT_BEGIN_NAMESPACE /*! diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp index 6a3355b90d..5edd6375c9 100644 --- a/src/gui/text/qsyntaxhighlighter.cpp +++ b/src/gui/text/qsyntaxhighlighter.cpp @@ -50,7 +50,6 @@ #include <qtextobject.h> #include <qtextcursor.h> #include <qdebug.h> -#include <qtextedit.h> #include <qtimer.h> QT_BEGIN_NAMESPACE @@ -311,10 +310,19 @@ void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block) /*! Constructs a QSyntaxHighlighter with the given \a parent. + + If the parent is a QTextEdit, it installs the syntaxhighlighter on the + parents document. The specified QTextEdit also becomes the owner of + the QSyntaxHighlighter. */ QSyntaxHighlighter::QSyntaxHighlighter(QObject *parent) : QObject(*new QSyntaxHighlighterPrivate, parent) { + if (parent->inherits("QTextEdit")) { + QTextDocument *doc = qobject_cast<QTextDocument *>(parent->property("document").value<QObject *>()); + if (doc) + setDocument(doc); + } } /*! @@ -329,17 +337,6 @@ QSyntaxHighlighter::QSyntaxHighlighter(QTextDocument *parent) } /*! - Constructs a QSyntaxHighlighter and installs it on \a parent 's - QTextDocument. The specified QTextEdit also becomes the owner of - the QSyntaxHighlighter. -*/ -QSyntaxHighlighter::QSyntaxHighlighter(QTextEdit *parent) - : QObject(*new QSyntaxHighlighterPrivate, parent) -{ - setDocument(parent->document()); -} - -/*! Destructor. Uninstalls this syntax highlighter from the text document. */ QSyntaxHighlighter::~QSyntaxHighlighter() diff --git a/src/gui/text/qsyntaxhighlighter.h b/src/gui/text/qsyntaxhighlighter.h index 9cd5778074..33006cdd9e 100644 --- a/src/gui/text/qsyntaxhighlighter.h +++ b/src/gui/text/qsyntaxhighlighter.h @@ -61,7 +61,6 @@ class QTextCharFormat; class QFont; class QColor; class QTextBlockUserData; -class QTextEdit; class Q_GUI_EXPORT QSyntaxHighlighter : public QObject { @@ -70,7 +69,6 @@ class Q_GUI_EXPORT QSyntaxHighlighter : public QObject public: QSyntaxHighlighter(QObject *parent); QSyntaxHighlighter(QTextDocument *parent); - QSyntaxHighlighter(QTextEdit *parent); virtual ~QSyntaxHighlighter(); void setDocument(QTextDocument *doc); diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp deleted file mode 100644 index 43967307bc..0000000000 --- a/src/gui/text/qtextcontrol.cpp +++ /dev/null @@ -1,3148 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtextcontrol_p.h" -#include "qtextcontrol_p_p.h" - -#ifndef QT_NO_TEXTCONTROL - -#include <qfont.h> -#include <qpainter.h> -#include <qevent.h> -#include <qdebug.h> -#include <qmime.h> -#include <qdrag.h> -#include <qclipboard.h> -#include <qmenu.h> -#include <qstyle.h> -#include <qtimer.h> -#include "private/qtextdocumentlayout_p.h" -#include "private/qabstracttextdocumentlayout_p.h" -#include "private/qtextedit_p.h" -#include "qtextdocument.h" -#include "private/qtextdocument_p.h" -#include "qtextlist.h" -#include "private/qtextcontrol_p.h" -#include "qgraphicssceneevent.h" -#include "qprinter.h" -#include "qtextdocumentwriter.h" -#include "private/qtextcursor_p.h" - -#include <qtextformat.h> -#include <qdatetime.h> -#include <qbuffer.h> -#include <qapplication.h> -#include <limits.h> -#include <qtexttable.h> -#include <qvariant.h> -#include <qurl.h> -#include <qdesktopservices.h> -#include <qinputcontext.h> -#include <qtooltip.h> -#include <qstyleoption.h> -#include <QtGui/qlineedit.h> - -#ifndef QT_NO_SHORTCUT -#include "private/qapplication_p.h" -#include "private/qshortcutmap_p.h" -#include <qkeysequence.h> -#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString()) -#else -#define ACCEL_KEY(k) QString() -#endif - -QT_BEGIN_NAMESPACE - -#ifndef QT_NO_CONTEXTMENU -#if defined(Q_WS_WIN) || defined(Q_WS_X11) -extern bool qt_use_rtl_extensions; -#endif -#endif - -// could go into QTextCursor... -static QTextLine currentTextLine(const QTextCursor &cursor) -{ - const QTextBlock block = cursor.block(); - if (!block.isValid()) - return QTextLine(); - - const QTextLayout *layout = block.layout(); - if (!layout) - return QTextLine(); - - const int relativePos = cursor.position() - block.position(); - return layout->lineForTextPosition(relativePos); -} - -QTextControlPrivate::QTextControlPrivate() - : doc(0), cursorOn(false), cursorIsFocusIndicator(false), - interactionFlags(Qt::TextEditorInteraction), - dragEnabled(true), -#ifndef QT_NO_DRAGANDDROP - mousePressed(false), mightStartDrag(false), -#endif - lastSelectionState(false), ignoreAutomaticScrollbarAdjustement(false), - overwriteMode(false), - acceptRichText(true), - preeditCursor(0), hideCursor(false), - hasFocus(false), -#ifdef QT_KEYPAD_NAVIGATION - hasEditFocus(false), -#endif - isEnabled(true), - hadSelectionOnMousePress(false), - ignoreUnusedNavigationEvents(false), - openExternalLinks(false), - wordSelectionEnabled(false) -{} - -bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) -{ -#ifdef QT_NO_SHORTCUT - Q_UNUSED(e); -#endif - - Q_Q(QTextControl); - if (cursor.isNull()) - return false; - - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - - QTextCursor::MoveMode mode = QTextCursor::MoveAnchor; - QTextCursor::MoveOperation op = QTextCursor::NoMove; - - if (false) { - } -#ifndef QT_NO_SHORTCUT - if (e == QKeySequence::MoveToNextChar) { - op = QTextCursor::Right; - } - else if (e == QKeySequence::MoveToPreviousChar) { - op = QTextCursor::Left; - } - else if (e == QKeySequence::SelectNextChar) { - op = QTextCursor::Right; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectPreviousChar) { - op = QTextCursor::Left; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectNextWord) { - op = QTextCursor::WordRight; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectPreviousWord) { - op = QTextCursor::WordLeft; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectStartOfLine) { - op = QTextCursor::StartOfLine; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectEndOfLine) { - op = QTextCursor::EndOfLine; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectStartOfBlock) { - op = QTextCursor::StartOfBlock; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectEndOfBlock) { - op = QTextCursor::EndOfBlock; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectStartOfDocument) { - op = QTextCursor::Start; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectEndOfDocument) { - op = QTextCursor::End; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectPreviousLine) { - op = QTextCursor::Up; - mode = QTextCursor::KeepAnchor; - } - else if (e == QKeySequence::SelectNextLine) { - op = QTextCursor::Down; - mode = QTextCursor::KeepAnchor; - { - QTextBlock block = cursor.block(); - QTextLine line = currentTextLine(cursor); - if (!block.next().isValid() - && line.isValid() - && line.lineNumber() == block.layout()->lineCount() - 1) - op = QTextCursor::End; - } - } - else if (e == QKeySequence::MoveToNextWord) { - op = QTextCursor::WordRight; - } - else if (e == QKeySequence::MoveToPreviousWord) { - op = QTextCursor::WordLeft; - } - else if (e == QKeySequence::MoveToEndOfBlock) { - op = QTextCursor::EndOfBlock; - } - else if (e == QKeySequence::MoveToStartOfBlock) { - op = QTextCursor::StartOfBlock; - } - else if (e == QKeySequence::MoveToNextLine) { - op = QTextCursor::Down; - } - else if (e == QKeySequence::MoveToPreviousLine) { - op = QTextCursor::Up; - } - else if (e == QKeySequence::MoveToPreviousLine) { - op = QTextCursor::Up; - } - else if (e == QKeySequence::MoveToStartOfLine) { - op = QTextCursor::StartOfLine; - } - else if (e == QKeySequence::MoveToEndOfLine) { - op = QTextCursor::EndOfLine; - } - else if (e == QKeySequence::MoveToStartOfDocument) { - op = QTextCursor::Start; - } - else if (e == QKeySequence::MoveToEndOfDocument) { - op = QTextCursor::End; - } -#endif // QT_NO_SHORTCUT - else { - return false; - } - -// Except for pageup and pagedown, Mac OS X has very different behavior, we don't do it all, but -// here's the breakdown: -// Shift still works as an anchor, but only one of the other keys can be down Ctrl (Command), -// Alt (Option), or Meta (Control). -// Command/Control + Left/Right -- Move to left or right of the line -// + Up/Down -- Move to top bottom of the file. (Control doesn't move the cursor) -// Option + Left/Right -- Move one word Left/right. -// + Up/Down -- Begin/End of Paragraph. -// Home/End Top/Bottom of file. (usually don't move the cursor, but will select) - - bool visualNavigation = cursor.visualNavigation(); - cursor.setVisualNavigation(true); - const bool moved = cursor.movePosition(op, mode); - cursor.setVisualNavigation(visualNavigation); - q->ensureCursorVisible(); - - bool ignoreNavigationEvents = ignoreUnusedNavigationEvents; - bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down; - -#ifdef QT_KEYPAD_NAVIGATION - ignoreNavigationEvents = ignoreNavigationEvents || QApplication::keypadNavigationEnabled(); - isNavigationEvent = isNavigationEvent || - (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional - && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)); -#else - isNavigationEvent = isNavigationEvent || e->key() == Qt::Key_Left || e->key() == Qt::Key_Right; -#endif - - if (moved) { - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - emit q->microFocusChanged(); - } else if (ignoreNavigationEvents && isNavigationEvent && oldSelection.anchor() == cursor.anchor()) { - return false; - } - - selectionChanged(/*forceEmitSelectionChanged =*/(mode == QTextCursor::KeepAnchor)); - - repaintOldAndNewSelection(oldSelection); - - return true; -} - -void QTextControlPrivate::updateCurrentCharFormat() -{ - Q_Q(QTextControl); - - QTextCharFormat fmt = cursor.charFormat(); - if (fmt == lastCharFormat) - return; - lastCharFormat = fmt; - - emit q->currentCharFormatChanged(fmt); - emit q->microFocusChanged(); -} - -void QTextControlPrivate::indent() -{ - QTextBlockFormat blockFmt = cursor.blockFormat(); - - QTextList *list = cursor.currentList(); - if (!list) { - QTextBlockFormat modifier; - modifier.setIndent(blockFmt.indent() + 1); - cursor.mergeBlockFormat(modifier); - } else { - QTextListFormat format = list->format(); - format.setIndent(format.indent() + 1); - - if (list->itemNumber(cursor.block()) == 1) - list->setFormat(format); - else - cursor.createList(format); - } -} - -void QTextControlPrivate::outdent() -{ - QTextBlockFormat blockFmt = cursor.blockFormat(); - - QTextList *list = cursor.currentList(); - - if (!list) { - QTextBlockFormat modifier; - modifier.setIndent(blockFmt.indent() - 1); - cursor.mergeBlockFormat(modifier); - } else { - QTextListFormat listFmt = list->format(); - listFmt.setIndent(listFmt.indent() - 1); - list->setFormat(listFmt); - } -} - -void QTextControlPrivate::gotoNextTableCell() -{ - QTextTable *table = cursor.currentTable(); - QTextTableCell cell = table->cellAt(cursor); - - int newColumn = cell.column() + cell.columnSpan(); - int newRow = cell.row(); - - if (newColumn >= table->columns()) { - newColumn = 0; - ++newRow; - if (newRow >= table->rows()) - table->insertRows(table->rows(), 1); - } - - cell = table->cellAt(newRow, newColumn); - cursor = cell.firstCursorPosition(); -} - -void QTextControlPrivate::gotoPreviousTableCell() -{ - QTextTable *table = cursor.currentTable(); - QTextTableCell cell = table->cellAt(cursor); - - int newColumn = cell.column() - 1; - int newRow = cell.row(); - - if (newColumn < 0) { - newColumn = table->columns() - 1; - --newRow; - if (newRow < 0) - return; - } - - cell = table->cellAt(newRow, newColumn); - cursor = cell.firstCursorPosition(); -} - -void QTextControlPrivate::createAutoBulletList() -{ - cursor.beginEditBlock(); - - QTextBlockFormat blockFmt = cursor.blockFormat(); - - QTextListFormat listFmt; - listFmt.setStyle(QTextListFormat::ListDisc); - listFmt.setIndent(blockFmt.indent() + 1); - - blockFmt.setIndent(0); - cursor.setBlockFormat(blockFmt); - - cursor.createList(listFmt); - - cursor.endEditBlock(); -} - -void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QTextDocument *document) -{ - Q_Q(QTextControl); - setContent(format, text, document); - - doc->setUndoRedoEnabled(interactionFlags & Qt::TextEditable); - q->setCursorWidth(-1); -} - -void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text, QTextDocument *document) -{ - Q_Q(QTextControl); - - // for use when called from setPlainText. we may want to re-use the currently - // set char format then. - const QTextCharFormat charFormatForInsertion = cursor.charFormat(); - - bool clearDocument = true; - if (!doc) { - if (document) { - doc = document; - clearDocument = false; - } else { - palette = QApplication::palette("QTextControl"); - doc = new QTextDocument(q); - } - _q_documentLayoutChanged(); - cursor = QTextCursor(doc); - -// #### doc->documentLayout()->setPaintDevice(viewport); - - QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection())); - QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor))); - QObject::connect(doc, SIGNAL(documentLayoutChanged()), q, SLOT(_q_documentLayoutChanged())); - - // convenience signal forwards - QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); - QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); - QObject::connect(doc, SIGNAL(modificationChanged(bool)), q, SIGNAL(modificationChanged(bool))); - QObject::connect(doc, SIGNAL(blockCountChanged(int)), q, SIGNAL(blockCountChanged(int))); - } - - bool previousUndoRedoState = doc->isUndoRedoEnabled(); - if (!document) - doc->setUndoRedoEnabled(false); - - //Saving the index save some time. - static int contentsChangedIndex = QTextDocument::staticMetaObject.indexOfSignal("contentsChanged()"); - static int textChangedIndex = QTextControl::staticMetaObject.indexOfSignal("textChanged()"); - // avoid multiple textChanged() signals being emitted - QMetaObject::disconnect(doc, contentsChangedIndex, q, textChangedIndex); - - if (!text.isEmpty()) { - // clear 'our' cursor for insertion to prevent - // the emission of the cursorPositionChanged() signal. - // instead we emit it only once at the end instead of - // at the end of the document after loading and when - // positioning the cursor again to the start of the - // document. - cursor = QTextCursor(); - if (format == Qt::PlainText) { - QTextCursor formatCursor(doc); - // put the setPlainText and the setCharFormat into one edit block, - // so that the syntax highlight triggers only /once/ for the entire - // document, not twice. - formatCursor.beginEditBlock(); - doc->setPlainText(text); - doc->setUndoRedoEnabled(false); - formatCursor.select(QTextCursor::Document); - formatCursor.setCharFormat(charFormatForInsertion); - formatCursor.endEditBlock(); - } else { -#ifndef QT_NO_TEXTHTMLPARSER - doc->setHtml(text); -#else - doc->setPlainText(text); -#endif - doc->setUndoRedoEnabled(false); - } - cursor = QTextCursor(doc); - } else if (clearDocument) { - doc->clear(); - } - cursor.setCharFormat(charFormatForInsertion); - - QMetaObject::connect(doc, contentsChangedIndex, q, textChangedIndex); - emit q->textChanged(); - if (!document) - doc->setUndoRedoEnabled(previousUndoRedoState); - _q_updateCurrentCharFormatAndSelection(); - if (!document) - doc->setModified(false); - - q->ensureCursorVisible(); - emit q->cursorPositionChanged(); -} - -void QTextControlPrivate::startDrag() -{ -#ifndef QT_NO_DRAGANDDROP - Q_Q(QTextControl); - mousePressed = false; - if (!contextWidget) - return; - QMimeData *data = q->createMimeDataFromSelection(); - - QDrag *drag = new QDrag(contextWidget); - drag->setMimeData(data); - - Qt::DropActions actions = Qt::CopyAction; - Qt::DropAction action; - if (interactionFlags & Qt::TextEditable) { - actions |= Qt::MoveAction; - action = drag->exec(actions, Qt::MoveAction); - } else { - action = drag->exec(actions, Qt::CopyAction); - } - - if (action == Qt::MoveAction && drag->target() != contextWidget) - cursor.removeSelectedText(); -#endif -} - -void QTextControlPrivate::setCursorPosition(const QPointF &pos) -{ - Q_Q(QTextControl); - const int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) - return; - cursor.setPosition(cursorPos); -} - -void QTextControlPrivate::setCursorPosition(int pos, QTextCursor::MoveMode mode) -{ - cursor.setPosition(pos, mode); - - if (mode != QTextCursor::KeepAnchor) { - selectedWordOnDoubleClick = QTextCursor(); - selectedBlockOnTrippleClick = QTextCursor(); - } -} - -void QTextControlPrivate::repaintCursor() -{ - Q_Q(QTextControl); - emit q->updateRequest(cursorRectPlusUnicodeDirectionMarkers(cursor)); -} - -void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelection) -{ - Q_Q(QTextControl); - if (cursor.hasSelection() - && oldSelection.hasSelection() - && cursor.currentFrame() == oldSelection.currentFrame() - && !cursor.hasComplexSelection() - && !oldSelection.hasComplexSelection() - && cursor.anchor() == oldSelection.anchor() - ) { - QTextCursor differenceSelection(doc); - differenceSelection.setPosition(oldSelection.position()); - differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor); - emit q->updateRequest(q->selectionRect(differenceSelection)); - } else { - if (!oldSelection.isNull()) - emit q->updateRequest(q->selectionRect(oldSelection) | cursorRectPlusUnicodeDirectionMarkers(oldSelection)); - emit q->updateRequest(q->selectionRect() | cursorRectPlusUnicodeDirectionMarkers(cursor)); - } -} - -void QTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /*=false*/) -{ - Q_Q(QTextControl); - if (forceEmitSelectionChanged) - emit q->selectionChanged(); - - bool current = cursor.hasSelection(); - if (current == lastSelectionState) - return; - - lastSelectionState = current; - emit q->copyAvailable(current); - if (!forceEmitSelectionChanged) - emit q->selectionChanged(); - emit q->microFocusChanged(); -} - -void QTextControlPrivate::_q_updateCurrentCharFormatAndSelection() -{ - updateCurrentCharFormat(); - selectionChanged(); -} - -#ifndef QT_NO_CLIPBOARD -void QTextControlPrivate::setClipboardSelection() -{ - QClipboard *clipboard = QApplication::clipboard(); - if (!cursor.hasSelection() || !clipboard->supportsSelection()) - return; - Q_Q(QTextControl); - QMimeData *data = q->createMimeDataFromSelection(); - clipboard->setMimeData(data, QClipboard::Selection); -} -#endif - -void QTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someCursor) -{ - Q_Q(QTextControl); - if (someCursor.isCopyOf(cursor)) { - emit q->cursorPositionChanged(); - emit q->microFocusChanged(); - } -} - -void QTextControlPrivate::_q_documentLayoutChanged() -{ - Q_Q(QTextControl); - QAbstractTextDocumentLayout *layout = doc->documentLayout(); - QObject::connect(layout, SIGNAL(update(QRectF)), q, SIGNAL(updateRequest(QRectF))); - QObject::connect(layout, SIGNAL(updateBlock(QTextBlock)), q, SLOT(_q_updateBlock(QTextBlock))); - QObject::connect(layout, SIGNAL(documentSizeChanged(QSizeF)), q, SIGNAL(documentSizeChanged(QSizeF))); - -} - -void QTextControlPrivate::setBlinkingCursorEnabled(bool enable) -{ - Q_Q(QTextControl); - - if (enable && QApplication::cursorFlashTime() > 0) - cursorBlinkTimer.start(QApplication::cursorFlashTime() / 2, q); - else - cursorBlinkTimer.stop(); - - cursorOn = enable; - - repaintCursor(); -} - -void QTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition) -{ - Q_Q(QTextControl); - - // if inside the initial selected word keep that - if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart() - && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) { - q->setTextCursor(selectedWordOnDoubleClick); - return; - } - - QTextCursor curs = selectedWordOnDoubleClick; - curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); - - if (!curs.movePosition(QTextCursor::StartOfWord)) - return; - const int wordStartPos = curs.position(); - - const int blockPos = curs.block().position(); - const QPointF blockCoordinates = q->blockBoundingRect(curs.block()).topLeft(); - - QTextLine line = currentTextLine(curs); - if (!line.isValid()) - return; - - const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); - - if (!curs.movePosition(QTextCursor::EndOfWord)) - return; - const int wordEndPos = curs.position(); - - const QTextLine otherLine = currentTextLine(curs); - if (otherLine.textStart() != line.textStart() - || wordEndPos == wordStartPos) - return; - - const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); - - if (mouseXPosition < wordStartX || mouseXPosition > wordEndX) - return; - - // keep the already selected word even when moving to the left - // (#39164) - if (suggestedNewPosition < selectedWordOnDoubleClick.position()) - cursor.setPosition(selectedWordOnDoubleClick.selectionEnd()); - else - cursor.setPosition(selectedWordOnDoubleClick.selectionStart()); - - const qreal differenceToStart = mouseXPosition - wordStartX; - const qreal differenceToEnd = wordEndX - mouseXPosition; - - if (differenceToStart < differenceToEnd) - setCursorPosition(wordStartPos, QTextCursor::KeepAnchor); - else - setCursorPosition(wordEndPos, QTextCursor::KeepAnchor); - - if (interactionFlags & Qt::TextSelectableByMouse) { -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); -#endif - selectionChanged(true); - } -} - -void QTextControlPrivate::extendBlockwiseSelection(int suggestedNewPosition) -{ - Q_Q(QTextControl); - - // if inside the initial selected line keep that - if (suggestedNewPosition >= selectedBlockOnTrippleClick.selectionStart() - && suggestedNewPosition <= selectedBlockOnTrippleClick.selectionEnd()) { - q->setTextCursor(selectedBlockOnTrippleClick); - return; - } - - if (suggestedNewPosition < selectedBlockOnTrippleClick.position()) { - cursor.setPosition(selectedBlockOnTrippleClick.selectionEnd()); - cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::StartOfBlock, QTextCursor::KeepAnchor); - } else { - cursor.setPosition(selectedBlockOnTrippleClick.selectionStart()); - cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - } - - if (interactionFlags & Qt::TextSelectableByMouse) { -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); -#endif - selectionChanged(true); - } -} - -void QTextControlPrivate::_q_deleteSelected() -{ - if (!(interactionFlags & Qt::TextEditable) || !cursor.hasSelection()) - return; - cursor.removeSelectedText(); -} - -void QTextControl::undo() -{ - Q_D(QTextControl); - d->repaintSelection(); - const int oldCursorPos = d->cursor.position(); - d->doc->undo(&d->cursor); - if (d->cursor.position() != oldCursorPos) - emit cursorPositionChanged(); - emit microFocusChanged(); - ensureCursorVisible(); -} - -void QTextControl::redo() -{ - Q_D(QTextControl); - d->repaintSelection(); - const int oldCursorPos = d->cursor.position(); - d->doc->redo(&d->cursor); - if (d->cursor.position() != oldCursorPos) - emit cursorPositionChanged(); - emit microFocusChanged(); - ensureCursorVisible(); -} - -QTextControl::QTextControl(QObject *parent) - : QObject(*new QTextControlPrivate, parent) -{ - Q_D(QTextControl); - d->init(); -} - -QTextControl::QTextControl(const QString &text, QObject *parent) - : QObject(*new QTextControlPrivate, parent) -{ - Q_D(QTextControl); - d->init(Qt::RichText, text); -} - -QTextControl::QTextControl(QTextDocument *doc, QObject *parent) - : QObject(*new QTextControlPrivate, parent) -{ - Q_D(QTextControl); - d->init(Qt::RichText, QString(), doc); -} - -QTextControl::~QTextControl() -{ -} - -void QTextControl::setDocument(QTextDocument *document) -{ - Q_D(QTextControl); - if (d->doc == document) - return; - - d->doc->disconnect(this); - d->doc->documentLayout()->disconnect(this); - d->doc->documentLayout()->setPaintDevice(0); - - if (d->doc->parent() == this) - delete d->doc; - - d->doc = 0; - d->setContent(Qt::RichText, QString(), document); -} - -QTextDocument *QTextControl::document() const -{ - Q_D(const QTextControl); - return d->doc; -} - -void QTextControl::setTextCursor(const QTextCursor &cursor) -{ - Q_D(QTextControl); - d->cursorIsFocusIndicator = false; - const bool posChanged = cursor.position() != d->cursor.position(); - const QTextCursor oldSelection = d->cursor; - d->cursor = cursor; - d->cursorOn = d->hasFocus && (d->interactionFlags & Qt::TextEditable); - d->_q_updateCurrentCharFormatAndSelection(); - ensureCursorVisible(); - d->repaintOldAndNewSelection(oldSelection); - if (posChanged) - emit cursorPositionChanged(); -} - -QTextCursor QTextControl::textCursor() const -{ - Q_D(const QTextControl); - return d->cursor; -} - -#ifndef QT_NO_CLIPBOARD - -void QTextControl::cut() -{ - Q_D(QTextControl); - if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection()) - return; - copy(); - d->cursor.removeSelectedText(); -} - -void QTextControl::copy() -{ - Q_D(QTextControl); - if (!d->cursor.hasSelection()) - return; - QMimeData *data = createMimeDataFromSelection(); - QApplication::clipboard()->setMimeData(data); -} - -void QTextControl::paste(QClipboard::Mode mode) -{ - const QMimeData *md = QApplication::clipboard()->mimeData(mode); - if (md) - insertFromMimeData(md); -} -#endif - -void QTextControl::clear() -{ - Q_D(QTextControl); - // clears and sets empty content - d->extraSelections.clear(); - d->setContent(); -} - - -void QTextControl::selectAll() -{ - Q_D(QTextControl); - const int selectionLength = qAbs(d->cursor.position() - d->cursor.anchor()); - d->cursor.select(QTextCursor::Document); - d->selectionChanged(selectionLength != qAbs(d->cursor.position() - d->cursor.anchor())); - d->cursorIsFocusIndicator = false; - emit updateRequest(); -} - -void QTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset, QWidget *contextWidget) -{ - QMatrix m; - m.translate(coordinateOffset.x(), coordinateOffset.y()); - processEvent(e, m, contextWidget); -} - -void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget) -{ - Q_D(QTextControl); - if (d->interactionFlags == Qt::NoTextInteraction) { - e->ignore(); - return; - } - - d->contextWidget = contextWidget; - - if (!d->contextWidget) { - switch (e->type()) { -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMouseMove: - case QEvent::GraphicsSceneMousePress: - case QEvent::GraphicsSceneMouseRelease: - case QEvent::GraphicsSceneMouseDoubleClick: - case QEvent::GraphicsSceneContextMenu: - case QEvent::GraphicsSceneHoverEnter: - case QEvent::GraphicsSceneHoverMove: - case QEvent::GraphicsSceneHoverLeave: - case QEvent::GraphicsSceneHelp: - case QEvent::GraphicsSceneDragEnter: - case QEvent::GraphicsSceneDragMove: - case QEvent::GraphicsSceneDragLeave: - case QEvent::GraphicsSceneDrop: { - QGraphicsSceneEvent *ev = static_cast<QGraphicsSceneEvent *>(e); - d->contextWidget = ev->widget(); - break; - } -#endif // QT_NO_GRAPHICSVIEW - default: break; - }; - } - - switch (e->type()) { - case QEvent::KeyPress: - d->keyPressEvent(static_cast<QKeyEvent *>(e)); - break; - case QEvent::MouseButtonPress: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::MouseMove: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::MouseButtonRelease: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::MouseButtonDblClick: { - QMouseEvent *ev = static_cast<QMouseEvent *>(e); - d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), - ev->buttons(), ev->globalPos()); - break; } - case QEvent::InputMethod: - d->inputMethodEvent(static_cast<QInputMethodEvent *>(e)); - break; -#ifndef QT_NO_CONTEXTMENU - case QEvent::ContextMenu: { - QContextMenuEvent *ev = static_cast<QContextMenuEvent *>(e); - d->contextMenuEvent(ev->globalPos(), matrix.map(ev->pos()), contextWidget); - break; } -#endif // QT_NO_CONTEXTMENU - case QEvent::FocusIn: - case QEvent::FocusOut: - d->focusEvent(static_cast<QFocusEvent *>(e)); - break; - - case QEvent::EnabledChange: - d->isEnabled = e->isAccepted(); - break; - -#ifndef QT_NO_TOOLTIP - case QEvent::ToolTip: { - QHelpEvent *ev = static_cast<QHelpEvent *>(e); - d->showToolTip(ev->globalPos(), matrix.map(ev->pos()), contextWidget); - break; - } -#endif // QT_NO_TOOLTIP - -#ifndef QT_NO_DRAGANDDROP - case QEvent::DragEnter: { - QDragEnterEvent *ev = static_cast<QDragEnterEvent *>(e); - if (d->dragEnterEvent(e, ev->mimeData())) - ev->acceptProposedAction(); - break; - } - case QEvent::DragLeave: - d->dragLeaveEvent(); - break; - case QEvent::DragMove: { - QDragMoveEvent *ev = static_cast<QDragMoveEvent *>(e); - if (d->dragMoveEvent(e, ev->mimeData(), matrix.map(ev->pos()))) - ev->acceptProposedAction(); - break; - } - case QEvent::Drop: { - QDropEvent *ev = static_cast<QDropEvent *>(e); - if (d->dropEvent(ev->mimeData(), matrix.map(ev->pos()), ev->dropAction(), ev->source())) - ev->acceptProposedAction(); - break; - } -#endif - -#ifndef QT_NO_GRAPHICSVIEW - case QEvent::GraphicsSceneMousePress: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mousePressEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneMouseMove: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseMoveEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneMouseRelease: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseReleaseEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneMouseDoubleClick: { - QGraphicsSceneMouseEvent *ev = static_cast<QGraphicsSceneMouseEvent *>(e); - d->mouseDoubleClickEvent(ev, ev->button(), matrix.map(ev->pos()), ev->modifiers(), ev->buttons(), - ev->screenPos()); - break; } - case QEvent::GraphicsSceneContextMenu: { - QGraphicsSceneContextMenuEvent *ev = static_cast<QGraphicsSceneContextMenuEvent *>(e); - d->contextMenuEvent(ev->screenPos(), matrix.map(ev->pos()), contextWidget); - break; } - - case QEvent::GraphicsSceneHoverMove: { - QGraphicsSceneHoverEvent *ev = static_cast<QGraphicsSceneHoverEvent *>(e); - d->mouseMoveEvent(ev, Qt::NoButton, matrix.map(ev->pos()), ev->modifiers(),Qt::NoButton, - ev->screenPos()); - break; } - - case QEvent::GraphicsSceneDragEnter: { - QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e); - if (d->dragEnterEvent(e, ev->mimeData())) - ev->acceptProposedAction(); - break; } - case QEvent::GraphicsSceneDragLeave: - d->dragLeaveEvent(); - break; - case QEvent::GraphicsSceneDragMove: { - QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e); - if (d->dragMoveEvent(e, ev->mimeData(), matrix.map(ev->pos()))) - ev->acceptProposedAction(); - break; } - case QEvent::GraphicsSceneDrop: { - QGraphicsSceneDragDropEvent *ev = static_cast<QGraphicsSceneDragDropEvent *>(e); - if (d->dropEvent(ev->mimeData(), matrix.map(ev->pos()), ev->dropAction(), ev->source())) - ev->accept(); - break; } -#endif // QT_NO_GRAPHICSVIEW -#ifdef QT_KEYPAD_NAVIGATION - case QEvent::EnterEditFocus: - case QEvent::LeaveEditFocus: - if (QApplication::keypadNavigationEnabled()) - d->editFocusEvent(e); - break; -#endif - case QEvent::ShortcutOverride: - if (d->interactionFlags & Qt::TextEditable) { - QKeyEvent* ke = static_cast<QKeyEvent *>(e); - if (ke->modifiers() == Qt::NoModifier - || ke->modifiers() == Qt::ShiftModifier - || ke->modifiers() == Qt::KeypadModifier) { - if (ke->key() < Qt::Key_Escape) { - ke->accept(); - } else { - switch (ke->key()) { - case Qt::Key_Return: - case Qt::Key_Enter: - case Qt::Key_Delete: - case Qt::Key_Home: - case Qt::Key_End: - case Qt::Key_Backspace: - case Qt::Key_Left: - case Qt::Key_Right: - case Qt::Key_Up: - case Qt::Key_Down: - case Qt::Key_Tab: - ke->accept(); - default: - break; - } - } -#ifndef QT_NO_SHORTCUT - } else if (ke == QKeySequence::Copy - || ke == QKeySequence::Paste - || ke == QKeySequence::Cut - || ke == QKeySequence::Redo - || ke == QKeySequence::Undo - || ke == QKeySequence::MoveToNextWord - || ke == QKeySequence::MoveToPreviousWord - || ke == QKeySequence::MoveToStartOfDocument - || ke == QKeySequence::MoveToEndOfDocument - || ke == QKeySequence::SelectNextWord - || ke == QKeySequence::SelectPreviousWord - || ke == QKeySequence::SelectStartOfLine - || ke == QKeySequence::SelectEndOfLine - || ke == QKeySequence::SelectStartOfBlock - || ke == QKeySequence::SelectEndOfBlock - || ke == QKeySequence::SelectStartOfDocument - || ke == QKeySequence::SelectEndOfDocument - || ke == QKeySequence::SelectAll - ) { - ke->accept(); -#endif - } - } - break; - default: - break; - } -} - -bool QTextControl::event(QEvent *e) -{ - return QObject::event(e); -} - -void QTextControl::timerEvent(QTimerEvent *e) -{ - Q_D(QTextControl); - if (e->timerId() == d->cursorBlinkTimer.timerId()) { - d->cursorOn = !d->cursorOn; - - if (d->cursor.hasSelection()) - d->cursorOn &= (QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected) - != 0); - - d->repaintCursor(); - } else if (e->timerId() == d->trippleClickTimer.timerId()) { - d->trippleClickTimer.stop(); - } -} - -void QTextControl::setPlainText(const QString &text) -{ - Q_D(QTextControl); - d->setContent(Qt::PlainText, text); -} - -void QTextControl::setHtml(const QString &text) -{ - Q_D(QTextControl); - d->setContent(Qt::RichText, text); -} - -void QTextControlPrivate::keyPressEvent(QKeyEvent *e) -{ - Q_Q(QTextControl); -#ifndef QT_NO_SHORTCUT - if (e == QKeySequence::SelectAll) { - e->accept(); - q->selectAll(); - return; - } -#ifndef QT_NO_CLIPBOARD - else if (e == QKeySequence::Copy) { - e->accept(); - q->copy(); - return; - } -#endif -#endif // QT_NO_SHORTCUT - - if (interactionFlags & Qt::TextSelectableByKeyboard - && cursorMoveKeyEvent(e)) - goto accept; - - if (interactionFlags & Qt::LinksAccessibleByKeyboard) { - if ((e->key() == Qt::Key_Return - || e->key() == Qt::Key_Enter -#ifdef QT_KEYPAD_NAVIGATION - || e->key() == Qt::Key_Select -#endif - ) - && cursor.hasSelection()) { - - e->accept(); - activateLinkUnderCursor(); - return; - } - } - - if (!(interactionFlags & Qt::TextEditable)) { - e->ignore(); - return; - } - - if (e->key() == Qt::Key_Direction_L || e->key() == Qt::Key_Direction_R) { - QTextBlockFormat fmt; - fmt.setLayoutDirection((e->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); - cursor.mergeBlockFormat(fmt); - goto accept; - } - - // schedule a repaint of the region of the cursor, as when we move it we - // want to make sure the old cursor disappears (not noticeable when moving - // only a few pixels but noticeable when jumping between cells in tables for - // example) - repaintSelection(); - - if (e->key() == Qt::Key_Backspace && !(e->modifiers() & ~Qt::ShiftModifier)) { - QTextBlockFormat blockFmt = cursor.blockFormat(); - QTextList *list = cursor.currentList(); - if (list && cursor.atBlockStart() && !cursor.hasSelection()) { - list->remove(cursor.block()); - } else if (cursor.atBlockStart() && blockFmt.indent() > 0) { - blockFmt.setIndent(blockFmt.indent() - 1); - cursor.setBlockFormat(blockFmt); - } else { - QTextCursor localCursor = cursor; - localCursor.deletePreviousChar(); - } - goto accept; - } -#ifndef QT_NO_SHORTCUT - else if (e == QKeySequence::InsertParagraphSeparator) { - cursor.insertBlock(); - e->accept(); - goto accept; - } else if (e == QKeySequence::InsertLineSeparator) { - cursor.insertText(QString(QChar::LineSeparator)); - e->accept(); - goto accept; - } -#endif - if (false) { - } -#ifndef QT_NO_SHORTCUT - else if (e == QKeySequence::Undo) { - q->undo(); - } - else if (e == QKeySequence::Redo) { - q->redo(); - } -#ifndef QT_NO_CLIPBOARD - else if (e == QKeySequence::Cut) { - q->cut(); - } - else if (e == QKeySequence::Paste) { - QClipboard::Mode mode = QClipboard::Clipboard; -#ifdef Q_WS_X11 - if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert) - mode = QClipboard::Selection; -#endif - q->paste(mode); - } -#endif - else if (e == QKeySequence::Delete) { - QTextCursor localCursor = cursor; - localCursor.deleteChar(); - } - else if (e == QKeySequence::DeleteEndOfWord) { - if (!cursor.hasSelection()) - cursor.movePosition(QTextCursor::NextWord, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - } - else if (e == QKeySequence::DeleteStartOfWord) { - if (!cursor.hasSelection()) - cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - } - else if (e == QKeySequence::DeleteEndOfLine) { - QTextBlock block = cursor.block(); - if (cursor.position() == block.position() + block.length() - 2) - cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor); - else - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.removeSelectedText(); - } -#endif // QT_NO_SHORTCUT - else { - goto process; - } - goto accept; - -process: - { - QString text = e->text(); - if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) { - if (overwriteMode - // no need to call deleteChar() if we have a selection, insertText - // does it already - && !cursor.hasSelection() - && !cursor.atBlockEnd()) - cursor.deleteChar(); - - cursor.insertText(text); - selectionChanged(); - } else { - e->ignore(); - return; - } - } - - accept: - - e->accept(); - cursorOn = true; - - q->ensureCursorVisible(); - - updateCurrentCharFormat(); -} - -QVariant QTextControl::loadResource(int type, const QUrl &name) -{ -#ifdef QT_NO_TEXTEDIT - Q_UNUSED(type); - Q_UNUSED(name); -#else - if (QTextEdit *textEdit = qobject_cast<QTextEdit *>(parent())) { - QUrl resolvedName = textEdit->d_func()->resolveUrl(name); - return textEdit->loadResource(type, resolvedName); - } -#endif - return QVariant(); -} - -void QTextControlPrivate::_q_updateBlock(const QTextBlock &block) -{ - Q_Q(QTextControl); - QRectF br = q->blockBoundingRect(block); - br.setRight(qreal(INT_MAX)); // the block might have shrunk - emit q->updateRequest(br); -} - -QRectF QTextControlPrivate::rectForPosition(int position) const -{ - Q_Q(const QTextControl); - const QTextBlock block = doc->findBlock(position); - if (!block.isValid()) - return QRectF(); - const QAbstractTextDocumentLayout *docLayout = doc->documentLayout(); - const QTextLayout *layout = block.layout(); - const QPointF layoutPos = q->blockBoundingRect(block).topLeft(); - int relativePos = position - block.position(); - if (preeditCursor != 0) { - int preeditPos = layout->preeditAreaPosition(); - if (relativePos == preeditPos) - relativePos += preeditCursor; - else if (relativePos > preeditPos) - relativePos += layout->preeditAreaText().length(); - } - QTextLine line = layout->lineForTextPosition(relativePos); - - int cursorWidth; - { - bool ok = false; -#ifndef QT_NO_PROPERTIES - cursorWidth = docLayout->property("cursorWidth").toInt(&ok); -#endif - if (!ok) - cursorWidth = 1; - } - - QRectF r; - - if (line.isValid()) { - qreal x = line.cursorToX(relativePos); - qreal w = 0; - if (overwriteMode) { - if (relativePos < line.textLength() - line.textStart()) - w = line.cursorToX(relativePos + 1) - x; - else - w = QFontMetrics(block.layout()->font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw() - } - r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), - cursorWidth + w, line.height()); - } else { - r = QRectF(layoutPos.x(), layoutPos.y(), cursorWidth, 10); // #### correct height - } - - return r; -} - -static inline bool firstFramePosLessThanCursorPos(QTextFrame *frame, int position) -{ - return frame->firstPosition() < position; -} - -static inline bool cursorPosLessThanLastFramePos(int position, QTextFrame *frame) -{ - return position < frame->lastPosition(); -} - -static QRectF boundingRectOfFloatsInSelection(const QTextCursor &cursor) -{ - QRectF r; - QTextFrame *frame = cursor.currentFrame(); - const QList<QTextFrame *> children = frame->childFrames(); - - const QList<QTextFrame *>::ConstIterator firstFrame = qLowerBound(children.constBegin(), children.constEnd(), - cursor.selectionStart(), firstFramePosLessThanCursorPos); - const QList<QTextFrame *>::ConstIterator lastFrame = qUpperBound(children.constBegin(), children.constEnd(), - cursor.selectionEnd(), cursorPosLessThanLastFramePos); - for (QList<QTextFrame *>::ConstIterator it = firstFrame; it != lastFrame; ++it) { - if ((*it)->frameFormat().position() != QTextFrameFormat::InFlow) - r |= frame->document()->documentLayout()->frameBoundingRect(*it); - } - return r; -} - -QRectF QTextControl::selectionRect(const QTextCursor &cursor) const -{ - Q_D(const QTextControl); - - QRectF r = d->rectForPosition(cursor.selectionStart()); - - if (cursor.hasComplexSelection() && cursor.currentTable()) { - QTextTable *table = cursor.currentTable(); - - r = d->doc->documentLayout()->frameBoundingRect(table); - /* - int firstRow, numRows, firstColumn, numColumns; - cursor.selectedTableCells(&firstRow, &numRows, &firstColumn, &numColumns); - - const QTextTableCell firstCell = table->cellAt(firstRow, firstColumn); - const QTextTableCell lastCell = table->cellAt(firstRow + numRows - 1, firstColumn + numColumns - 1); - - const QAbstractTextDocumentLayout * const layout = doc->documentLayout(); - - QRectF tableSelRect = layout->blockBoundingRect(firstCell.firstCursorPosition().block()); - - for (int col = firstColumn; col < firstColumn + numColumns; ++col) { - const QTextTableCell cell = table->cellAt(firstRow, col); - const qreal y = layout->blockBoundingRect(cell.firstCursorPosition().block()).top(); - - tableSelRect.setTop(qMin(tableSelRect.top(), y)); - } - - for (int row = firstRow; row < firstRow + numRows; ++row) { - const QTextTableCell cell = table->cellAt(row, firstColumn); - const qreal x = layout->blockBoundingRect(cell.firstCursorPosition().block()).left(); - - tableSelRect.setLeft(qMin(tableSelRect.left(), x)); - } - - for (int col = firstColumn; col < firstColumn + numColumns; ++col) { - const QTextTableCell cell = table->cellAt(firstRow + numRows - 1, col); - const qreal y = layout->blockBoundingRect(cell.lastCursorPosition().block()).bottom(); - - tableSelRect.setBottom(qMax(tableSelRect.bottom(), y)); - } - - for (int row = firstRow; row < firstRow + numRows; ++row) { - const QTextTableCell cell = table->cellAt(row, firstColumn + numColumns - 1); - const qreal x = layout->blockBoundingRect(cell.lastCursorPosition().block()).right(); - - tableSelRect.setRight(qMax(tableSelRect.right(), x)); - } - - r = tableSelRect.toRect(); - */ - } else if (cursor.hasSelection()) { - const int position = cursor.selectionStart(); - const int anchor = cursor.selectionEnd(); - const QTextBlock posBlock = d->doc->findBlock(position); - const QTextBlock anchorBlock = d->doc->findBlock(anchor); - if (posBlock == anchorBlock && posBlock.isValid() && posBlock.layout()->lineCount()) { - const QTextLine posLine = posBlock.layout()->lineForTextPosition(position - posBlock.position()); - const QTextLine anchorLine = anchorBlock.layout()->lineForTextPosition(anchor - anchorBlock.position()); - - const int firstLine = qMin(posLine.lineNumber(), anchorLine.lineNumber()); - const int lastLine = qMax(posLine.lineNumber(), anchorLine.lineNumber()); - const QTextLayout *layout = posBlock.layout(); - r = QRectF(); - for (int i = firstLine; i <= lastLine; ++i) { - r |= layout->lineAt(i).rect(); - r |= layout->lineAt(i).naturalTextRect(); // might be bigger in the case of wrap not enabled - } - r.translate(blockBoundingRect(posBlock).topLeft()); - } else { - QRectF anchorRect = d->rectForPosition(cursor.selectionEnd()); - r |= anchorRect; - r |= boundingRectOfFloatsInSelection(cursor); - QRectF frameRect(d->doc->documentLayout()->frameBoundingRect(cursor.currentFrame())); - r.setLeft(frameRect.left()); - r.setRight(frameRect.right()); - } - if (r.isValid()) - r.adjust(-1, -1, 1, 1); - } - - return r; -} - -QRectF QTextControl::selectionRect() const -{ - Q_D(const QTextControl); - return selectionRect(d->cursor); -} - -void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseButtonPress, button, pos, modifiers, buttons, globalPos)) { - return; - } - - if (interactionFlags & Qt::LinksAccessibleByMouse) { - anchorOnMousePress = q->anchorAt(pos); - - if (cursorIsFocusIndicator) { - cursorIsFocusIndicator = false; - repaintSelection(); - cursor.clearSelection(); - } - } - if (!(button & Qt::LeftButton) || - !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) { - e->ignore(); - return; - } - - cursorIsFocusIndicator = false; - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - - mousePressed = (interactionFlags & Qt::TextSelectableByMouse); -#ifndef QT_NO_DRAGANDDROP - mightStartDrag = false; -#endif - - if (trippleClickTimer.isActive() - && ((pos - trippleClickPoint).toPoint().manhattanLength() < QApplication::startDragDistance())) { - - cursor.movePosition(QTextCursor::StartOfBlock); - cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); - cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - selectedBlockOnTrippleClick = cursor; - - anchorOnMousePress = QString(); - - trippleClickTimer.stop(); - } else { - int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) { - e->ignore(); - return; - } - - if (modifiers == Qt::ShiftModifier && (interactionFlags & Qt::TextSelectableByMouse)) { - if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { - selectedWordOnDoubleClick = cursor; - selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); - } - - if (selectedBlockOnTrippleClick.hasSelection()) - extendBlockwiseSelection(cursorPos); - else if (selectedWordOnDoubleClick.hasSelection()) - extendWordwiseSelection(cursorPos, pos.x()); - else if (!wordSelectionEnabled) - setCursorPosition(cursorPos, QTextCursor::KeepAnchor); - } else { - - if (dragEnabled - && cursor.hasSelection() - && !cursorIsFocusIndicator - && cursorPos >= cursor.selectionStart() - && cursorPos <= cursor.selectionEnd() - && q->hitTest(pos, Qt::ExactHit) != -1) { -#ifndef QT_NO_DRAGANDDROP - mightStartDrag = true; - dragStartPos = pos.toPoint(); -#endif - return; - } - - setCursorPosition(cursorPos); - } - } - - if (interactionFlags & Qt::TextEditable) { - q->ensureCursorVisible(); - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - _q_updateCurrentCharFormatAndSelection(); - } else { - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - selectionChanged(); - } - repaintOldAndNewSelection(oldSelection); - hadSelectionOnMousePress = cursor.hasSelection(); -} - -void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &mousePos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseMove, button, mousePos, modifiers, buttons, globalPos)) { - return; - } - - if (interactionFlags & Qt::LinksAccessibleByMouse) { - QString anchor = q->anchorAt(mousePos); - if (anchor != highlightedAnchor) { - highlightedAnchor = anchor; - emit q->linkHovered(anchor); - } - } - - if (!(buttons & Qt::LeftButton)) - return; - - const bool editable = interactionFlags & Qt::TextEditable; - - if (!(mousePressed - || editable - || mightStartDrag - || selectedWordOnDoubleClick.hasSelection() - || selectedBlockOnTrippleClick.hasSelection())) - return; - - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - - if (mightStartDrag) { - if ((mousePos.toPoint() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) - startDrag(); - return; - } - - if (!mousePressed) - return; - - const qreal mouseX = qreal(mousePos.x()); - - int newCursorPos = q->hitTest(mousePos, Qt::FuzzyHit); - if (newCursorPos == -1) - return; - - if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { - selectedWordOnDoubleClick = cursor; - selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); - } - - if (selectedBlockOnTrippleClick.hasSelection()) - extendBlockwiseSelection(newCursorPos); - else if (selectedWordOnDoubleClick.hasSelection()) - extendWordwiseSelection(newCursorPos, mouseX); - else - setCursorPosition(newCursorPos, QTextCursor::KeepAnchor); - - if (interactionFlags & Qt::TextEditable) { - // don't call ensureVisible for the visible cursor to avoid jumping - // scrollbars. the autoscrolling ensures smooth scrolling if necessary. - //q->ensureCursorVisible(); - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - _q_updateCurrentCharFormatAndSelection(); -#ifndef QT_NO_IM - if (contextWidget) { - if (QInputContext *ic = inputContext()) { - ic->update(); - } - } -#endif //QT_NO_IM - } else { - //emit q->visibilityRequest(QRectF(mousePos, QSizeF(1, 1))); - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - } - selectionChanged(true); - repaintOldAndNewSelection(oldSelection); -} - -void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) { - return; - } - - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - -#ifndef QT_NO_DRAGANDDROP - if (mightStartDrag && (button & Qt::LeftButton)) { - mousePressed = false; - setCursorPosition(pos); - cursor.clearSelection(); - selectionChanged(); - } -#endif - if (mousePressed) { - mousePressed = false; -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); - selectionChanged(true); - } else if (button == Qt::MidButton - && (interactionFlags & Qt::TextEditable) - && QApplication::clipboard()->supportsSelection()) { - setCursorPosition(pos); - const QMimeData *md = QApplication::clipboard()->mimeData(QClipboard::Selection); - if (md) - q->insertFromMimeData(md); -#endif - } - - repaintOldAndNewSelection(oldSelection); - - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - - if (interactionFlags & Qt::LinksAccessibleByMouse) { - if (!(button & Qt::LeftButton)) - return; - - const QString anchor = q->anchorAt(pos); - - if (anchor.isEmpty()) - return; - - if (!cursor.hasSelection() - || (anchor == anchorOnMousePress && hadSelectionOnMousePress)) { - - const int anchorPos = q->hitTest(pos, Qt::ExactHit); - if (anchorPos != -1) { - cursor.setPosition(anchorPos); - - QString anchor = anchorOnMousePress; - anchorOnMousePress = QString(); - activateLinkUnderCursor(anchor); - } - } - } -} - -void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, const QPoint &globalPos) -{ - Q_Q(QTextControl); - - if (sendMouseEventToInputContext( - e, QEvent::MouseButtonDblClick, button, pos, modifiers, buttons, globalPos)) { - return; - } - - if (button != Qt::LeftButton - || !(interactionFlags & Qt::TextSelectableByMouse)) { - e->ignore(); - return; - } - -#ifndef QT_NO_DRAGANDDROP - mightStartDrag = false; -#endif - const QTextCursor oldSelection = cursor; - setCursorPosition(pos); - QTextLine line = currentTextLine(cursor); - bool doEmit = false; - if (line.isValid() && line.textLength()) { - cursor.select(QTextCursor::WordUnderCursor); - doEmit = true; - } - repaintOldAndNewSelection(oldSelection); - - cursorIsFocusIndicator = false; - selectedWordOnDoubleClick = cursor; - - trippleClickPoint = pos; - trippleClickTimer.start(QApplication::doubleClickInterval(), q); - if (doEmit) { - selectionChanged(); -#ifndef QT_NO_CLIPBOARD - setClipboardSelection(); -#endif - emit q->cursorPositionChanged(); - } -} - -bool QTextControlPrivate::sendMouseEventToInputContext( - QEvent *e, QEvent::Type eventType, Qt::MouseButton button, const QPointF &pos, - Qt::KeyboardModifiers modifiers, Qt::MouseButtons buttons, const QPoint &globalPos) -{ -#if !defined(QT_NO_IM) - Q_Q(QTextControl); - - QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { - QInputContext *ctx = inputContext(); - int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); - - if (cursorPos < 0 || cursorPos > layout->preeditAreaText().length()) { - cursorPos = -1; - // don't send move events outside the preedit area - if (eventType == QEvent::MouseMove) - return true; - } - if (ctx) { - QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, - button, buttons, modifiers); - ctx->mouseHandler(cursorPos, &ev); - e->setAccepted(ev.isAccepted()); - } - if (!layout->preeditAreaText().isEmpty()) - return true; - } -#else - Q_UNUSED(e); - Q_UNUSED(eventType); - Q_UNUSED(button); - Q_UNUSED(pos); - Q_UNUSED(modifiers); - Q_UNUSED(buttons); - Q_UNUSED(globalPos); -#endif - return false; -} - -void QTextControlPrivate::contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget) -{ -#ifdef QT_NO_CONTEXTMENU - Q_UNUSED(screenPos); - Q_UNUSED(docPos); - Q_UNUSED(contextWidget); -#else - Q_Q(QTextControl); - if (!hasFocus) - return; - QMenu *menu = q->createStandardContextMenu(docPos, contextWidget); - if (!menu) - return; - menu->setAttribute(Qt::WA_DeleteOnClose); - menu->popup(screenPos); -#endif -} - -bool QTextControlPrivate::dragEnterEvent(QEvent *e, const QMimeData *mimeData) -{ - Q_Q(QTextControl); - if (!(interactionFlags & Qt::TextEditable) || !q->canInsertFromMimeData(mimeData)) { - e->ignore(); - return false; - } - - dndFeedbackCursor = QTextCursor(); - - return true; // accept proposed action -} - -void QTextControlPrivate::dragLeaveEvent() -{ - Q_Q(QTextControl); - - const QRectF crect = q->cursorRect(dndFeedbackCursor); - dndFeedbackCursor = QTextCursor(); - - if (crect.isValid()) - emit q->updateRequest(crect); -} - -bool QTextControlPrivate::dragMoveEvent(QEvent *e, const QMimeData *mimeData, const QPointF &pos) -{ - Q_Q(QTextControl); - if (!(interactionFlags & Qt::TextEditable) || !q->canInsertFromMimeData(mimeData)) { - e->ignore(); - return false; - } - - const int cursorPos = q->hitTest(pos, Qt::FuzzyHit); - if (cursorPos != -1) { - QRectF crect = q->cursorRect(dndFeedbackCursor); - if (crect.isValid()) - emit q->updateRequest(crect); - - dndFeedbackCursor = cursor; - dndFeedbackCursor.setPosition(cursorPos); - - crect = q->cursorRect(dndFeedbackCursor); - emit q->updateRequest(crect); - } - - return true; // accept proposed action -} - -bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &pos, Qt::DropAction dropAction, QWidget *source) -{ - Q_Q(QTextControl); - dndFeedbackCursor = QTextCursor(); - - if (!(interactionFlags & Qt::TextEditable) || !q->canInsertFromMimeData(mimeData)) - return false; - - repaintSelection(); - - QTextCursor insertionCursor = q->cursorForPosition(pos); - insertionCursor.beginEditBlock(); - - if (dropAction == Qt::MoveAction && source == contextWidget) - cursor.removeSelectedText(); - - cursor = insertionCursor; - q->insertFromMimeData(mimeData); - insertionCursor.endEditBlock(); - q->ensureCursorVisible(); - return true; // accept proposed action -} - -void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) -{ - Q_Q(QTextControl); - if (!(interactionFlags & Qt::TextEditable) || cursor.isNull()) { - e->ignore(); - return; - } - bool isGettingInput = !e->commitString().isEmpty() - || e->preeditString() != cursor.block().layout()->preeditAreaText() - || e->replacementLength() > 0; - - cursor.beginEditBlock(); - if (isGettingInput) { - cursor.removeSelectedText(); - } - - // insert commit string - if (!e->commitString().isEmpty() || e->replacementLength()) { - QTextCursor c = cursor; - c.setPosition(c.position() + e->replacementStart()); - c.setPosition(c.position() + e->replacementLength(), QTextCursor::KeepAnchor); - c.insertText(e->commitString()); - } - - for (int i = 0; i < e->attributes().size(); ++i) { - const QInputMethodEvent::Attribute &a = e->attributes().at(i); - if (a.type == QInputMethodEvent::Selection) { - QTextCursor oldCursor = cursor; - int blockStart = a.start + cursor.block().position(); - cursor.setPosition(blockStart, QTextCursor::MoveAnchor); - cursor.setPosition(blockStart + a.length, QTextCursor::KeepAnchor); - q->ensureCursorVisible(); - repaintOldAndNewSelection(oldCursor); - } - } - - QTextBlock block = cursor.block(); - QTextLayout *layout = block.layout(); - if (isGettingInput) - layout->setPreeditArea(cursor.position() - block.position(), e->preeditString()); - QList<QTextLayout::FormatRange> overrides; - const int oldPreeditCursor = preeditCursor; - preeditCursor = e->preeditString().length(); - hideCursor = false; - for (int i = 0; i < e->attributes().size(); ++i) { - const QInputMethodEvent::Attribute &a = e->attributes().at(i); - if (a.type == QInputMethodEvent::Cursor) { - preeditCursor = a.start; - hideCursor = !a.length; - } else if (a.type == QInputMethodEvent::TextFormat) { - QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat(); - if (f.isValid()) { - QTextLayout::FormatRange o; - o.start = a.start + cursor.position() - block.position(); - o.length = a.length; - o.format = f; - overrides.append(o); - } - } - } - layout->setAdditionalFormats(overrides); - cursor.endEditBlock(); - if (cursor.d) - cursor.d->setX(); - if (oldPreeditCursor != preeditCursor) - emit q->microFocusChanged(); -} - -QVariant QTextControl::inputMethodQuery(Qt::InputMethodQuery property) const -{ - Q_D(const QTextControl); - QTextBlock block = d->cursor.block(); - switch(property) { - case Qt::ImMicroFocus: - return cursorRect(); - case Qt::ImFont: - return QVariant(d->cursor.charFormat().font()); - case Qt::ImCursorPosition: - return QVariant(d->cursor.position() - block.position()); - case Qt::ImSurroundingText: - return QVariant(block.text()); - case Qt::ImCurrentSelection: - return QVariant(d->cursor.selectedText()); - case Qt::ImMaximumTextLength: - return QVariant(); // No limit. - case Qt::ImAnchorPosition: - return QVariant(qBound(0, d->cursor.anchor() - block.position(), block.length())); - default: - return QVariant(); - } -} - -void QTextControl::setFocus(bool focus, Qt::FocusReason reason) -{ - QFocusEvent ev(focus ? QEvent::FocusIn : QEvent::FocusOut, - reason); - processEvent(&ev); -} - -void QTextControlPrivate::focusEvent(QFocusEvent *e) -{ - Q_Q(QTextControl); - emit q->updateRequest(q->selectionRect()); - if (e->gotFocus()) { -#ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason -#ifdef Q_OS_SYMBIAN - || e->reason() == Qt::ActiveWindowFocusReason -#endif - ))) { -#endif - cursorOn = (interactionFlags & Qt::TextSelectableByKeyboard); - if (interactionFlags & Qt::TextEditable) { - setBlinkingCursorEnabled(true); - } -#ifdef QT_KEYPAD_NAVIGATION - } -#endif - } else { - setBlinkingCursorEnabled(false); - - if (cursorIsFocusIndicator - && e->reason() != Qt::ActiveWindowFocusReason - && e->reason() != Qt::PopupFocusReason - && cursor.hasSelection()) { - cursor.clearSelection(); - } - } - hasFocus = e->gotFocus(); -} - -QString QTextControlPrivate::anchorForCursor(const QTextCursor &anchorCursor) const -{ - if (anchorCursor.hasSelection()) { - QTextCursor cursor = anchorCursor; - if (cursor.selectionStart() != cursor.position()) - cursor.setPosition(cursor.selectionStart()); - cursor.movePosition(QTextCursor::NextCharacter); - QTextCharFormat fmt = cursor.charFormat(); - if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) - return fmt.stringProperty(QTextFormat::AnchorHref); - } - return QString(); -} - -#ifdef QT_KEYPAD_NAVIGATION -void QTextControlPrivate::editFocusEvent(QEvent *e) -{ - Q_Q(QTextControl); - - if (QApplication::keypadNavigationEnabled()) { - if (e->type() == QEvent::EnterEditFocus && interactionFlags & Qt::TextEditable) { - const QTextCursor oldSelection = cursor; - const int oldCursorPos = cursor.position(); - const bool moved = cursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); - q->ensureCursorVisible(); - if (moved) { - if (cursor.position() != oldCursorPos) - emit q->cursorPositionChanged(); - emit q->microFocusChanged(); - } - selectionChanged(); - repaintOldAndNewSelection(oldSelection); - - setBlinkingCursorEnabled(true); - } else - setBlinkingCursorEnabled(false); - } - - hasEditFocus = e->type() == QEvent::EnterEditFocus ? true : false; -} -#endif - -#ifndef QT_NO_CONTEXTMENU -QMenu *QTextControl::createStandardContextMenu(const QPointF &pos, QWidget *parent) -{ - Q_D(QTextControl); - - const bool showTextSelectionActions = d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse); - - d->linkToCopy = QString(); - if (!pos.isNull()) - d->linkToCopy = anchorAt(pos); - - if (d->linkToCopy.isEmpty() && !showTextSelectionActions) - return 0; - - QMenu *menu = new QMenu(parent); - QAction *a; - - if (d->interactionFlags & Qt::TextEditable) { - a = menu->addAction(tr("&Undo") + ACCEL_KEY(QKeySequence::Undo), this, SLOT(undo())); - a->setEnabled(d->doc->isUndoAvailable()); - a = menu->addAction(tr("&Redo") + ACCEL_KEY(QKeySequence::Redo), this, SLOT(redo())); - a->setEnabled(d->doc->isRedoAvailable()); - menu->addSeparator(); - - a = menu->addAction(tr("Cu&t") + ACCEL_KEY(QKeySequence::Cut), this, SLOT(cut())); - a->setEnabled(d->cursor.hasSelection()); - } - - if (showTextSelectionActions) { - a = menu->addAction(tr("&Copy") + ACCEL_KEY(QKeySequence::Copy), this, SLOT(copy())); - a->setEnabled(d->cursor.hasSelection()); - } - - if ((d->interactionFlags & Qt::LinksAccessibleByKeyboard) - || (d->interactionFlags & Qt::LinksAccessibleByMouse)) { - - a = menu->addAction(tr("Copy &Link Location"), this, SLOT(_q_copyLink())); - a->setEnabled(!d->linkToCopy.isEmpty()); - } - - if (d->interactionFlags & Qt::TextEditable) { -#if !defined(QT_NO_CLIPBOARD) - a = menu->addAction(tr("&Paste") + ACCEL_KEY(QKeySequence::Paste), this, SLOT(paste())); - a->setEnabled(canPaste()); -#endif - a = menu->addAction(tr("Delete"), this, SLOT(_q_deleteSelected())); - a->setEnabled(d->cursor.hasSelection()); - } - - - if (showTextSelectionActions) { - menu->addSeparator(); - a = menu->addAction(tr("Select All") + ACCEL_KEY(QKeySequence::SelectAll), this, SLOT(selectAll())); - a->setEnabled(!d->doc->isEmpty()); - } - -#if !defined(QT_NO_IM) - if (d->contextWidget) { - QInputContext *qic = d->inputContext(); - if (qic) { - QList<QAction *> imActions = qic->actions(); - for (int i = 0; i < imActions.size(); ++i) - menu->addAction(imActions.at(i)); - } - } -#endif - -#if defined(Q_WS_WIN) || defined(Q_WS_X11) - if ((d->interactionFlags & Qt::TextEditable) && qt_use_rtl_extensions) { -#else - if (d->interactionFlags & Qt::TextEditable) { -#endif - menu->addSeparator(); - QUnicodeControlCharacterMenu *ctrlCharacterMenu = new QUnicodeControlCharacterMenu(this, menu); - menu->addMenu(ctrlCharacterMenu); - } - - return menu; -} -#endif // QT_NO_CONTEXTMENU - -QTextCursor QTextControl::cursorForPosition(const QPointF &pos) const -{ - Q_D(const QTextControl); - int cursorPos = hitTest(pos, Qt::FuzzyHit); - if (cursorPos == -1) - cursorPos = 0; - QTextCursor c(d->doc); - c.setPosition(cursorPos); - return c; -} - -QRectF QTextControl::cursorRect(const QTextCursor &cursor) const -{ - Q_D(const QTextControl); - if (cursor.isNull()) - return QRectF(); - - return d->rectForPosition(cursor.position()); -} - -QRectF QTextControl::cursorRect() const -{ - Q_D(const QTextControl); - return cursorRect(d->cursor); -} - -QRectF QTextControlPrivate::cursorRectPlusUnicodeDirectionMarkers(const QTextCursor &cursor) const -{ - if (cursor.isNull()) - return QRectF(); - - return rectForPosition(cursor.position()).adjusted(-4, 0, 4, 0); -} - -QString QTextControl::anchorAt(const QPointF &pos) const -{ - Q_D(const QTextControl); - return d->doc->documentLayout()->anchorAt(pos); -} - -QString QTextControl::anchorAtCursor() const -{ - Q_D(const QTextControl); - - return d->anchorForCursor(d->cursor); -} - -bool QTextControl::overwriteMode() const -{ - Q_D(const QTextControl); - return d->overwriteMode; -} - -void QTextControl::setOverwriteMode(bool overwrite) -{ - Q_D(QTextControl); - d->overwriteMode = overwrite; -} - -int QTextControl::cursorWidth() const -{ -#ifndef QT_NO_PROPERTIES - Q_D(const QTextControl); - return d->doc->documentLayout()->property("cursorWidth").toInt(); -#else - return 1; -#endif -} - -void QTextControl::setCursorWidth(int width) -{ - Q_D(QTextControl); -#ifdef QT_NO_PROPERTIES - Q_UNUSED(width); -#else - if (width == -1) - width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth); - d->doc->documentLayout()->setProperty("cursorWidth", width); -#endif - d->repaintCursor(); -} - -bool QTextControl::acceptRichText() const -{ - Q_D(const QTextControl); - return d->acceptRichText; -} - -void QTextControl::setAcceptRichText(bool accept) -{ - Q_D(QTextControl); - d->acceptRichText = accept; -} - -#ifndef QT_NO_TEXTEDIT - -void QTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections) -{ - Q_D(QTextControl); - - QHash<int, int> hash; - for (int i = 0; i < d->extraSelections.count(); ++i) { - const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(i); - hash.insertMulti(esel.cursor.anchor(), i); - } - - for (int i = 0; i < selections.count(); ++i) { - const QTextEdit::ExtraSelection &sel = selections.at(i); - QHash<int, int>::iterator it = hash.find(sel.cursor.anchor()); - if (it != hash.end()) { - const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(it.value()); - if (esel.cursor.position() == sel.cursor.position() - && esel.format == sel.format) { - hash.erase(it); - continue; - } - } - QRectF r = selectionRect(sel.cursor); - if (sel.format.boolProperty(QTextFormat::FullWidthSelection)) { - r.setLeft(0); - r.setWidth(qreal(INT_MAX)); - } - emit updateRequest(r); - } - - for (QHash<int, int>::iterator it = hash.begin(); it != hash.end(); ++it) { - const QAbstractTextDocumentLayout::Selection &esel = d->extraSelections.at(it.value()); - QRectF r = selectionRect(esel.cursor); - if (esel.format.boolProperty(QTextFormat::FullWidthSelection)) { - r.setLeft(0); - r.setWidth(qreal(INT_MAX)); - } - emit updateRequest(r); - } - - d->extraSelections.resize(selections.count()); - for (int i = 0; i < selections.count(); ++i) { - d->extraSelections[i].cursor = selections.at(i).cursor; - d->extraSelections[i].format = selections.at(i).format; - } -} - -QList<QTextEdit::ExtraSelection> QTextControl::extraSelections() const -{ - Q_D(const QTextControl); - QList<QTextEdit::ExtraSelection> selections; - for (int i = 0; i < d->extraSelections.count(); ++i) { - QTextEdit::ExtraSelection sel; - sel.cursor = d->extraSelections.at(i).cursor; - sel.format = d->extraSelections.at(i).format; - selections.append(sel); - } - return selections; -} - -#endif // QT_NO_TEXTEDIT - -void QTextControl::setTextWidth(qreal width) -{ - Q_D(QTextControl); - d->doc->setTextWidth(width); -} - -qreal QTextControl::textWidth() const -{ - Q_D(const QTextControl); - return d->doc->textWidth(); -} - -QSizeF QTextControl::size() const -{ - Q_D(const QTextControl); - return d->doc->size(); -} - -void QTextControl::setOpenExternalLinks(bool open) -{ - Q_D(QTextControl); - d->openExternalLinks = open; -} - -bool QTextControl::openExternalLinks() const -{ - Q_D(const QTextControl); - return d->openExternalLinks; -} - -bool QTextControl::ignoreUnusedNavigationEvents() const -{ - Q_D(const QTextControl); - return d->ignoreUnusedNavigationEvents; -} - -void QTextControl::setIgnoreUnusedNavigationEvents(bool ignore) -{ - Q_D(QTextControl); - d->ignoreUnusedNavigationEvents = ignore; -} - -void QTextControl::moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode) -{ - Q_D(QTextControl); - const QTextCursor oldSelection = d->cursor; - const bool moved = d->cursor.movePosition(op, mode); - d->_q_updateCurrentCharFormatAndSelection(); - ensureCursorVisible(); - d->repaintOldAndNewSelection(oldSelection); - if (moved) - emit cursorPositionChanged(); -} - -bool QTextControl::canPaste() const -{ -#ifndef QT_NO_CLIPBOARD - Q_D(const QTextControl); - if (d->interactionFlags & Qt::TextEditable) { - const QMimeData *md = QApplication::clipboard()->mimeData(); - return md && canInsertFromMimeData(md); - } -#endif - return false; -} - -void QTextControl::setCursorIsFocusIndicator(bool b) -{ - Q_D(QTextControl); - d->cursorIsFocusIndicator = b; - d->repaintCursor(); -} - -bool QTextControl::cursorIsFocusIndicator() const -{ - Q_D(const QTextControl); - return d->cursorIsFocusIndicator; -} - - -void QTextControl::setDragEnabled(bool enabled) -{ - Q_D(QTextControl); - d->dragEnabled = enabled; -} - -bool QTextControl::isDragEnabled() const -{ - Q_D(const QTextControl); - return d->dragEnabled; -} - -void QTextControl::setWordSelectionEnabled(bool enabled) -{ - Q_D(QTextControl); - d->wordSelectionEnabled = enabled; -} - -bool QTextControl::isWordSelectionEnabled() const -{ - Q_D(const QTextControl); - return d->wordSelectionEnabled; -} - -#ifndef QT_NO_PRINTER -void QTextControl::print(QPrinter *printer) const -{ -#ifndef QT_NO_PRINTER - Q_D(const QTextControl); - if (!printer || !printer->isValid()) - return; - QTextDocument *tempDoc = 0; - const QTextDocument *doc = d->doc; - if (printer->printRange() == QPrinter::Selection) { - if (!d->cursor.hasSelection()) - return; - tempDoc = new QTextDocument(const_cast<QTextDocument *>(doc)); - tempDoc->setMetaInformation(QTextDocument::DocumentTitle, doc->metaInformation(QTextDocument::DocumentTitle)); - tempDoc->setPageSize(doc->pageSize()); - tempDoc->setDefaultFont(doc->defaultFont()); - tempDoc->setUseDesignMetrics(doc->useDesignMetrics()); - QTextCursor(tempDoc).insertFragment(d->cursor.selection()); - doc = tempDoc; - - // copy the custom object handlers - doc->documentLayout()->d_func()->handlers = d->doc->documentLayout()->d_func()->handlers; - } - doc->print(printer); - delete tempDoc; -#endif -} -#endif // QT_NO_PRINTER - -QMimeData *QTextControl::createMimeDataFromSelection() const -{ - Q_D(const QTextControl); - const QTextDocumentFragment fragment(d->cursor); - return new QTextEditMimeData(fragment); -} - -bool QTextControl::canInsertFromMimeData(const QMimeData *source) const -{ - Q_D(const QTextControl); - if (d->acceptRichText) - return (source->hasText() && !source->text().isEmpty()) - || source->hasHtml() - || source->hasFormat(QLatin1String("application/x-qrichtext")) - || source->hasFormat(QLatin1String("application/x-qt-richtext")); - else - return source->hasText() && !source->text().isEmpty(); -} - -void QTextControl::insertFromMimeData(const QMimeData *source) -{ - Q_D(QTextControl); - if (!(d->interactionFlags & Qt::TextEditable) || !source) - return; - - bool hasData = false; - QTextDocumentFragment fragment; -#ifndef QT_NO_TEXTHTMLPARSER - if (source->hasFormat(QLatin1String("application/x-qrichtext")) && d->acceptRichText) { - // x-qrichtext is always UTF-8 (taken from Qt3 since we don't use it anymore). - QString richtext = QString::fromUtf8(source->data(QLatin1String("application/x-qrichtext"))); - richtext.prepend(QLatin1String("<meta name=\"qrichtext\" content=\"1\" />")); - fragment = QTextDocumentFragment::fromHtml(richtext, d->doc); - hasData = true; - } else if (source->hasHtml() && d->acceptRichText) { - fragment = QTextDocumentFragment::fromHtml(source->html(), d->doc); - hasData = true; - } else { - QString text = source->text(); - if (!text.isNull()) { - fragment = QTextDocumentFragment::fromPlainText(text); - hasData = true; - } - } -#else - fragment = QTextDocumentFragment::fromPlainText(source->text()); -#endif // QT_NO_TEXTHTMLPARSER - - if (hasData) - d->cursor.insertFragment(fragment); - ensureCursorVisible(); -} - -bool QTextControl::findNextPrevAnchor(const QTextCursor &startCursor, bool next, QTextCursor &newAnchor) -{ - Q_D(QTextControl); - - int anchorStart = -1; - QString anchorHref; - int anchorEnd = -1; - - if (next) { - const int startPos = startCursor.selectionEnd(); - - QTextBlock block = d->doc->findBlock(startPos); - QTextBlock::Iterator it = block.begin(); - - while (!it.atEnd() && it.fragment().position() < startPos) - ++it; - - while (block.isValid()) { - anchorStart = -1; - - // find next anchor - for (; !it.atEnd(); ++it) { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) { - anchorStart = fragment.position(); - anchorHref = fmt.anchorHref(); - break; - } - } - - if (anchorStart != -1) { - anchorEnd = -1; - - // find next non-anchor fragment - for (; !it.atEnd(); ++it) { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) { - anchorEnd = fragment.position(); - break; - } - } - - if (anchorEnd == -1) - anchorEnd = block.position() + block.length() - 1; - - // make found selection - break; - } - - block = block.next(); - it = block.begin(); - } - } else { - int startPos = startCursor.selectionStart(); - if (startPos > 0) - --startPos; - - QTextBlock block = d->doc->findBlock(startPos); - QTextBlock::Iterator blockStart = block.begin(); - QTextBlock::Iterator it = block.end(); - - if (startPos == block.position()) { - it = block.begin(); - } else { - do { - if (it == blockStart) { - it = QTextBlock::Iterator(); - block = QTextBlock(); - } else { - --it; - } - } while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos); - } - - while (block.isValid()) { - anchorStart = -1; - - if (!it.atEnd()) { - do { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) { - anchorStart = fragment.position() + fragment.length(); - anchorHref = fmt.anchorHref(); - break; - } - - if (it == blockStart) - it = QTextBlock::Iterator(); - else - --it; - } while (!it.atEnd()); - } - - if (anchorStart != -1 && !it.atEnd()) { - anchorEnd = -1; - - do { - const QTextFragment fragment = it.fragment(); - const QTextCharFormat fmt = fragment.charFormat(); - - if (!fmt.isAnchor() || fmt.anchorHref() != anchorHref) { - anchorEnd = fragment.position() + fragment.length(); - break; - } - - if (it == blockStart) - it = QTextBlock::Iterator(); - else - --it; - } while (!it.atEnd()); - - if (anchorEnd == -1) - anchorEnd = qMax(0, block.position()); - - break; - } - - block = block.previous(); - it = block.end(); - if (it != block.begin()) - --it; - blockStart = block.begin(); - } - - } - - if (anchorStart != -1 && anchorEnd != -1) { - newAnchor = d->cursor; - newAnchor.setPosition(anchorStart); - newAnchor.setPosition(anchorEnd, QTextCursor::KeepAnchor); - return true; - } - - return false; -} - -void QTextControlPrivate::activateLinkUnderCursor(QString href) -{ - QTextCursor oldCursor = cursor; - - if (href.isEmpty()) { - QTextCursor tmp = cursor; - if (tmp.selectionStart() != tmp.position()) - tmp.setPosition(tmp.selectionStart()); - tmp.movePosition(QTextCursor::NextCharacter); - href = tmp.charFormat().anchorHref(); - } - if (href.isEmpty()) - return; - - if (!cursor.hasSelection()) { - QTextBlock block = cursor.block(); - const int cursorPos = cursor.position(); - - QTextBlock::Iterator it = block.begin(); - QTextBlock::Iterator linkFragment; - - for (; !it.atEnd(); ++it) { - QTextFragment fragment = it.fragment(); - const int fragmentPos = fragment.position(); - if (fragmentPos <= cursorPos && - fragmentPos + fragment.length() > cursorPos) { - linkFragment = it; - break; - } - } - - if (!linkFragment.atEnd()) { - it = linkFragment; - cursor.setPosition(it.fragment().position()); - if (it != block.begin()) { - do { - --it; - QTextFragment fragment = it.fragment(); - if (fragment.charFormat().anchorHref() != href) - break; - cursor.setPosition(fragment.position()); - } while (it != block.begin()); - } - - for (it = linkFragment; !it.atEnd(); ++it) { - QTextFragment fragment = it.fragment(); - if (fragment.charFormat().anchorHref() != href) - break; - cursor.setPosition(fragment.position() + fragment.length(), QTextCursor::KeepAnchor); - } - } - } - - if (hasFocus) { - cursorIsFocusIndicator = true; - } else { - cursorIsFocusIndicator = false; - cursor.clearSelection(); - } - repaintOldAndNewSelection(oldCursor); - -#ifndef QT_NO_DESKTOPSERVICES - if (openExternalLinks) - QDesktopServices::openUrl(href); - else -#endif - emit q_func()->linkActivated(href); -} - -#ifndef QT_NO_TOOLTIP -void QTextControlPrivate::showToolTip(const QPoint &globalPos, const QPointF &pos, QWidget *contextWidget) -{ - const QString toolTip = q_func()->cursorForPosition(pos).charFormat().toolTip(); - if (toolTip.isEmpty()) - return; - QToolTip::showText(globalPos, toolTip, contextWidget); -} -#endif // QT_NO_TOOLTIP - -bool QTextControl::setFocusToNextOrPreviousAnchor(bool next) -{ - Q_D(QTextControl); - - if (!(d->interactionFlags & Qt::LinksAccessibleByKeyboard)) - return false; - - QRectF crect = selectionRect(); - emit updateRequest(crect); - - // If we don't have a current anchor, we start from the start/end - if (!d->cursor.hasSelection()) { - d->cursor = QTextCursor(d->doc); - if (next) - d->cursor.movePosition(QTextCursor::Start); - else - d->cursor.movePosition(QTextCursor::End); - } - - QTextCursor newAnchor; - if (findNextPrevAnchor(d->cursor, next, newAnchor)) { - d->cursor = newAnchor; - d->cursorIsFocusIndicator = true; - } else { - d->cursor.clearSelection(); - } - - if (d->cursor.hasSelection()) { - crect = selectionRect(); - emit updateRequest(crect); - emit visibilityRequest(crect); - return true; - } else { - return false; - } -} - -bool QTextControl::setFocusToAnchor(const QTextCursor &newCursor) -{ - Q_D(QTextControl); - - if (!(d->interactionFlags & Qt::LinksAccessibleByKeyboard)) - return false; - - // Verify that this is an anchor. - const QString anchorHref = d->anchorForCursor(newCursor); - if (anchorHref.isEmpty()) - return false; - - // and process it - QRectF crect = selectionRect(); - emit updateRequest(crect); - - d->cursor.setPosition(newCursor.selectionStart()); - d->cursor.setPosition(newCursor.selectionEnd(), QTextCursor::KeepAnchor); - d->cursorIsFocusIndicator = true; - - crect = selectionRect(); - emit updateRequest(crect); - emit visibilityRequest(crect); - return true; -} - -void QTextControl::setTextInteractionFlags(Qt::TextInteractionFlags flags) -{ - Q_D(QTextControl); - if (flags == d->interactionFlags) - return; - d->interactionFlags = flags; - - if (d->hasFocus) - d->setBlinkingCursorEnabled(flags & Qt::TextEditable); -} - -Qt::TextInteractionFlags QTextControl::textInteractionFlags() const -{ - Q_D(const QTextControl); - return d->interactionFlags; -} - -void QTextControl::mergeCurrentCharFormat(const QTextCharFormat &modifier) -{ - Q_D(QTextControl); - d->cursor.mergeCharFormat(modifier); - d->updateCurrentCharFormat(); -} - -void QTextControl::setCurrentCharFormat(const QTextCharFormat &format) -{ - Q_D(QTextControl); - d->cursor.setCharFormat(format); - d->updateCurrentCharFormat(); -} - -QTextCharFormat QTextControl::currentCharFormat() const -{ - Q_D(const QTextControl); - return d->cursor.charFormat(); -} - -void QTextControl::insertPlainText(const QString &text) -{ - Q_D(QTextControl); - d->cursor.insertText(text); -} - -#ifndef QT_NO_TEXTHTMLPARSER -void QTextControl::insertHtml(const QString &text) -{ - Q_D(QTextControl); - d->cursor.insertHtml(text); -} -#endif // QT_NO_TEXTHTMLPARSER - -QPointF QTextControl::anchorPosition(const QString &name) const -{ - Q_D(const QTextControl); - if (name.isEmpty()) - return QPointF(); - - QRectF r; - for (QTextBlock block = d->doc->begin(); block.isValid(); block = block.next()) { - QTextCharFormat format = block.charFormat(); - if (format.isAnchor() && format.anchorNames().contains(name)) { - r = d->rectForPosition(block.position()); - break; - } - - for (QTextBlock::Iterator it = block.begin(); !it.atEnd(); ++it) { - QTextFragment fragment = it.fragment(); - format = fragment.charFormat(); - if (format.isAnchor() && format.anchorNames().contains(name)) { - r = d->rectForPosition(fragment.position()); - block = QTextBlock(); - break; - } - } - } - if (!r.isValid()) - return QPointF(); - return QPointF(0, r.top()); -} - -void QTextControl::adjustSize() -{ - Q_D(QTextControl); - d->doc->adjustSize(); -} - -bool QTextControl::find(const QString &exp, QTextDocument::FindFlags options) -{ - Q_D(QTextControl); - QTextCursor search = d->doc->find(exp, d->cursor, options); - if (search.isNull()) - return false; - - setTextCursor(search); - return true; -} - - - -void QTextControlPrivate::append(const QString &text, Qt::TextFormat format) -{ - QTextCursor tmp(doc); - tmp.beginEditBlock(); - tmp.movePosition(QTextCursor::End); - - if (!doc->isEmpty()) - tmp.insertBlock(cursor.blockFormat(), cursor.charFormat()); - else - tmp.setCharFormat(cursor.charFormat()); - - // preserve the char format - QTextCharFormat oldCharFormat = cursor.charFormat(); - -#ifndef QT_NO_TEXTHTMLPARSER - if (format == Qt::RichText || (format == Qt::AutoText && Qt::mightBeRichText(text))) { - tmp.insertHtml(text); - } else { - tmp.insertText(text); - } -#else - tmp.insertText(text); -#endif // QT_NO_TEXTHTMLPARSER - if (!cursor.hasSelection()) - cursor.setCharFormat(oldCharFormat); - - tmp.endEditBlock(); -} - -void QTextControl::append(const QString &text) -{ - Q_D(QTextControl); - d->append(text, Qt::AutoText); -} - -void QTextControl::appendHtml(const QString &html) -{ - Q_D(QTextControl); - d->append(html, Qt::RichText); -} - -void QTextControl::appendPlainText(const QString &text) -{ - Q_D(QTextControl); - d->append(text, Qt::PlainText); -} - - -void QTextControl::ensureCursorVisible() -{ - Q_D(QTextControl); - QRectF crect = d->rectForPosition(d->cursor.position()).adjusted(-5, 0, 5, 0); - emit visibilityRequest(crect); - emit microFocusChanged(); -} - -QPalette QTextControl::palette() const -{ - Q_D(const QTextControl); - return d->palette; -} - -void QTextControl::setPalette(const QPalette &pal) -{ - Q_D(QTextControl); - d->palette = pal; -} - -QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget *widget) const -{ - Q_D(const QTextControl); - - QAbstractTextDocumentLayout::PaintContext ctx; - - ctx.selections = d->extraSelections; - ctx.palette = d->palette; - if (d->cursorOn && d->isEnabled) { - if (d->hideCursor) - ctx.cursorPosition = -1; - else if (d->preeditCursor != 0) - ctx.cursorPosition = - (d->preeditCursor + 2); - else - ctx.cursorPosition = d->cursor.position(); - } - - if (!d->dndFeedbackCursor.isNull()) - ctx.cursorPosition = d->dndFeedbackCursor.position(); -#ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || d->hasEditFocus) -#endif - if (d->cursor.hasSelection()) { - QAbstractTextDocumentLayout::Selection selection; - selection.cursor = d->cursor; - if (d->cursorIsFocusIndicator) { - QStyleOption opt; - opt.palette = ctx.palette; - QStyleHintReturnVariant ret; - QStyle *style = QApplication::style(); - if (widget) - style = widget->style(); - style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret); - selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat(); - } else { - QPalette::ColorGroup cg = d->hasFocus ? QPalette::Active : QPalette::Inactive; - selection.format.setBackground(ctx.palette.brush(cg, QPalette::Highlight)); - selection.format.setForeground(ctx.palette.brush(cg, QPalette::HighlightedText)); - QStyleOption opt; - QStyle *style = QApplication::style(); - if (widget) { - opt.initFrom(widget); - style = widget->style(); - } - if (style->styleHint(QStyle::SH_RichText_FullWidthSelection, &opt, widget)) - selection.format.setProperty(QTextFormat::FullWidthSelection, true); - } - ctx.selections.append(selection); - } - - return ctx; -} - -void QTextControl::drawContents(QPainter *p, const QRectF &rect, QWidget *widget) -{ - Q_D(QTextControl); - p->save(); - QAbstractTextDocumentLayout::PaintContext ctx = getPaintContext(widget); - if (rect.isValid()) - p->setClipRect(rect, Qt::IntersectClip); - ctx.clip = rect; - - d->doc->documentLayout()->draw(p, ctx); - p->restore(); -} - -void QTextControlPrivate::_q_copyLink() -{ -#ifndef QT_NO_CLIPBOARD - QMimeData *md = new QMimeData; - md->setText(linkToCopy); - QApplication::clipboard()->setMimeData(md); -#endif -} - -QInputContext *QTextControlPrivate::inputContext() -{ - QInputContext *ctx = contextWidget->inputContext(); - if (!ctx && contextWidget->parentWidget()) - ctx = contextWidget->parentWidget()->inputContext(); - return ctx; -} - -int QTextControl::hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const -{ - Q_D(const QTextControl); - return d->doc->documentLayout()->hitTest(point, accuracy); -} - -QRectF QTextControl::blockBoundingRect(const QTextBlock &block) const -{ - Q_D(const QTextControl); - return d->doc->documentLayout()->blockBoundingRect(block); -} - -#ifndef QT_NO_CONTEXTMENU -#define NUM_CONTROL_CHARACTERS 10 -const struct QUnicodeControlCharacter { - const char *text; - ushort character; -} qt_controlCharacters[NUM_CONTROL_CHARACTERS] = { - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "LRM Left-to-right mark"), 0x200e }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "RLM Right-to-left mark"), 0x200f }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "ZWJ Zero width joiner"), 0x200d }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "ZWNJ Zero width non-joiner"), 0x200c }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "ZWSP Zero width space"), 0x200b }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "LRE Start of left-to-right embedding"), 0x202a }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "RLE Start of right-to-left embedding"), 0x202b }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "LRO Start of left-to-right override"), 0x202d }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "RLO Start of right-to-left override"), 0x202e }, - { QT_TRANSLATE_NOOP("QUnicodeControlCharacterMenu", "PDF Pop directional formatting"), 0x202c }, -}; - -QUnicodeControlCharacterMenu::QUnicodeControlCharacterMenu(QObject *_editWidget, QWidget *parent) - : QMenu(parent), editWidget(_editWidget) -{ - setTitle(tr("Insert Unicode control character")); - for (int i = 0; i < NUM_CONTROL_CHARACTERS; ++i) { - addAction(tr(qt_controlCharacters[i].text), this, SLOT(menuActionTriggered())); - } -} - -void QUnicodeControlCharacterMenu::menuActionTriggered() -{ - QAction *a = qobject_cast<QAction *>(sender()); - int idx = actions().indexOf(a); - if (idx < 0 || idx >= NUM_CONTROL_CHARACTERS) - return; - QChar c(qt_controlCharacters[idx].character); - QString str(c); - -#ifndef QT_NO_TEXTEDIT - if (QTextEdit *edit = qobject_cast<QTextEdit *>(editWidget)) { - edit->insertPlainText(str); - return; - } -#endif - if (QTextControl *control = qobject_cast<QTextControl *>(editWidget)) { - control->insertPlainText(str); - } -#ifndef QT_NO_LINEEDIT - if (QLineEdit *edit = qobject_cast<QLineEdit *>(editWidget)) { - edit->insert(str); - return; - } -#endif -} -#endif // QT_NO_CONTEXTMENU - -QStringList QTextEditMimeData::formats() const -{ - if (!fragment.isEmpty()) - return QStringList() << QString::fromLatin1("text/plain") << QString::fromLatin1("text/html") -#ifndef QT_NO_TEXTODFWRITER - << QString::fromLatin1("application/vnd.oasis.opendocument.text") -#endif - ; - else - return QMimeData::formats(); -} - -QVariant QTextEditMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const -{ - if (!fragment.isEmpty()) - setup(); - return QMimeData::retrieveData(mimeType, type); -} - -void QTextEditMimeData::setup() const -{ - QTextEditMimeData *that = const_cast<QTextEditMimeData *>(this); -#ifndef QT_NO_TEXTHTMLPARSER - that->setData(QLatin1String("text/html"), fragment.toHtml("utf-8").toUtf8()); -#endif -#ifndef QT_NO_TEXTODFWRITER - { - QBuffer buffer; - QTextDocumentWriter writer(&buffer, "ODF"); - writer.write(fragment); - buffer.close(); - that->setData(QLatin1String("application/vnd.oasis.opendocument.text"), buffer.data()); - } -#endif - that->setText(fragment.toPlainText()); - fragment = QTextDocumentFragment(); -} - -QT_END_NAMESPACE - -#include "moc_qtextcontrol_p.cpp" - -#endif // QT_NO_TEXTCONTROL diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h deleted file mode 100644 index 31fa843a3a..0000000000 --- a/src/gui/text/qtextcontrol_p.h +++ /dev/null @@ -1,312 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTEXTCONTROL_P_H -#define QTEXTCONTROL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/qtextdocument.h> -#include <QtGui/qtextoption.h> -#include <QtGui/qtextcursor.h> -#include <QtGui/qtextformat.h> -#include <QtGui/qtextedit.h> -#include <QtGui/qmenu.h> -#include <QtCore/qrect.h> -#include <QtGui/qabstracttextdocumentlayout.h> -#include <QtGui/qtextdocumentfragment.h> -#include <QtGui/qclipboard.h> - -#ifdef QT3_SUPPORT -#include <QtGui/qtextobject.h> -#include <QtGui/qtextlayout.h> -#endif - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -QT_MODULE(Gui) - -class QStyleSheet; -class QTextDocument; -class QMenu; -class QTextControlPrivate; -class QMimeData; -class QAbstractScrollArea; -class QEvent; -class QTimerEvent; - -class Q_GUI_EXPORT QTextControl : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QTextControl) -#ifndef QT_NO_TEXTHTMLPARSER - Q_PROPERTY(QString html READ toHtml WRITE setHtml NOTIFY textChanged USER true) -#endif - Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode) - Q_PROPERTY(bool acceptRichText READ acceptRichText WRITE setAcceptRichText) - Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth) - Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) - Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks) - Q_PROPERTY(bool ignoreUnusedNavigationEvents READ ignoreUnusedNavigationEvents WRITE setIgnoreUnusedNavigationEvents) -public: - explicit QTextControl(QObject *parent = 0); - explicit QTextControl(const QString &text, QObject *parent = 0); - explicit QTextControl(QTextDocument *doc, QObject *parent = 0); - virtual ~QTextControl(); - - void setDocument(QTextDocument *document); - QTextDocument *document() const; - - void setTextCursor(const QTextCursor &cursor); - QTextCursor textCursor() const; - - void setTextInteractionFlags(Qt::TextInteractionFlags flags); - Qt::TextInteractionFlags textInteractionFlags() const; - - void mergeCurrentCharFormat(const QTextCharFormat &modifier); - - void setCurrentCharFormat(const QTextCharFormat &format); - QTextCharFormat currentCharFormat() const; - - bool find(const QString &exp, QTextDocument::FindFlags options = 0); - - inline QString toPlainText() const - { return document()->toPlainText(); } -#ifndef QT_NO_TEXTHTMLPARSER - inline QString toHtml() const - { return document()->toHtml(); } -#endif - - virtual void ensureCursorVisible(); - - virtual QVariant loadResource(int type, const QUrl &name); -#ifndef QT_NO_CONTEXTMENU - QMenu *createStandardContextMenu(const QPointF &pos, QWidget *parent); -#endif - - QTextCursor cursorForPosition(const QPointF &pos) const; - QRectF cursorRect(const QTextCursor &cursor) const; - QRectF cursorRect() const; - QRectF selectionRect(const QTextCursor &cursor) const; - QRectF selectionRect() const; - - QString anchorAt(const QPointF &pos) const; - QPointF anchorPosition(const QString &name) const; - - QString anchorAtCursor() const; - - bool overwriteMode() const; - void setOverwriteMode(bool overwrite); - - int cursorWidth() const; - void setCursorWidth(int width); - - bool acceptRichText() const; - void setAcceptRichText(bool accept); - -#ifndef QT_NO_TEXTEDIT - void setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections); - QList<QTextEdit::ExtraSelection> extraSelections() const; -#endif - - void setTextWidth(qreal width); - qreal textWidth() const; - QSizeF size() const; - - void setOpenExternalLinks(bool open); - bool openExternalLinks() const; - - void setIgnoreUnusedNavigationEvents(bool ignore); - bool ignoreUnusedNavigationEvents() const; - - void moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor); - - bool canPaste() const; - - void setCursorIsFocusIndicator(bool b); - bool cursorIsFocusIndicator() const; - - void setDragEnabled(bool enabled); - bool isDragEnabled() const; - - bool isWordSelectionEnabled() const; - void setWordSelectionEnabled(bool enabled); - -#ifndef QT_NO_PRINTER - void print(QPrinter *printer) const; -#endif - - virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const; - virtual QRectF blockBoundingRect(const QTextBlock &block) const; - QAbstractTextDocumentLayout::PaintContext getPaintContext(QWidget *widget) const; - -public Q_SLOTS: - void setPlainText(const QString &text); - void setHtml(const QString &text); - -#ifndef QT_NO_CLIPBOARD - void cut(); - void copy(); - void paste(QClipboard::Mode mode = QClipboard::Clipboard); -#endif - - void undo(); - void redo(); - - void clear(); - void selectAll(); - - void insertPlainText(const QString &text); -#ifndef QT_NO_TEXTHTMLPARSER - void insertHtml(const QString &text); -#endif - - void append(const QString &text); - void appendHtml(const QString &html); - void appendPlainText(const QString &text); - - void adjustSize(); - -Q_SIGNALS: - void textChanged(); - void undoAvailable(bool b); - void redoAvailable(bool b); - void currentCharFormatChanged(const QTextCharFormat &format); - void copyAvailable(bool b); - void selectionChanged(); - void cursorPositionChanged(); - - // control signals - void updateRequest(const QRectF &rect = QRectF()); - void documentSizeChanged(const QSizeF &); - void blockCountChanged(int newBlockCount); - void visibilityRequest(const QRectF &rect); - void microFocusChanged(); - void linkActivated(const QString &link); - void linkHovered(const QString &); - void modificationChanged(bool m); - -public: - // control properties - QPalette palette() const; - void setPalette(const QPalette &pal); - - virtual void processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget = 0); - void processEvent(QEvent *e, const QPointF &coordinateOffset = QPointF(), QWidget *contextWidget = 0); - - // control methods - void drawContents(QPainter *painter, const QRectF &rect = QRectF(), QWidget *widget = 0); - - void setFocus(bool focus, Qt::FocusReason = Qt::OtherFocusReason); - - virtual QVariant inputMethodQuery(Qt::InputMethodQuery property) const; - - virtual QMimeData *createMimeDataFromSelection() const; - virtual bool canInsertFromMimeData(const QMimeData *source) const; - virtual void insertFromMimeData(const QMimeData *source); - - bool setFocusToAnchor(const QTextCursor &newCursor); - bool setFocusToNextOrPreviousAnchor(bool next); - bool findNextPrevAnchor(const QTextCursor& from, bool next, QTextCursor& newAnchor); - -protected: - virtual void timerEvent(QTimerEvent *e); - - virtual bool event(QEvent *e); - -private: - Q_DISABLE_COPY(QTextControl) - Q_PRIVATE_SLOT(d_func(), void _q_updateCurrentCharFormatAndSelection()) - Q_PRIVATE_SLOT(d_func(), void _q_emitCursorPosChanged(const QTextCursor &)) - Q_PRIVATE_SLOT(d_func(), void _q_deleteSelected()) - Q_PRIVATE_SLOT(d_func(), void _q_copyLink()) - Q_PRIVATE_SLOT(d_func(), void _q_updateBlock(const QTextBlock &)) - Q_PRIVATE_SLOT(d_func(), void _q_documentLayoutChanged()) -}; - - -#ifndef QT_NO_CONTEXTMENU -class QUnicodeControlCharacterMenu : public QMenu -{ - Q_OBJECT -public: - QUnicodeControlCharacterMenu(QObject *editWidget, QWidget *parent); - -private Q_SLOTS: - void menuActionTriggered(); - -private: - QObject *editWidget; -}; -#endif // QT_NO_CONTEXTMENU - - -// also used by QLabel -class QTextEditMimeData : public QMimeData -{ -public: - inline QTextEditMimeData(const QTextDocumentFragment &aFragment) : fragment(aFragment) {} - - virtual QStringList formats() const; -protected: - virtual QVariant retrieveData(const QString &mimeType, QVariant::Type type) const; -private: - void setup() const; - - mutable QTextDocumentFragment fragment; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QTEXTCONTROL_H diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h deleted file mode 100644 index 94670e225e..0000000000 --- a/src/gui/text/qtextcontrol_p_p.h +++ /dev/null @@ -1,238 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTEXTCONTROL_P_P_H -#define QTEXTCONTROL_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "QtGui/qtextdocumentfragment.h" -#include "QtGui/qscrollbar.h" -#include "QtGui/qtextcursor.h" -#include "QtGui/qtextformat.h" -#include "QtGui/qmenu.h" -#include "QtGui/qabstracttextdocumentlayout.h" -#include "QtCore/qbasictimer.h" -#include "QtCore/qpointer.h" -#include "private/qobject_p.h" - -QT_BEGIN_NAMESPACE - -class QMimeData; -class QAbstractScrollArea; -class QInputContext; - -class QTextControlPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QTextControl) -public: - QTextControlPrivate(); - - bool cursorMoveKeyEvent(QKeyEvent *e); - - void updateCurrentCharFormat(); - - void indent(); - void outdent(); - - void gotoNextTableCell(); - void gotoPreviousTableCell(); - - void createAutoBulletList(); - - void init(Qt::TextFormat format = Qt::RichText, const QString &text = QString(), - QTextDocument *document = 0); - void setContent(Qt::TextFormat format = Qt::RichText, const QString &text = QString(), - QTextDocument *document = 0); - void startDrag(); - - void paste(const QMimeData *source); - - void setCursorPosition(const QPointF &pos); - void setCursorPosition(int pos, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor); - - void repaintCursor(); - inline void repaintSelection() - { repaintOldAndNewSelection(QTextCursor()); } - void repaintOldAndNewSelection(const QTextCursor &oldSelection); - - void selectionChanged(bool forceEmitSelectionChanged = false); - - void _q_updateCurrentCharFormatAndSelection(); - -#ifndef QT_NO_CLIPBOARD - void setClipboardSelection(); -#endif - - void _q_emitCursorPosChanged(const QTextCursor &someCursor); - - void setBlinkingCursorEnabled(bool enable); - - void extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition); - void extendBlockwiseSelection(int suggestedNewPosition); - - void _q_deleteSelected(); - - void _q_setCursorAfterUndoRedo(int undoPosition, int charsAdded, int charsRemoved); - - QRectF cursorRectPlusUnicodeDirectionMarkers(const QTextCursor &cursor) const; - QRectF rectForPosition(int position) const; - QRectF selectionRect(const QTextCursor &cursor) const; - inline QRectF selectionRect() const - { return selectionRect(this->cursor); } - - QString anchorForCursor(const QTextCursor &anchor) const; - - void keyPressEvent(QKeyEvent *e); - void mousePressEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, - Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, - const QPoint &globalPos); - void mouseMoveEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, - Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, - const QPoint &globalPos); - void mouseReleaseEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, - Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, - const QPoint &globalPos); - void mouseDoubleClickEvent(QEvent *e, Qt::MouseButton button, const QPointF &pos, - Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, - const QPoint &globalPos); - bool sendMouseEventToInputContext(QEvent *e, QEvent::Type eventType, Qt::MouseButton button, - const QPointF &pos, - Qt::KeyboardModifiers modifiers, - Qt::MouseButtons buttons, - const QPoint &globalPos); - void contextMenuEvent(const QPoint &screenPos, const QPointF &docPos, QWidget *contextWidget); - void focusEvent(QFocusEvent *e); -#ifdef QT_KEYPAD_NAVIGATION - void editFocusEvent(QEvent *e); -#endif - bool dragEnterEvent(QEvent *e, const QMimeData *mimeData); - void dragLeaveEvent(); - bool dragMoveEvent(QEvent *e, const QMimeData *mimeData, const QPointF &pos); - bool dropEvent(const QMimeData *mimeData, const QPointF &pos, Qt::DropAction dropAction, QWidget *source); - - void inputMethodEvent(QInputMethodEvent *); - - void activateLinkUnderCursor(QString href = QString()); - -#ifndef QT_NO_TOOLTIP - void showToolTip(const QPoint &globalPos, const QPointF &pos, QWidget *contextWidget); -#endif - - void append(const QString &text, Qt::TextFormat format = Qt::AutoText); - - QInputContext *inputContext(); - - QTextDocument *doc; - bool cursorOn; - QTextCursor cursor; - bool cursorIsFocusIndicator; - QTextCharFormat lastCharFormat; - - QTextCursor dndFeedbackCursor; - - Qt::TextInteractionFlags interactionFlags; - - QBasicTimer cursorBlinkTimer; - QBasicTimer trippleClickTimer; - QPointF trippleClickPoint; - - bool dragEnabled; - - bool mousePressed; - - bool mightStartDrag; - QPoint dragStartPos; - QPointer<QWidget> contextWidget; - - bool lastSelectionState; - - bool ignoreAutomaticScrollbarAdjustement; - - QTextCursor selectedWordOnDoubleClick; - QTextCursor selectedBlockOnTrippleClick; - - bool overwriteMode; - bool acceptRichText; - - int preeditCursor; - bool hideCursor; // used to hide the cursor in the preedit area - - QVector<QAbstractTextDocumentLayout::Selection> extraSelections; - - QPalette palette; - bool hasFocus; -#ifdef QT_KEYPAD_NAVIGATION - bool hasEditFocus; -#endif - bool isEnabled; - - QString highlightedAnchor; // Anchor below cursor - QString anchorOnMousePress; - bool hadSelectionOnMousePress; - - bool ignoreUnusedNavigationEvents; - bool openExternalLinks; - - bool wordSelectionEnabled; - - QString linkToCopy; - void _q_copyLink(); - void _q_updateBlock(const QTextBlock &); - void _q_documentLayoutChanged(); -}; - -QT_END_NAMESPACE - -#endif // QTEXTCONTROL_P_H diff --git a/src/gui/text/qtextcursor_p.h b/src/gui/text/qtextcursor_p.h index 566495e1a3..9d9d79ff5d 100644 --- a/src/gui/text/qtextcursor_p.h +++ b/src/gui/text/qtextcursor_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE -class QTextCursorPrivate : public QSharedData +class Q_GUI_EXPORT QTextCursorPrivate : public QSharedData { public: QTextCursorPrivate(QTextDocumentPrivate *p); diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 9169955617..83b875c149 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -54,14 +54,10 @@ #include "qtexthtmlparser_p.h" #include "qpainter.h" #include "qprinter.h" -#include "qtextedit.h" #include <qfile.h> #include <qfileinfo.h> #include <qdir.h> -#include <qapplication.h> -#include "qtextcontrol_p.h" #include "qfont_p.h" -#include "private/qtextedit_p.h" #include "private/qdataurl_p.h" #include "qtextdocument_p.h" @@ -1971,6 +1967,8 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) if (doc) { r = doc->loadResource(type, name); } +#if 0 + // ### Qt5: reenable #ifndef QT_NO_TEXTEDIT else if (QTextEdit *edit = qobject_cast<QTextEdit *>(parent())) { QUrl resolvedName = edit->d_func()->resolveUrl(name); @@ -1982,6 +1980,7 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) r = control->loadResource(type, name); } #endif +#endif // handle data: URLs if (r.isNull() && name.scheme().compare(QLatin1String("data"), Qt::CaseInsensitive) == 0) diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index f3dc975259..e6d5070340 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -46,6 +46,7 @@ #include "qtextlist.h" #include "qtextengine_p.h" #include "private/qcssutil_p.h" +#include "private/qguiapplication_p.h" #include "qabstracttextdocumentlayout_p.h" #include "qcssparser_p.h" @@ -57,7 +58,6 @@ #include <qdebug.h> #include <qvarlengtharray.h> #include <limits.h> -#include <qstyle.h> #include <qbasictimer.h> #include "private/qfunctions_p.h" @@ -2572,7 +2572,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi Qt::Alignment align = docPrivate->defaultTextOption.alignment(); if (blockFormat.hasProperty(QTextFormat::BlockAlignment)) align = blockFormat.alignment(); - option.setAlignment(QStyle::visualAlignment(dir, align)); // for paragraph that are RTL, alignment is auto-reversed; + option.setAlignment(QGuiApplicationPrivate::visualAlignment(dir, align)); // for paragraph that are RTL, alignment is auto-reversed; if (blockFormat.nonBreakableLines() || document->pageSize().width() < 0) { option.setWrapMode(QTextOption::ManualWrap); diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index ff27bc673f..b0713bb0e4 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -53,7 +53,7 @@ #include "qstring.h" #include <private/qunicodetables_p.h> #include "qtextdocument_p.h" -#include <qapplication.h> +#include <qguiapplication.h> #include <stdlib.h> @@ -1606,7 +1606,7 @@ bool QTextEngine::isRightToLeft() const itemize(); // this places the cursor in the right position depending on the keyboard layout if (layoutData->string.isEmpty()) - return QApplication::keyboardInputDirection() == Qt::RightToLeft; + return QGuiApplication::keyboardInputDirection() == Qt::RightToLeft; return layoutData->string.isRightToLeft(); } diff --git a/src/gui/text/qtextengine_mac.cpp b/src/gui/text/qtextengine_mac.cpp deleted file mode 100644 index 2c6e579b45..0000000000 --- a/src/gui/text/qtextengine_mac.cpp +++ /dev/null @@ -1,656 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtGui module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtextengine_p.h" - -#include <private/qfontengine_coretext_p.h> -#include <private/qfontengine_mac_p.h> - -QT_BEGIN_NAMESPACE - -// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs -// and no reordering. -// also computes logClusters heuristically -static void heuristicSetGlyphAttributes(const QChar *uc, int length, QGlyphLayout *glyphs, unsigned short *logClusters, int num_glyphs) -{ - // ### zeroWidth and justification are missing here!!!!! - - Q_UNUSED(num_glyphs); - -// qDebug("QScriptEngine::heuristicSetGlyphAttributes, num_glyphs=%d", item->num_glyphs); - - const bool symbolFont = false; // #### - glyphs->attributes[0].mark = false; - glyphs->attributes[0].clusterStart = true; - glyphs->attributes[0].dontPrint = (!symbolFont && uc[0].unicode() == 0x00ad) || qIsControlChar(uc[0].unicode()); - - int pos = 0; - int lastCat = QChar::category(uc[0].unicode()); - for (int i = 1; i < length; ++i) { - if (logClusters[i] == pos) - // same glyph - continue; - ++pos; - while (pos < logClusters[i]) { - ++pos; - } - // hide soft-hyphens by default - if ((!symbolFont && uc[i].unicode() == 0x00ad) || qIsControlChar(uc[i].unicode())) - glyphs->attributes[pos].dontPrint = true; - const QUnicodeTables::Properties *prop = QUnicodeTables::properties(uc[i].unicode()); - int cat = prop->category; - - // one gets an inter character justification point if the current char is not a non spacing mark. - // as then the current char belongs to the last one and one gets a space justification point - // after the space char. - if (lastCat == QChar::Separator_Space) - glyphs->attributes[pos-1].justification = HB_Space; - else if (cat != QChar::Mark_NonSpacing) - glyphs->attributes[pos-1].justification = HB_Character; - else - glyphs->attributes[pos-1].justification = HB_NoJustification; - - lastCat = cat; - } - pos = logClusters[length-1]; - if (lastCat == QChar::Separator_Space) - glyphs->attributes[pos].justification = HB_Space; - else - glyphs->attributes[pos].justification = HB_Character; -} - -struct QArabicProperties { - unsigned char shape; - unsigned char justification; -}; -Q_DECLARE_TYPEINFO(QArabicProperties, Q_PRIMITIVE_TYPE); - -enum QArabicShape { - XIsolated, - XFinal, - XInitial, - XMedial, - // intermediate state - XCausing -}; - - -// these groups correspond to the groups defined in the Unicode standard. -// Some of these groups are equal with regards to both joining and line breaking behaviour, -// and thus have the same enum value -// -// I'm not sure the mapping of syriac to arabic enums is correct with regards to justification, but as -// I couldn't find any better document I'll hope for the best. -enum ArabicGroup { - // NonJoining - ArabicNone, - ArabicSpace, - // Transparent - Transparent, - // Causing - Center, - Kashida, - - // Arabic - // Dual - Beh, - Noon, - Meem = Noon, - Heh = Noon, - KnottedHeh = Noon, - HehGoal = Noon, - SwashKaf = Noon, - Yeh, - Hah, - Seen, - Sad = Seen, - Tah, - Kaf = Tah, - Gaf = Tah, - Lam = Tah, - Ain, - Feh = Ain, - Qaf = Ain, - // Right - Alef, - Waw, - Dal, - TehMarbuta = Dal, - Reh, - HamzaOnHehGoal, - YehWithTail = HamzaOnHehGoal, - YehBarre = HamzaOnHehGoal, - - // Syriac - // Dual - Beth = Beh, - Gamal = Ain, - Heth = Noon, - Teth = Hah, - Yudh = Noon, - Kaph = Noon, - Lamadh = Lam, - Mim = Noon, - Nun = Noon, - Semakh = Noon, - FinalSemakh = Noon, - SyriacE = Ain, - Pe = Ain, - ReversedPe = Hah, - Qaph = Noon, - Shin = Noon, - Fe = Ain, - - // Right - Alaph = Alef, - Dalath = Dal, - He = Dal, - SyriacWaw = Waw, - Zain = Alef, - YudhHe = Waw, - Sadhe = HamzaOnHehGoal, - Taw = Dal, - - // Compiler bug? Otherwise ArabicGroupsEnd would be equal to Dal + 1. - Dummy = HamzaOnHehGoal, - ArabicGroupsEnd -}; - -static const unsigned char arabic_group[0x150] = { - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - ArabicNone, ArabicNone, Alef, Alef, - Waw, Alef, Yeh, Alef, - Beh, TehMarbuta, Beh, Beh, - Hah, Hah, Hah, Dal, - - Dal, Reh, Reh, Seen, - Seen, Sad, Sad, Tah, - Tah, Ain, Ain, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - // 0x640 - Kashida, Feh, Qaf, Kaf, - Lam, Meem, Noon, Heh, - Waw, Yeh, Yeh, Transparent, - Transparent, Transparent, Transparent, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, Beh, Qaf, - - Transparent, Alef, Alef, Alef, - ArabicNone, Alef, Waw, Waw, - Yeh, Beh, Beh, Beh, - Beh, Beh, Beh, Beh, - - // 0x680 - Beh, Hah, Hah, Hah, - Hah, Hah, Hah, Hah, - Dal, Dal, Dal, Dal, - Dal, Dal, Dal, Dal, - - Dal, Reh, Reh, Reh, - Reh, Reh, Reh, Reh, - Reh, Reh, Seen, Seen, - Seen, Sad, Sad, Tah, - - Ain, Feh, Feh, Feh, - Feh, Feh, Feh, Qaf, - Qaf, Gaf, SwashKaf, Gaf, - Kaf, Kaf, Kaf, Gaf, - - Gaf, Gaf, Gaf, Gaf, - Gaf, Lam, Lam, Lam, - Lam, Noon, Noon, Noon, - Noon, Noon, KnottedHeh, Hah, - - // 0x6c0 - TehMarbuta, HehGoal, HamzaOnHehGoal, HamzaOnHehGoal, - Waw, Waw, Waw, Waw, - Waw, Waw, Waw, Waw, - Yeh, YehWithTail, Yeh, Waw, - - Yeh, Yeh, YehBarre, YehBarre, - ArabicNone, TehMarbuta, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, ArabicNone, ArabicNone, Transparent, - Transparent, ArabicNone, Transparent, Transparent, - Transparent, Transparent, Dal, Reh, - - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, Seen, Sad, - Ain, ArabicNone, ArabicNone, KnottedHeh, - - // 0x700 - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - ArabicNone, ArabicNone, ArabicNone, ArabicNone, - - Alaph, Transparent, Beth, Gamal, - Gamal, Dalath, Dalath, He, - SyriacWaw, Zain, Heth, Teth, - Teth, Yudh, YudhHe, Kaph, - - Lamadh, Mim, Nun, Semakh, - FinalSemakh, SyriacE, Pe, ReversedPe, - Sadhe, Qaph, Dalath, Shin, - Taw, Beth, Gamal, Dalath, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, Transparent, - Transparent, Transparent, Transparent, ArabicNone, - ArabicNone, Zain, Kaph, Fe, -}; - -static inline ArabicGroup arabicGroup(unsigned short uc) -{ - if (uc >= 0x0600 && uc < 0x750) - return (ArabicGroup) arabic_group[uc-0x600]; - else if (uc == 0x200d) - return Center; - else if (QChar::category(uc) == QChar::Separator_Space) - return ArabicSpace; - else - return ArabicNone; -} - - -/* - Arabic shaping obeys a number of rules according to the joining classes (see Unicode book, section on - arabic). - - Each unicode char has a joining class (right, dual (left&right), center (joincausing) or transparent). - transparent joining is not encoded in QChar::joining(), but applies to all combining marks and format marks. - - Right join-causing: dual + center - Left join-causing: dual + right + center - - Rules are as follows (for a string already in visual order, as we have it here): - - R1 Transparent characters do not affect joining behaviour. - R2 A right joining character, that has a right join-causing char on the right will get form XRight - (R3 A left joining character, that has a left join-causing char on the left will get form XLeft) - Note: the above rule is meaningless, as there are no pure left joining characters defined in Unicode - R4 A dual joining character, that has a left join-causing char on the left and a right join-causing char on - the right will get form XMedial - R5 A dual joining character, that has a right join causing char on the right, and no left join causing char on the left - will get form XRight - R6 A dual joining character, that has a left join causing char on the left, and no right join causing char on the right - will get form XLeft - R7 Otherwise the character will get form XIsolated - - Additionally we have to do the minimal ligature support for lam-alef ligatures: - - L1 Transparent characters do not affect ligature behaviour. - L2 Any sequence of Alef(XRight) + Lam(XMedial) will form the ligature Alef.Lam(XLeft) - L3 Any sequence of Alef(XRight) + Lam(XLeft) will form the ligature Alef.Lam(XIsolated) - - The state table below handles rules R1-R7. -*/ - -enum Joining { - JNone, - JCausing, - JDual, - JRight, - JTransparent -}; - -static const Joining joining_for_group[ArabicGroupsEnd] = { - // NonJoining - JNone, // ArabicNone - JNone, // ArabicSpace - // Transparent - JTransparent, // Transparent - // Causing - JCausing, // Center - JCausing, // Kashida - // Dual - JDual, // Beh - JDual, // Noon - JDual, // Yeh - JDual, // Hah - JDual, // Seen - JDual, // Tah - JDual, // Ain - // Right - JRight, // Alef - JRight, // Waw - JRight, // Dal - JRight, // Reh - JRight // HamzaOnHehGoal -}; - - -struct JoiningPair { - QArabicShape form1; - QArabicShape form2; -}; - -static const JoiningPair joining_table[5][4] = -// None, Causing, Dual, Right -{ - { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XInitial }, { XIsolated, XIsolated } }, // XIsolated - { { XFinal, XIsolated }, { XFinal, XCausing }, { XFinal, XInitial }, { XFinal, XIsolated } }, // XFinal - { { XIsolated, XIsolated }, { XInitial, XCausing }, { XInitial, XMedial }, { XInitial, XFinal } }, // XInitial - { { XFinal, XIsolated }, { XMedial, XCausing }, { XMedial, XMedial }, { XMedial, XFinal } }, // XMedial - { { XIsolated, XIsolated }, { XIsolated, XCausing }, { XIsolated, XMedial }, { XIsolated, XFinal } }, // XCausing -}; - - -/* -According to http://www.microsoft.com/middleeast/Arabicdev/IE6/KBase.asp - -1. Find the priority of the connecting opportunities in each word -2. Add expansion at the highest priority connection opportunity -3. If more than one connection opportunity have the same highest value, - use the opportunity closest to the end of the word. - -Following is a chart that provides the priority for connection -opportunities and where expansion occurs. The character group names -are those in table 6.6 of the UNICODE 2.0 book. - - -PrioritY Glyph Condition Kashida Location - -Arabic_Kashida User inserted Kashida The user entered a Kashida in a position. After the user - (Shift+j or Shift+[E with hat]) Thus, it is the highest priority to insert an inserted kashida - automatic kashida. - -Arabic_Seen Seen, Sad Connecting to the next character. After the character. - (Initial or medial form). - -Arabic_HaaDal Teh Marbutah, Haa, Dal Connecting to previous character. Before the final form - of these characters. - -Arabic_Alef Alef, Tah, Lam, Connecting to previous character. Before the final form - Kaf and Gaf of these characters. - -Arabic_BaRa Reh, Yeh Connected to medial Beh Before preceding medial Baa - -Arabic_Waw Waw, Ain, Qaf, Feh Connecting to previous character. Before the final form of - these characters. - -Arabic_Normal Other connecting Connecting to previous character. Before the final form - characters of these characters. - - - -This seems to imply that we have at most one kashida point per arabic word. - -*/ - -void qt_getArabicProperties(const unsigned short *chars, int len, QArabicProperties *properties) -{ -// qDebug("arabicSyriacOpenTypeShape: properties:"); - int lastPos = 0; - int lastGroup = ArabicNone; - - ArabicGroup group = arabicGroup(chars[0]); - Joining j = joining_for_group[group]; - QArabicShape shape = joining_table[XIsolated][j].form2; - properties[0].justification = HB_NoJustification; - - for (int i = 1; i < len; ++i) { - // #### fix handling for spaces and punktuation - properties[i].justification = HB_NoJustification; - - group = arabicGroup(chars[i]); - j = joining_for_group[group]; - - if (j == JTransparent) { - properties[i].shape = XIsolated; - continue; - } - - properties[lastPos].shape = joining_table[shape][j].form1; - shape = joining_table[shape][j].form2; - - switch(lastGroup) { - case Seen: - if (properties[lastPos].shape == XInitial || properties[lastPos].shape == XMedial) - properties[i-1].justification = HB_Arabic_Seen; - break; - case Hah: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_HaaDal; - break; - case Alef: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_Alef; - break; - case Ain: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_Waw; - break; - case Noon: - if (properties[lastPos].shape == XFinal) - properties[lastPos-1].justification = HB_Arabic_Normal; - break; - case ArabicNone: - break; - - default: - Q_ASSERT(false); - } - - lastGroup = ArabicNone; - - switch(group) { - case ArabicNone: - case Transparent: - // ### Center should probably be treated as transparent when it comes to justification. - case Center: - break; - case ArabicSpace: - properties[i].justification = HB_Arabic_Space; - break; - case Kashida: - properties[i].justification = HB_Arabic_Kashida; - break; - case Seen: - lastGroup = Seen; - break; - - case Hah: - case Dal: - lastGroup = Hah; - break; - - case Alef: - case Tah: - lastGroup = Alef; - break; - - case Yeh: - case Reh: - if (properties[lastPos].shape == XMedial && arabicGroup(chars[lastPos]) == Beh) - properties[lastPos-1].justification = HB_Arabic_BaRa; - break; - - case Ain: - case Waw: - lastGroup = Ain; - break; - - case Noon: - case Beh: - case HamzaOnHehGoal: - lastGroup = Noon; - break; - case ArabicGroupsEnd: - Q_ASSERT(false); - } - - lastPos = i; - } - properties[lastPos].shape = joining_table[shape][JNone].form1; - - -// for (int i = 0; i < len; ++i) -// qDebug("arabic properties(%d): uc=%x shape=%d, justification=%d", i, chars[i], properties[i].shape, properties[i].justification); -} - -void QTextEngine::shapeTextMac(int item) const -{ - QScriptItem &si = layoutData->items[item]; - - si.glyph_data_offset = layoutData->used; - - QFontEngine *font = fontEngine(si, &si.ascent, &si.descent, &si.leading); - if (font->type() != QFontEngine::Multi) { - shapeTextWithHarfbuzz(item); - return; - } - -#ifndef QT_MAC_USE_COCOA - QFontEngineMacMulti *fe = static_cast<QFontEngineMacMulti *>(font); -#else - QCoreTextFontEngineMulti *fe = static_cast<QCoreTextFontEngineMulti *>(font); -#endif - QTextEngine::ShaperFlags flags; - if (si.analysis.bidiLevel % 2) - flags |= RightToLeft; - if (option.useDesignMetrics()) - flags |= DesignMetrics; - - attributes(); // pre-initialize char attributes - - const int len = length(item); - int num_glyphs = length(item); - const QChar *str = layoutData->string.unicode() + si.position; - ushort upperCased[256]; - if (si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) { - ushort *uc = upperCased; - if (len > 256) - uc = new ushort[len]; - for (int i = 0; i < len; ++i) { - if(si.analysis.flags == QScriptAnalysis::Lowercase) - uc[i] = str[i].toLower().unicode(); - else - uc[i] = str[i].toUpper().unicode(); - } - str = reinterpret_cast<const QChar *>(uc); - } - - ensureSpace(num_glyphs); - num_glyphs = layoutData->glyphLayout.numGlyphs - layoutData->used; - - QGlyphLayout g = availableGlyphs(&si); - g.numGlyphs = num_glyphs; - unsigned short *log_clusters = logClusters(&si); - - bool stringToCMapFailed = false; - if (!fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, attributes(), &si)) { - ensureSpace(num_glyphs); - g = availableGlyphs(&si); - stringToCMapFailed = !fe->stringToCMap(str, len, &g, &num_glyphs, flags, log_clusters, - attributes(), &si); - } - - if (!stringToCMapFailed) { - heuristicSetGlyphAttributes(str, len, &g, log_clusters, num_glyphs); - - si.num_glyphs = num_glyphs; - - layoutData->used += si.num_glyphs; - - QGlyphLayout g = shapedGlyphs(&si); - - if (si.analysis.script == QUnicodeTables::Arabic) { - QVarLengthArray<QArabicProperties> props(len + 2); - QArabicProperties *properties = props.data(); - int f = si.position; - int l = len; - if (f > 0) { - --f; - ++l; - ++properties; - } - if (f + l < layoutData->string.length()) { - ++l; - } - qt_getArabicProperties((const unsigned short *)(layoutData->string.unicode()+f), l, props.data()); - - unsigned short *log_clusters = logClusters(&si); - - for (int i = 0; i < len; ++i) { - int gpos = log_clusters[i]; - g.attributes[gpos].justification = properties[i].justification; - } - } - } - - const ushort *uc = reinterpret_cast<const ushort *>(str); - - if ((si.analysis.flags == QScriptAnalysis::SmallCaps || si.analysis.flags == QScriptAnalysis::Uppercase - || si.analysis.flags == QScriptAnalysis::Lowercase) - && uc != upperCased) - delete [] uc; -} - -QT_END_NAMESPACE diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index c476485c1d..bea39e55c5 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -644,7 +644,7 @@ private: int beginningOfLine(int lineNum); }; -class QStackTextEngine : public QTextEngine { +class Q_GUI_EXPORT QStackTextEngine : public QTextEngine { public: enum { MemSize = 256*40/sizeof(void *) }; QStackTextEngine(const QString &string, const QFont &f); diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp index 3513a280c6..0eb0673c69 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -43,7 +43,6 @@ #include <qbytearray.h> #include <qtextcodec.h> -#include <qapplication.h> #include <qstack.h> #include <qdebug.h> #include <qthread.h> @@ -1055,7 +1054,7 @@ void QTextHtmlParserNode::initializeProperties(const QTextHtmlParserNode *parent && !attributes.at(i + 1).isEmpty()) { hasHref = true; charFormat.setUnderlineStyle(QTextCharFormat::SingleUnderline); - charFormat.setForeground(QApplication::palette().link()); + charFormat.setForeground(Qt::blue); // ### Qt5: QApplication::palette().link()); } } @@ -1406,7 +1405,7 @@ void QTextHtmlParserNode::applyBackgroundImage(const QString &url, const QTextDo if (!url.isEmpty() && resourceProvider) { QVariant val = resourceProvider->resource(QTextDocument::ImageResource, url); - if (qApp->thread() != QThread::currentThread()) { + if (QCoreApplication::instance()->thread() != QThread::currentThread()) { // must use images in non-GUI threads if (val.type() == QVariant::Image) { QImage image = qvariant_cast<QImage>(val); diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp index bbff79cbc6..d04b758bc9 100644 --- a/src/gui/text/qtextimagehandler.cpp +++ b/src/gui/text/qtextimagehandler.cpp @@ -42,13 +42,12 @@ #include "qtextimagehandler_p.h" -#include <qapplication.h> +#include <qcoreapplication.h> #include <qtextformat.h> #include <qpainter.h> #include <qdebug.h> #include <private/qtextengine_p.h> #include <qpalette.h> -#include <qtextbrowser.h> #include <qthread.h> QT_BEGIN_NAMESPACE @@ -73,7 +72,8 @@ static QPixmap getPixmap(QTextDocument *doc, const QTextImageFormat &format) if (pm.isNull()) { QString context; -#ifndef QT_NO_TEXTBROWSER +#if 0 + // ### Qt5 QTextBrowser *browser = qobject_cast<QTextBrowser *>(doc->parent()); if (browser) context = browser->source().toString(); @@ -150,7 +150,9 @@ static QImage getImage(QTextDocument *doc, const QTextImageFormat &format) if (image.isNull()) { QString context; -#ifndef QT_NO_TEXTBROWSER + +#if 0 + // ### Qt5 QTextBrowser *browser = qobject_cast<QTextBrowser *>(doc->parent()); if (browser) context = browser->source().toString(); @@ -210,7 +212,7 @@ QSizeF QTextImageHandler::intrinsicSize(QTextDocument *doc, int posInDocument, c Q_UNUSED(posInDocument) const QTextImageFormat imageFormat = format.toImageFormat(); - if (qApp->thread() != QThread::currentThread()) + if (QCoreApplication::instance()->thread() != QThread::currentThread()) return getImageSize(doc, imageFormat); return getPixmapSize(doc, imageFormat); } @@ -220,7 +222,7 @@ void QTextImageHandler::drawObject(QPainter *p, const QRectF &rect, QTextDocumen Q_UNUSED(posInDocument) const QTextImageFormat imageFormat = format.toImageFormat(); - if (qApp->thread() != QThread::currentThread()) { + if (QCoreApplication::instance()->thread() != QThread::currentThread()) { const QImage image = getImage(doc, imageFormat); p->drawImage(rect, image, image.rect()); } else { diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 1280b4650b..271af7ae82 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -43,14 +43,12 @@ #include "qtextengine_p.h" #include <qfont.h> -#include <qapplication.h> #include <qpainter.h> #include <qvarlengtharray.h> #include <qtextformat.h> #include <qabstracttextdocumentlayout.h> #include "qtextdocument_p.h" #include "qtextformat_p.h" -#include "qstyleoption.h" #include "qpainterpath.h" #include "qglyphrun.h" #include "qglyphrun_p.h" diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp index 2b8e735305..b3358fa7b0 100644 --- a/src/gui/text/qtextoption.cpp +++ b/src/gui/text/qtextoption.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "qtextoption.h" -#include "qapplication.h" +#include "qguiapplication.h" #include "qlist.h" QT_BEGIN_NAMESPACE @@ -82,7 +82,7 @@ QTextOption::QTextOption(Qt::Alignment alignment) tab(-1), d(0) { - direction = QApplication::layoutDirection(); + direction = QGuiApplication::layoutDirection(); } /*! diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index b6cdc52e10..6357dec1d2 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -9,9 +9,7 @@ HEADERS += \ text/qfontmetrics.h \ text/qfont_p.h \ text/qfontsubset_p.h \ - text/qtextcontrol_p.h \ - text/qtextcontrol_p_p.h \ - text/qtextengine_p.h \ + text/qtextengine_p.h \ text/qtextlayout.h \ text/qtextformat.h \ text/qtextformat_p.h \ @@ -51,8 +49,7 @@ SOURCES += \ text/qfontsubset.cpp \ text/qfontmetrics.cpp \ text/qfontdatabase.cpp \ - text/qtextcontrol.cpp \ - text/qtextengine.cpp \ + text/qtextengine.cpp \ text/qtextlayout.cpp \ text/qtextformat.cpp \ text/qtextobject.cpp \ @@ -103,7 +100,7 @@ unix:x11 { text/qrawfont_ft.cpp } -!embedded:!qpa:!x11:mac { +!qpa:!x11:mac { HEADERS += \ text/qfontengine_mac_p.h OBJECTIVE_HEADERS += \ @@ -119,22 +116,6 @@ unix:x11 { } } -embedded { - SOURCES += \ - text/qfont_qws.cpp \ - text/qfontengine_qws.cpp \ - text/qfontengine_ft.cpp \ - text/qfontengine_qpf.cpp \ - text/qabstractfontengine_qws.cpp \ - text/qrawfont_ft.cpp - HEADERS += \ - text/qfontengine_ft_p.h \ - text/qfontengine_qpf_p.h \ - text/qabstractfontengine_qws.h \ - text/qabstractfontengine_p.h - DEFINES += QT_NO_FONTCONFIG -} - qpa { SOURCES += \ text/qfont_qpa.cpp \ @@ -232,9 +213,7 @@ contains(QT_CONFIG, freetype) { DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB - embedded:CONFIG += opentype } else:contains(QT_CONFIG, system-freetype) { - embedded:CONFIG += opentype # pull in the proper freetype2 include directory include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) LIBS_PRIVATE += -lfreetype |