diff options
Diffstat (limited to 'src/gui/text')
66 files changed, 2504 insertions, 17170 deletions
diff --git a/src/gui/text/qabstractfontengine_qws.cpp b/src/gui/text/qabstractfontengine_qws.cpp deleted file mode 100644 index b2c9cc478a..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 4c85a0a063..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h index 12f3ed1217..8e792e9b80 100644 --- a/src/gui/text/qabstracttextdocumentlayout.h +++ b/src/gui/text/qabstracttextdocumentlayout.h @@ -122,6 +122,7 @@ protected: QTextCharFormat format(int pos); private: + friend class QWidgetTextControl; friend class QTextControl; friend class QTextDocument; friend class QTextDocumentPrivate; diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp index 028011bfe8..6a28ff2d74 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 9c974f773a..4fa8bb0540 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 @@ -416,7 +416,7 @@ struct BorderData { // 4. QVector<Declaration> - { prop1: value1; prop2: value2; } // 5. Declaration - prop1: value1; -struct Q_AUTOTEST_EXPORT Declaration +struct Q_GUI_EXPORT Declaration { struct DeclarationData : public QSharedData { @@ -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; }; @@ -552,7 +552,7 @@ struct BasicSelector Relation relationToNext; }; -struct Q_AUTOTEST_EXPORT Selector +struct Q_GUI_EXPORT Selector { QVector<BasicSelector> basicSelectors; int specificity() const; @@ -565,7 +565,7 @@ struct MediaRule; struct PageRule; struct ImportRule; -struct Q_AUTOTEST_EXPORT ValueExtractor +struct Q_GUI_EXPORT ValueExtractor { ValueExtractor(const QVector<Declaration> &declarations, const QPalette & = QPalette()); @@ -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 @@ -739,7 +739,7 @@ struct Q_GUI_EXPORT Symbol QString lexem() const; }; -class Q_AUTOTEST_EXPORT Scanner +class Q_GUI_EXPORT Scanner { public: static QString preprocess(const QString &input, bool *hasEscapeSequences = 0); diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index cf97310ea3..e8308dba06 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -48,8 +48,9 @@ #include "qpainter.h" #include "qhash.h" #include "qdatastream.h" -#include "qapplication.h" +#include "qguiapplication.h" #include "qstringlist.h" +#include "qscreen.h" #include "qthread.h" #include "qthreadstorage.h" @@ -65,19 +66,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 <QtCore/QMutexLocker> @@ -173,20 +167,11 @@ 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(); - if (pi) { - QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + QScreen *screen = QGuiApplication::primaryScreen(); + if (screen) { const QSize screenSize = screen->geometry().size(); - const QSize physicalSize = screen->physicalSize(); + const QSize physicalSize = screen->handle()->physicalSize(); dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4))); } else { //PI has not been initialised, or it is being initialised. Give a default dpi @@ -212,20 +197,11 @@ 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(); - if (pi) { - QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + QScreen *screen = QGuiApplication::primaryScreen(); + if (screen) { const QSize screenSize = screen->geometry().size(); - const QSize physicalSize = screen->physicalSize(); + const QSize physicalSize = screen->handle()->physicalSize(); dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4))); } else { //PI has not been initialised, or it is being initialised. Give a default dpi @@ -453,9 +429,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 @@ -786,10 +762,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) { } @@ -809,7 +785,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) @@ -1133,18 +1109,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 @@ -1912,43 +1876,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 14f290ceb3..1035b665a3 100644 --- a/src/gui/text/qfont.h +++ b/src/gui/text/qfont.h @@ -287,14 +287,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 3bbff7f4bb..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 3e0a24636c..e151a389cd 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 3674e178ea..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 e0f4bad527..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 7a0f234ca6..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 e89e0d9dc2..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 6202fbac52..fa67dc1a8a 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; @@ -262,7 +262,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); } @@ -296,10 +296,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; } @@ -755,7 +755,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) @@ -1520,21 +1520,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(); } @@ -2026,7 +2026,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]; @@ -2040,7 +2040,7 @@ QFont QFontDatabase::font(const QString &family, const QString &style, QtFontStyle *s = bestStyle(&allStyles, styleKey, style); 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); @@ -2363,7 +2363,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 b1f370e6d1..994a7a4a7d 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 6876fae630..0000000000 --- a/src/gui/text/qfontdatabase_mac.cpp +++ /dev/null @@ -1,494 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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); - QCFString style_name = (CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute); - 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; - QString styleName = style_name; - 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, styleName, 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, QString(), 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; -} - -static QFontEngine *loadFromDatabase(const QFontDef &req, const QFontPrivate *d) -{ -#if defined(QT_MAC_USE_COCOA) - QCFString fontName = NULL; -#else - ATSFontFamilyRef familyRef = 0; - ATSFontRef fontRef = 0; -#endif - - 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(); - - 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); - goto found; - } -#else - familyRef = ATSFontFamilyFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); - if (familyRef) { - fontRef = ATSFontFindFromName(QCFString(db->families[k]->name), kATSOptionFlagsDefault); - goto found; - } -#endif - } - } - } -found: -#ifdef QT_MAC_USE_COCOA - if (fontName) - return new QCoreTextFontEngineMulti(fontName, req, d->kerning); -#else - if (familyRef) { - QCFString actualName; - if (ATSFontFamilyGetName(familyRef, kATSOptionFlagsDefault, &actualName) == noErr) - req.family = actualName; - return new QFontEngineMacMulti(familyRef, req, fontDef, d->kerning); - } -#endif - return NULL; -} - -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 = 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 - } - - QFontEngine *engine = NULL; -#if defined(QT_MAC_USE_COCOA) - // Shortcut to get the font directly without going through the font database - if (!req.family.isEmpty() && !req.styleName.isEmpty()) { - QCFString expectedFamily = QCFString(req.family); - QCFString expectedStyle = QCFString(req.styleName); - - QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(NULL, 0, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, expectedFamily); - CFDictionaryAddValue(attributes, kCTFontStyleNameAttribute, expectedStyle); - - QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes); - CGAffineTransform transform = qt_transform_from_fontdef(req); - QCFType<CTFontRef> ctFont = CTFontCreateWithFontDescriptor(descriptor, req.pixelSize, &transform); - if (ctFont) { - QCFString familyName = CTFontCopyFamilyName(ctFont); - // Only accept the font if the family name is exactly the same as we specified - if (CFEqual(expectedFamily, familyName)) { - engine = new QCoreTextFontEngineMulti(ctFont, req, d->kerning); - } - } - } -#endif - if (!engine) - engine = loadFromDatabase(req, d); - - if (engine) { - d->engineData->engine = engine; - engine->ref.ref(); - 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 032a42b9b1..c0edce1009 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); @@ -173,7 +156,7 @@ QFontEngine *loadEngine(int script, const QFontDef &request, QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size); //make sure that the db has all fallback families - if (engine + if (engine && engine->type() != QFontEngine::Multi && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) { if (family && !family->askedForFallback) { @@ -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; } @@ -359,7 +342,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 c83e9297d9..0000000000 --- a/src/gui/text/qfontdatabase_qws.cpp +++ /dev/null @@ -1,972 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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; -} - -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 cfa405dbc1..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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, QString(), 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 788eb307c3..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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, QString(), 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, QString(), 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, QString(), 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, QString(), 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 922a97f3aa..0000000000 --- a/src/gui/text/qfontdatabase_x11.cpp +++ /dev/null @@ -1,2154 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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, QString(), 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; - FcChar8 *style_value; - FcBool scalable; - - { - FcObjectSet *os = FcObjectSetCreate(); - FcPattern *pattern = FcPatternCreate(); - const char *properties [] = { - FC_FAMILY, FC_STYLE, 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; - if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch) - style_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; - QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); - 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, styleName, 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, QString(), 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, QString(), 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) -{ - double size_value = qMax(qreal(1.), request.pixelSize); - FcPatternDel(pattern, FC_PIXEL_SIZE); - FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value); - - 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); - } - - if (!request.styleName.isEmpty()) { - QByteArray cs = request.styleName.toUtf8(); - FcPatternAddString(pattern, FC_STYLE, (const FcChar8 *) cs.constData()); - return; - } - - 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); - - int stretch = request.stretch; - if (!stretch) - stretch = 100; - FcPatternDel(pattern, FC_WIDTH); - FcPatternAddInteger(pattern, FC_WIDTH, stretch); -} - -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); - - FcConfigSubstitute(0, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - - // 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 *match, int screen, - const QFontDef &request, int script) -{ -#ifdef FONT_MATCH_DEBUG - FcChar8 *fam; - FcPatternGetString(match, FC_FAMILY, 0, &fam); - FM_DEBUG("==== trying %s\n", fam); -#endif - FM_DEBUG("passes charset test\n"); - - QFontEngineX11FT *engine = 0; - if (!match) // probably no fonts available. - goto done; - - 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: - 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; - FcResult res; - FcPattern *match = FcFontMatch(0, pattern, &res); - fe = tryPatternLoad(match, fp->screen, request, script); - if (!fe) { - FcFontSet *fs = qt_fontSetForPattern(pattern, request); - - if (match) { - FcPatternDestroy(match); - match = 0; - } - - if (fs) { - for (int i = 0; !fe && i < fs->nfont; ++i) { - match = FcFontRenderPrepare(NULL, pattern, fs->fonts[i]); - fe = tryPatternLoad(match, fp->screen, request, script); - if (fe) - break; - FcPatternDestroy(match); - match = 0; - } - 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, match, pattern, fp->screen, request); - } else { - FcPatternDestroy(pattern); - if (match) - FcPatternDestroy(match); - } - 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); -} - -// Needed for fontconfig version < 2.2.97 -#ifndef FC_FAMILYLANG -#define FC_FAMILYLANG "familylang" -#endif - -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); - QByteArray cs = fnt->fileName.toUtf8(); - FcPatternAddString(pattern, FC_FILE, (const FcChar8 *) cs.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; - - QByteArray cs = family.toUtf8(); - FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData()); - 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.cpp b/src/gui/text/qfontengine.cpp index a258b72708..9d42d8ab69 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -1681,11 +1681,42 @@ bool QFontEngineMulti::canRender(const QChar *string, int len) return allExist; } -QImage QFontEngineMulti::alphaMapForGlyph(glyph_t) +/* Implement alphaMapForGlyph() which is called by Lighthouse/Windows code. + * Ideally, that code should be fixed to correctly handle QFontEngineMulti. */ + +QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph) +{ + const int which = highByte(glyph); + Q_ASSERT(which < engines.size()); + return engine(which)->alphaMapForGlyph(stripped(glyph)); +} + +QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) +{ + const int which = highByte(glyph); + Q_ASSERT(which < engines.size()); + return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition); +} + +QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, const QTransform &t) { - Q_ASSERT(false); - return QImage(); + const int which = highByte(glyph); + Q_ASSERT(which < engines.size()); + return engine(which)->alphaMapForGlyph(stripped(glyph), t); } +QImage QFontEngineMulti::alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) +{ + const int which = highByte(glyph); + Q_ASSERT(which < engines.size()); + return engine(which)->alphaMapForGlyph(stripped(glyph), subPixelPosition, t); +} + +QImage QFontEngineMulti::alphaRGBMapForGlyph(glyph_t glyph, QFixed subPixelPosition, int margin, const QTransform &t) +{ + const int which = highByte(glyph); + Q_ASSERT(which < engines.size()); + return engine(which)->alphaRGBMapForGlyph(stripped(glyph), subPixelPosition, margin, t); +} QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_coretext.mm b/src/gui/text/qfontengine_coretext.mm deleted file mode 100644 index 9943229787..0000000000 --- a/src/gui/text/qfontengine_coretext.mm +++ /dev/null @@ -1,870 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 = NULL; - // There is a side effect in Core Text: if we apply 0 as symbolic traits to a font in normal weight, - // we will get the light version of that font (while the way supposed to work doesn't: - // setting kCTFontWeightTrait to some value between -1.0 to 0.0 has no effect on font selection) - if (fontDef.weight != QFont::Normal || symbolicTraits) - 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(CTFontRef ctFontRef, const QFontDef &fontDef, bool kerning) - : QFontEngineMulti(0) -{ - this->fontDef = fontDef; - ctfont = (CTFontRef) CFRetain(ctFontRef); - 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); - fontDef.family = fe->fontDef.family; - fontDef.styleName = fe->fontDef.styleName; - transform = fe->transform; - 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 - -CGAffineTransform qt_transform_from_fontdef(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 = qt_transform_from_fontdef(fontDef); - ctfont = font; - CFRetain(ctfont); - cgFont = CTFontCopyGraphicsFont(font, NULL); - init(); -} - -QCoreTextFontEngine::QCoreTextFontEngine(CGFontRef font, const QFontDef &def) -{ - fontDef = def; - transform = qt_transform_from_fontdef(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; - - QCFString styleName = (CFStringRef) CTFontCopyAttribute(ctfont, kCTFontStyleNameAttribute); - fontDef.styleName = styleName; - - 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(); -} - -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 0; -} - -qreal QCoreTextFontEngine::minLeftBearing() const -{ - return 0; -} - -qreal QCoreTextFontEngine::minRightBearing() const -{ - return 0; -} - -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.truncate() + subPixelPosition.toReal(); - qreal pos_y = im.height() + br.y.toReal(); - 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 d8a3033be6..0000000000 --- a/src/gui/text/qfontengine_coretext_p.h +++ /dev/null @@ -1,153 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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) - -QT_BEGIN_HEADER - -QT_BEGIN_NAMESPACE - -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; - friend class QCoreTextFontEngineMulti; -}; - -class QCoreTextFontEngineMulti : public QFontEngineMulti -{ -public: - QCoreTextFontEngineMulti(const QCFString &name, const QFontDef &fontDef, bool kerning); - QCoreTextFontEngineMulti(CTFontRef ctFontRef, 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; -}; - -CGAffineTransform qt_transform_from_fontdef(const QFontDef &fontDef); - -QT_END_NAMESPACE - -QT_END_HEADER - -#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_ft_p.h b/src/gui/text/qfontengine_ft_p.h index bd8e24a3fe..e320be4421 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -51,7 +51,7 @@ // We mean it. // -#include "qfontengine_p.h" +#include "private/qfontengine_p.h" #ifndef QT_NO_FREETYPE diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm deleted file mode 100644 index 9d9eaed058..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 10561e54d6..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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_p.h b/src/gui/text/qfontengine_p.h index 5f779e155a..b32e6916f0 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -394,7 +394,7 @@ private: int _size; }; -class QFontEngineMulti : public QFontEngine +class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine { public: explicit QFontEngineMulti(int engineCount); @@ -417,6 +417,10 @@ public: virtual QFixed xHeight() const; virtual QFixed averageCharWidth() const; virtual QImage alphaMapForGlyph(glyph_t); + virtual QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition); + virtual QImage alphaMapForGlyph(glyph_t, const QTransform &t); + virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); + virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, int margin, const QTransform &t); virtual QFixed lineThickness() const; virtual QFixed underlinePosition() const; diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp index cb1e7d6830..6fd85150e3 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> @@ -667,9 +666,11 @@ QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QSt : QFontEngineMulti(fallbacks.size() + 1), fallbackFamilies(fallbacks), script(_script) { + Q_ASSERT(fe && fe->type() != QFontEngine::Multi); engines[0] = fe; fe->ref.ref(); fontDef = engines[0]->fontDef; + setObjectName(QStringLiteral("QFontEngineMultiQPA")); } void QFontEngineMultiQPA::loadEngine(int at) diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp deleted file mode 100644 index 4c6dff241d..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 2bcee0157c..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 c4fa9d16fe..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 aef2145e5e..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 ebcafffceb..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 490866c9fe..0000000000 --- a/src/gui/text/qfontengine_x11.cpp +++ /dev/null @@ -1,1205 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 *match, const QFontDef &request, int screen) -{ - 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), fontSet(0), screen(s) -{ - firstEnginePattern = FcPatternDuplicate(matchedPattern); - 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 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 *match = FcFontRenderPrepare(NULL, pattern, fontSet->fonts[at + firstFontIndex - 1]); - QFontDef fontDef = qt_FcPatternToQFontDef(match, 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) { - fontEngine = engineForPattern(match, request, screen); - QFontCache::instance()->insertEngine(key, fontEngine); - } - FcPatternDestroy(match); - 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)) - return; - - if (!freetype->charset) { - FcCharSet *cs; - FcPatternGetCharSet (pattern, FC_CHARSET, 0, &cs); - freetype->charset = FcCharSetCopy(cs); - } -} - -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 { -#ifndef QT_NO_XRENDER - fe->xglyph_format = xglyph_format; -#endif - 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 1c0bcada11..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 a23bb34e0d..f21e820556 100644 --- a/src/gui/text/qfontmetrics.h +++ b/src/gui/text/qfontmetrics.h @@ -120,15 +120,6 @@ public: bool operator==(const QFontMetrics &other) const; 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/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp index ccb1f247da..dc2a14a52a 100644 --- a/src/gui/text/qfontsubset.cpp +++ b/src/gui/text/qfontsubset.cpp @@ -57,8 +57,6 @@ #include FT_FREETYPE_H #endif -#ifndef QT_NO_PRINTER - QT_BEGIN_NAMESPACE static const char * const agl = @@ -1493,251 +1491,4 @@ QByteArray QFontSubset::toTruetype() const return bindFont(tables); } -// ------------------ Type 1 generation --------------------------- - -// needs at least 6 bytes of space in tmp -static const char *encodeNumber(int num, char *tmp) -{ - const char *ret = tmp; - if(num >= -107 && num <= 107) { - QPdf::toHex((uchar)(num + 139), tmp); - tmp += 2; - } else if (num > 107 && num <= 1131) { - num -= 108; - QPdf::toHex((uchar)((num >> 8) + 247), tmp); - tmp += 2; - QPdf::toHex((uchar)(num & 0xff), tmp); - tmp += 2; - } else if(num < - 107 && num >= -1131) { - num += 108; - num = -num; - QPdf::toHex((uchar)((num >> 8) + 251), tmp); - tmp += 2; - QPdf::toHex((uchar)(num & 0xff), tmp); - tmp += 2; - } else { - *tmp++ = 'f'; - *tmp++ = 'f'; - QPdf::toHex((uchar)(num >> 24), tmp); - tmp += 2; - QPdf::toHex((uchar)(num >> 16), tmp); - tmp += 2; - QPdf::toHex((uchar)(num >> 8), tmp); - tmp += 2; - QPdf::toHex((uchar)(num >> 0), tmp); - tmp += 2; - } - *tmp = 0; -// qDebug("encodeNumber: %d -> '%s'", num, ret); - return ret; -} - -static QByteArray charString(const QPainterPath &path, qreal advance, qreal lsb, qreal ppem) -{ - // the charstring commands we need - const char *hsbw = "0D"; - const char *closepath = "09"; - const char *moveto[3] = { "16", "04", "15" }; - const char *lineto[3] = { "06", "07", "05" }; - const char *rcurveto = "08"; - const char *endchar = "0E"; - - enum { horizontal = 1, vertical = 2 }; - - char tmp[16]; - - qreal factor = 1000./ppem; - - int lsb_i = qRound(lsb*factor); - int advance_i = qRound(advance*factor); -// qDebug("--- charstring"); - - // first of all add lsb and width to the charstring using the hsbw command - QByteArray charstring; - charstring += encodeNumber(lsb_i, tmp); - charstring += encodeNumber(advance_i, tmp); - charstring += hsbw; - - // add the path - int xl = lsb_i; - int yl = 0; - bool openpath = false; - for (int i = 0; i < path.elementCount(); ++i) { - const QPainterPath::Element &elm = path.elementAt(i); - int x = qRound(elm.x*factor); - int y = -qRound(elm.y*factor); - int dx = x - xl; - int dy = y - yl; - if (elm.type == QPainterPath::MoveToElement && openpath) { -// qDebug("closepath %s", closepath); - charstring += closepath; - } - if (elm.type == QPainterPath::MoveToElement || - elm.type == QPainterPath::LineToElement) { - int type = -1; - if (dx || !dy) { - charstring += encodeNumber(dx, tmp); - type += horizontal; -// qDebug("horizontal"); - } - if (dy) { - charstring += encodeNumber(dy, tmp); - type += vertical; -// qDebug("vertical"); - } -// qDebug("moveto/lineto %s", (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type])); - charstring += (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type]); - openpath = true; - xl = x; - yl = y; - } else { - Q_ASSERT(elm.type == QPainterPath::CurveToElement); - const QPainterPath::Element &elm2 = path.elementAt(++i); - const QPainterPath::Element &elm3 = path.elementAt(++i); - int x2 = qRound(elm2.x*factor); - int y2 = -qRound(elm2.y*factor); - int x3 = qRound(elm3.x*factor); - int y3 = -qRound(elm3.y*factor); - charstring += encodeNumber(dx, tmp); - charstring += encodeNumber(dy, tmp); - charstring += encodeNumber(x2 - x, tmp); - charstring += encodeNumber(y2 - y, tmp); - charstring += encodeNumber(x3 - x2, tmp); - charstring += encodeNumber(y3 - y2, tmp); - charstring += rcurveto; - openpath = true; - xl = x3; - yl = y3; -// qDebug("rcurveto"); - } - } - if (openpath) - charstring += closepath; - charstring += endchar; - if (charstring.length() > 240) { - int pos = 240; - while (pos < charstring.length()) { - charstring.insert(pos, '\n'); - pos += 241; - } - } - return charstring; -} - -#ifndef QT_NO_FREETYPE -static const char *helvetica_styles[4] = { - "Helvetica", - "Helvetica-Bold", - "Helvetica-Oblique", - "Helvetica-BoldOblique" -}; -static const char *times_styles[4] = { - "Times-Regular", - "Times-Bold", - "Times-Italic", - "Times-BoldItalic" -}; -static const char *courier_styles[4] = { - "Courier", - "Courier-Bold", - "Courier-Oblique", - "Courier-BoldOblique" -}; -#endif - -QByteArray QFontSubset::toType1() const -{ - QFontEngine::Properties properties = fontEngine->properties(); - QVector<int> reverseMap = getReverseMap(); - - QByteArray font; - QPdf::ByteStream s(&font); - - QByteArray id = QByteArray::number(object_id); - QByteArray psname = properties.postscriptName; - psname.replace(' ', ""); - - standard_font = false; - -#ifndef QT_NO_FREETYPE - FT_Face face = ft_face(fontEngine); - if (face && !FT_IS_SCALABLE(face)) { - int style = 0; - if (fontEngine->fontDef.style) - style += 2; - if (fontEngine->fontDef.weight >= QFont::Bold) - style++; - if (fontEngine->fontDef.family.contains(QLatin1String("Helvetica"))) { - psname = helvetica_styles[style]; - standard_font = true; - } else if (fontEngine->fontDef.family.contains(QLatin1String("Times"))) { - psname = times_styles[style]; - standard_font = true; - } else if (fontEngine->fontDef.family.contains(QLatin1String("Courier"))) { - psname = courier_styles[style]; - standard_font = true; - } - } -#endif - s << "/F" << id << "-Base\n"; - if (standard_font) { - s << '/' << psname << " findfont\n" - "0 dict copy dup /NumGlyphs 0 put dup /CMap 256 array put def\n"; - } else { - s << "<<\n"; - if(!psname.isEmpty()) - s << "/FontName /" << psname << '\n'; - s << "/FontInfo <</FsType " << (int)fontEngine->fsType << ">>\n" - "/FontType 1\n" - "/PaintType 0\n" - "/FontMatrix [.001 0 0 .001 0 0]\n" - "/FontBBox { 0 0 0 0 }\n" - "/Private <<\n" - "/password 5839\n" - "/MinFeature {16 16}\n" - "/BlueValues []\n" - "/lenIV -1\n" - ">>\n" - "/CharStrings << >>\n" - "/NumGlyphs 0\n" - "/CMap 256 array\n" - ">> def\n"; - } - s << type1AddedGlyphs(); - downloaded_glyphs = glyph_indices.size(); - - return font; -} - -QByteArray QFontSubset::type1AddedGlyphs() const -{ - if (downloaded_glyphs == glyph_indices.size()) - return QByteArray(); - - QFontEngine::Properties properties = fontEngine->properties(); - QVector<int> reverseMap = getReverseMap(); - QByteArray glyphs; - QPdf::ByteStream s(&glyphs); - - int nGlyphs = glyph_indices.size(); - QByteArray id = QByteArray::number(object_id); - - s << 'F' << id << "-Base [\n"; - for (int i = downloaded_glyphs; i < nGlyphs; ++i) { - glyph_t g = glyph_indices.at(i); - QPainterPath path; - glyph_metrics_t metric; - fontEngine->getUnscaledGlyph(g, &path, &metric); - QByteArray charstring = charString(path, metric.xoff.toReal(), metric.x.toReal(), - properties.emSquare.toReal()); - s << glyphName(i, reverseMap); - if (!standard_font) - s << "\n<" << charstring << ">\n"; - } - s << (standard_font ? "] T1AddMapping\n" : "] T1AddGlyphs\n"); - return glyphs; -} - QT_END_NAMESPACE - -#endif // QT_NO_PRINTER diff --git a/src/gui/text/qfontsubset_p.h b/src/gui/text/qfontsubset_p.h index 7b9b47486c..a99236f4cc 100644 --- a/src/gui/text/qfontsubset_p.h +++ b/src/gui/text/qfontsubset_p.h @@ -55,8 +55,6 @@ #include "private/qfontengine_p.h" -#ifndef QT_NO_PRINTER - QT_BEGIN_NAMESPACE class QFontSubset @@ -71,8 +69,6 @@ public: } QByteArray toTruetype() const; - QByteArray toType1() const; - QByteArray type1AddedGlyphs() const; QByteArray widthArray() const; QByteArray createToUnicodeMap() const; QVector<int> getReverseMap() const; @@ -94,6 +90,4 @@ public: QT_END_NAMESPACE -#endif // QT_NO_PRINTER - #endif // QFONTSUBSET_P_H diff --git a/src/gui/text/qlinecontrol.cpp b/src/gui/text/qlinecontrol.cpp new file mode 100644 index 0000000000..36c064ee40 --- /dev/null +++ b/src/gui/text/qlinecontrol.cpp @@ -0,0 +1,1711 @@ +/**************************************************************************** +** +** 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// ### +#define QT_NO_ACCESSIBILITY +#define QT_NO_IM + +#include "qlinecontrol_p.h" + +#ifndef QT_NO_LINEEDIT + +#include "qclipboard.h" +#ifndef QT_NO_ACCESSIBILITY +#include "qaccessible.h" +#endif +#ifndef QT_NO_IM +#include "qinputcontext.h" +#include "qlist.h" +#endif +#include "qguiapplication.h" + +QT_BEGIN_NAMESPACE + +// ### these should come from the application +const int startDragDistance = 10; +const int cursorFlashTime = 2000; +const int textCursorWidth = 1; +const bool fullWidthSelection = true; + +/*! + \internal + + Updates the display text based of the current edit text + If the text has changed will emit displayTextChanged() +*/ +void QLineControl::updateDisplayText(bool forceUpdate) +{ + QString orig = m_textLayout.text(); + QString str; + if (m_echoMode == NoEcho) + str = QString::fromLatin1(""); + else + str = m_text; + + if (m_echoMode == Password || (m_echoMode == PasswordEchoOnEdit + && !m_passwordEchoEditing)) + str.fill(m_passwordCharacter); + + // replace certain non-printable characters with spaces (to avoid + // drawing boxes when using fonts that don't have glyphs for such + // characters) + QChar* uc = str.data(); + for (int i = 0; i < (int)str.length(); ++i) { + if ((uc[i] < 0x20 && uc[i] != 0x09) + || uc[i] == QChar::LineSeparator + || uc[i] == QChar::ParagraphSeparator + || uc[i] == QChar::ObjectReplacementCharacter) + uc[i] = QChar(0x0020); + } + + m_textLayout.setText(str); + + QTextOption option; + option.setTextDirection(m_layoutDirection); + option.setFlags(QTextOption::IncludeTrailingSpaces); + m_textLayout.setTextOption(option); + + m_textLayout.beginLayout(); + QTextLine l = m_textLayout.createLine(); + m_textLayout.endLayout(); + m_ascent = qRound(l.ascent()); + + if (str != orig || forceUpdate) + emit displayTextChanged(str); +} + +#ifndef QT_NO_CLIPBOARD +/*! + \internal + + Copies the currently selected text into the clipboard using the given + \a mode. + + \note If the echo mode is set to a mode other than Normal then copy + will not work. This is to prevent using copy as a method of bypassing + password features of the line control. +*/ +void QLineControl::copy(QClipboard::Mode mode) const +{ + QString t = selectedText(); + if (!t.isEmpty() && m_echoMode == Normal) { + disconnect(QGuiApplication::clipboard(), SIGNAL(selectionChanged()), this, 0); + QGuiApplication::clipboard()->setText(t, mode); + connect(QGuiApplication::clipboard(), SIGNAL(selectionChanged()), + this, SLOT(_q_clipboardChanged())); + } +} + +/*! + \internal + + Inserts the text stored in the application clipboard into the line + control. + + \sa insert() +*/ +void QLineControl::paste(QClipboard::Mode clipboardMode) +{ + QString clip = QGuiApplication::clipboard()->text(clipboardMode); + if (!clip.isEmpty() || hasSelectedText()) { + separate(); //make it a separate undo/redo command + insert(clip); + separate(); + } +} + +#endif // !QT_NO_CLIPBOARD + +/*! + \internal + + Handles the behavior for the backspace key or function. + Removes the current selection if there is a selection, otherwise + removes the character prior to the cursor position. + + \sa del() +*/ +void QLineControl::backspace() +{ + int priorState = m_undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else if (m_cursor) { + --m_cursor; + if (m_maskData) + m_cursor = prevMaskBlank(m_cursor); + QChar uc = m_text.at(m_cursor); + if (m_cursor > 0 && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) { + // second half of a surrogate, check if we have the first half as well, + // if yes delete both at once + uc = m_text.at(m_cursor - 1); + if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) { + internalDelete(true); + --m_cursor; + } + } + internalDelete(true); + } + finishChange(priorState); +} + +/*! + \internal + + Handles the behavior for the delete key or function. + Removes the current selection if there is a selection, otherwise + removes the character after the cursor position. + + \sa del() +*/ +void QLineControl::del() +{ + int priorState = m_undoState; + if (hasSelectedText()) { + removeSelectedText(); + } else { + int n = m_textLayout.nextCursorPosition(m_cursor) - m_cursor; + while (n--) + internalDelete(); + } + finishChange(priorState); +} + +/*! + \internal + + Inserts the given \a newText at the current cursor position. + If there is any selected text it is removed prior to insertion of + the new text. +*/ +void QLineControl::insert(const QString &newText) +{ + int priorState = m_undoState; + removeSelectedText(); + internalInsert(newText); + finishChange(priorState); +} + +/*! + \internal + + Clears the line control text. +*/ +void QLineControl::clear() +{ + int priorState = m_undoState; + m_selstart = 0; + m_selend = m_text.length(); + removeSelectedText(); + separate(); + finishChange(priorState, /*update*/false, /*edited*/false); +} + +/*! + \internal + + Sets \a length characters from the given \a start position as selected. + The given \a start position must be within the current text for + the line control. If \a length characters cannot be selected, then + the selection will extend to the end of the current text. +*/ +void QLineControl::setSelection(int start, int length) +{ + if(start < 0 || start > (int)m_text.length()){ + qWarning("QLineControl::setSelection: Invalid start position"); + return; + } + + if (length > 0) { + if (start == m_selstart && start + length == m_selend) + return; + m_selstart = start; + m_selend = qMin(start + length, (int)m_text.length()); + m_cursor = m_selend; + } else if (length < 0){ + if (start == m_selend && start + length == m_selstart) + return; + m_selstart = qMax(start + length, 0); + m_selend = start; + m_cursor = m_selstart; + } else if (m_selstart != m_selend) { + m_selstart = 0; + m_selend = 0; + m_cursor = start; + } else { + m_cursor = start; + emitCursorPositionChanged(); + return; + } + emit selectionChanged(); + emitCursorPositionChanged(); +} + +void QLineControl::_q_clipboardChanged() +{ +} + +void QLineControl::_q_deleteSelected() +{ + if (!hasSelectedText()) + return; + + int priorState = m_undoState; + emit resetInputContext(); + removeSelectedText(); + separate(); + finishChange(priorState); +} + +/*! + \internal + + Initializes the line control with a starting text value of \a txt. +*/ +void QLineControl::init(const QString &txt) +{ + m_text = txt; + updateDisplayText(); + m_cursor = m_text.length(); +} + +/*! + \internal + + Sets the password echo editing to \a editing. If password echo editing + is true, then the text of the password is displayed even if the echo + mode is set to QLineEdit::PasswordEchoOnEdit. Password echoing editing + does not affect other echo modes. +*/ +void QLineControl::updatePasswordEchoEditing(bool editing) +{ + m_passwordEchoEditing = editing; + updateDisplayText(); +} + +/*! + \internal + + Returns the cursor position of the given \a x pixel value in relation + to the displayed text. The given \a betweenOrOn specified what kind + of cursor position is requested. +*/ +int QLineControl::xToPos(int x, QTextLine::CursorPosition betweenOrOn) const +{ + return m_textLayout.lineAt(0).xToCursor(x, betweenOrOn); +} + +/*! + \internal + + Returns the bounds of the current cursor, as defined as a + between characters cursor. +*/ +QRect QLineControl::cursorRect() const +{ + QTextLine l = m_textLayout.lineAt(0); + int c = m_cursor; + if (m_preeditCursor != -1) + c += m_preeditCursor; + int cix = qRound(l.cursorToX(c)); + int w = m_cursorWidth; + int ch = l.height() + 1; + + return QRect(cix-5, 0, w+9, ch); +} + +/*! + \internal + + Fixes the current text so that it is valid given any set validators. + + Returns true if the text was changed. Otherwise returns false. +*/ +bool QLineControl::fixup() // this function assumes that validate currently returns != Acceptable +{ +#ifndef QT_NO_VALIDATOR + if (m_validator) { + QString textCopy = m_text; + int cursorCopy = m_cursor; + m_validator->fixup(textCopy); + if (m_validator->validate(textCopy, cursorCopy) == QValidator::Acceptable) { + if (textCopy != m_text || cursorCopy != m_cursor) + internalSetText(textCopy, cursorCopy); + return true; + } + } +#endif + return false; +} + +/*! + \internal + + Moves the cursor to the given position \a pos. If \a mark is true will + adjust the currently selected text. +*/ +void QLineControl::moveCursor(int pos, bool mark) +{ + if (pos != m_cursor) { + separate(); + if (m_maskData) + pos = pos > m_cursor ? nextMaskBlank(pos) : prevMaskBlank(pos); + } + if (mark) { + int anchor; + if (m_selend > m_selstart && m_cursor == m_selstart) + anchor = m_selend; + else if (m_selend > m_selstart && m_cursor == m_selend) + anchor = m_selstart; + else + anchor = m_cursor; + m_selstart = qMin(anchor, pos); + m_selend = qMax(anchor, pos); + updateDisplayText(); + } else { + internalDeselect(); + } + m_cursor = pos; + if (mark || m_selDirty) { + m_selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); +} + +/*! + \internal + + Applies the given input method event \a event to the text of the line + control +*/ +void QLineControl::processInputMethodEvent(QInputMethodEvent *event) +{ + int priorState = 0; + bool isGettingInput = !event->commitString().isEmpty() + || event->preeditString() != preeditAreaText() + || event->replacementLength() > 0; + bool cursorPositionChanged = false; + + if (isGettingInput) { + // If any text is being input, remove selected text. + priorState = m_undoState; + if (echoMode() == PasswordEchoOnEdit && !passwordEchoEditing()) { + updatePasswordEchoEditing(true); + m_selstart = 0; + m_selend = m_text.length(); + } + removeSelectedText(); + } + + int c = m_cursor; // cursor position after insertion of commit string + if (event->replacementStart() <= 0) + c += event->commitString().length() - qMin(-event->replacementStart(), event->replacementLength()); + + m_cursor += event->replacementStart(); + if (m_cursor < 0) + m_cursor = 0; + + // insert commit string + if (event->replacementLength()) { + m_selstart = m_cursor; + m_selend = m_selstart + event->replacementLength(); + removeSelectedText(); + } + if (!event->commitString().isEmpty()) { + internalInsert(event->commitString()); + cursorPositionChanged = true; + } + + m_cursor = qBound(0, c, m_text.length()); + + for (int i = 0; i < event->attributes().size(); ++i) { + const QInputMethodEvent::Attribute &a = event->attributes().at(i); + if (a.type == QInputMethodEvent::Selection) { + m_cursor = qBound(0, a.start + a.length, m_text.length()); + if (a.length) { + m_selstart = qMax(0, qMin(a.start, m_text.length())); + m_selend = m_cursor; + if (m_selend < m_selstart) { + qSwap(m_selstart, m_selend); + } + } else { + m_selstart = m_selend = 0; + } + cursorPositionChanged = true; + } + } +#ifndef QT_NO_IM + setPreeditArea(m_cursor, event->preeditString()); +#endif //QT_NO_IM + const int oldPreeditCursor = m_preeditCursor; + m_preeditCursor = event->preeditString().length(); + m_hideCursor = false; + QList<QTextLayout::FormatRange> formats; + for (int i = 0; i < event->attributes().size(); ++i) { + const QInputMethodEvent::Attribute &a = event->attributes().at(i); + if (a.type == QInputMethodEvent::Cursor) { + m_preeditCursor = a.start; + m_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 + m_cursor; + o.length = a.length; + o.format = f; + formats.append(o); + } + } + } + m_textLayout.setAdditionalFormats(formats); + updateDisplayText(/*force*/ true); + if (cursorPositionChanged) + emitCursorPositionChanged(); + else if (m_preeditCursor != oldPreeditCursor) + emit updateMicroFocus(); + if (isGettingInput) + finishChange(priorState); +} + +/*! + \internal + + Draws the display text for the line control using the given + \a painter, \a clip, and \a offset. Which aspects of the display text + are drawn is specified by the given \a flags. + + If the flags contain DrawSelections, then the selection or input mask + backgrounds and foregrounds will be applied before drawing the text. + + If the flags contain DrawCursor a cursor of the current cursorWidth() + will be drawn after drawing the text. + + The display text will only be drawn if the flags contain DrawText +*/ +void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &clip, int flags) +{ + QVector<QTextLayout::FormatRange> selections; + if (flags & DrawSelections) { + QTextLayout::FormatRange o; + if (m_selstart < m_selend) { + o.start = m_selstart; + o.length = m_selend - m_selstart; + o.format.setBackground(m_palette.brush(QPalette::Highlight)); + o.format.setForeground(m_palette.brush(QPalette::HighlightedText)); + } else { + // mask selection + if(!m_blinkPeriod || m_blinkStatus){ + o.start = m_cursor; + o.length = 1; + o.format.setBackground(m_palette.brush(QPalette::Text)); + o.format.setForeground(m_palette.brush(QPalette::Window)); + } + } + selections.append(o); + } + + if (flags & DrawText) + m_textLayout.draw(painter, offset, selections, clip); + + if (flags & DrawCursor){ + int cursor = m_cursor; + if (m_preeditCursor != -1) + cursor += m_preeditCursor; + if (!m_hideCursor && (!m_blinkPeriod || m_blinkStatus)) + m_textLayout.drawCursor(painter, offset, cursor, m_cursorWidth); + } +} + +/*! + \internal + + Sets the selection to cover the word at the given cursor position. + The word boundaries are defined by the behavior of QTextLayout::SkipWords + cursor mode. +*/ +void QLineControl::selectWordAtPos(int cursor) +{ + int next = cursor + 1; + if(next > end()) + --next; + int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords); + moveCursor(c, false); + // ## text layout should support end of words. + int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords); + while (end > cursor && m_text[end-1].isSpace()) + --end; + moveCursor(end, true); +} + +/*! + \internal + + Completes a change to the line control text. If the change is not valid + will undo the line control state back to the given \a validateFromState. + + If \a edited is true and the change is valid, will emit textEdited() in + addition to textChanged(). Otherwise only emits textChanged() on a valid + change. + + The \a update value is currently unused. +*/ +bool QLineControl::finishChange(int validateFromState, bool update, bool edited) +{ + Q_UNUSED(update) + bool lineDirty = m_selDirty; + if (m_textDirty) { + // do validation + bool wasValidInput = m_validInput; + m_validInput = true; +#ifndef QT_NO_VALIDATOR + if (m_validator) { + m_validInput = false; + QString textCopy = m_text; + int cursorCopy = m_cursor; + m_validInput = (m_validator->validate(textCopy, cursorCopy) != QValidator::Invalid); + if (m_validInput) { + if (m_text != textCopy) { + internalSetText(textCopy, cursorCopy); + return true; + } + m_cursor = cursorCopy; + } + } +#endif + if (validateFromState >= 0 && wasValidInput && !m_validInput) { + if (m_transactions.count()) + return false; + internalUndo(validateFromState); + m_history.resize(m_undoState); + if (m_modifiedState > m_undoState) + m_modifiedState = -1; + m_validInput = true; + m_textDirty = false; + } + updateDisplayText(); + lineDirty |= m_textDirty; + if (m_textDirty) { + m_textDirty = false; + QString actualText = text(); + if (edited) + emit textEdited(actualText); + emit textChanged(actualText); + } + } + if (m_selDirty) { + m_selDirty = false; + emit selectionChanged(); + } + emitCursorPositionChanged(); + return true; +} + +/*! + \internal + + An internal function for setting the text of the line control. +*/ +void QLineControl::internalSetText(const QString &txt, int pos, bool edited) +{ + internalDeselect(); + emit resetInputContext(); + QString oldText = m_text; + if (m_maskData) { + m_text = maskString(0, txt, true); + m_text += clearString(m_text.length(), m_maxLength - m_text.length()); + } else { + m_text = txt.isEmpty() ? txt : txt.left(m_maxLength); + } + m_history.clear(); + m_modifiedState = m_undoState = 0; + m_cursor = (pos < 0 || pos > m_text.length()) ? m_text.length() : pos; + m_textDirty = (oldText != m_text); + +#ifdef QT_NO_ACCESSIBILITY + Q_UNUSED(edited) +#else + bool changed = finishChange(-1, true, edited); + if (changed) + QAccessible::updateAccessibility(parent(), 0, QAccessible::TextUpdated); +#endif +} + + +/*! + \internal + + Adds the given \a command to the undo history + of the line control. Does not apply the command. +*/ +void QLineControl::addCommand(const Command &cmd) +{ + if (m_separator && m_undoState && m_history[m_undoState - 1].type != Separator) { + m_history.resize(m_undoState + 2); + m_history[m_undoState++] = Command(Separator, m_cursor, 0, m_selstart, m_selend); + } else { + m_history.resize(m_undoState + 1); + } + m_separator = false; + m_history[m_undoState++] = cmd; +} + +/*! + \internal + + Inserts the given string \a s into the line + control. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::internalInsert(const QString &s) +{ + if (hasSelectedText()) + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + if (m_maskData) { + QString ms = maskString(m_cursor, s); + for (int i = 0; i < (int) ms.length(); ++i) { + addCommand (Command(DeleteSelection, m_cursor + i, m_text.at(m_cursor + i), -1, -1)); + addCommand(Command(Insert, m_cursor + i, ms.at(i), -1, -1)); + } + m_text.replace(m_cursor, ms.length(), ms); + m_cursor += ms.length(); + m_cursor = nextMaskBlank(m_cursor); + m_textDirty = true; + } else { + int remaining = m_maxLength - m_text.length(); + if (remaining != 0) { + m_text.insert(m_cursor, s.left(remaining)); + for (int i = 0; i < (int) s.left(remaining).length(); ++i) + addCommand(Command(Insert, m_cursor++, s.at(i), -1, -1)); + m_textDirty = true; + } + } +} + +/*! + \internal + + deletes a single character from the current text. If \a wasBackspace, + the character prior to the cursor is removed. Otherwise the character + after the cursor is removed. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::internalDelete(bool wasBackspace) +{ + if (m_cursor < (int) m_text.length()) { + if (hasSelectedText()) + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + addCommand(Command((CommandType)((m_maskData ? 2 : 0) + (wasBackspace ? Remove : Delete)), + m_cursor, m_text.at(m_cursor), -1, -1)); + if (m_maskData) { + m_text.replace(m_cursor, 1, clearString(m_cursor, 1)); + addCommand(Command(Insert, m_cursor, m_text.at(m_cursor), -1, -1)); + } else { + m_text.remove(m_cursor, 1); + } + m_textDirty = true; + } +} + +/*! + \internal + + removes the currently selected text from the line control. + + Also adds the appropriate commands into the undo history. + This function does not call finishChange(), and may leave the text + in an invalid state. +*/ +void QLineControl::removeSelectedText() +{ + if (m_selstart < m_selend && m_selend <= (int) m_text.length()) { + separate(); + int i ; + addCommand(Command(SetSelection, m_cursor, 0, m_selstart, m_selend)); + if (m_selstart <= m_cursor && m_cursor < m_selend) { + // cursor is within the selection. Split up the commands + // to be able to restore the correct cursor position + for (i = m_cursor; i >= m_selstart; --i) + addCommand (Command(DeleteSelection, i, m_text.at(i), -1, 1)); + for (i = m_selend - 1; i > m_cursor; --i) + addCommand (Command(DeleteSelection, i - m_cursor + m_selstart - 1, m_text.at(i), -1, -1)); + } else { + for (i = m_selend-1; i >= m_selstart; --i) + addCommand (Command(RemoveSelection, i, m_text.at(i), -1, -1)); + } + if (m_maskData) { + m_text.replace(m_selstart, m_selend - m_selstart, clearString(m_selstart, m_selend - m_selstart)); + for (int i = 0; i < m_selend - m_selstart; ++i) + addCommand(Command(Insert, m_selstart + i, m_text.at(m_selstart + i), -1, -1)); + } else { + m_text.remove(m_selstart, m_selend - m_selstart); + } + if (m_cursor > m_selstart) + m_cursor -= qMin(m_cursor, m_selend) - m_selstart; + internalDeselect(); + m_textDirty = true; + } +} + +/*! + \internal + + Parses the input mask specified by \a maskFields to generate + the mask data used to handle input masks. +*/ +void QLineControl::parseInputMask(const QString &maskFields) +{ + int delimiter = maskFields.indexOf(QLatin1Char(';')); + if (maskFields.isEmpty() || delimiter == 0) { + if (m_maskData) { + delete [] m_maskData; + m_maskData = 0; + m_maxLength = 32767; + internalSetText(QString()); + } + return; + } + + if (delimiter == -1) { + m_blank = QLatin1Char(' '); + m_inputMask = maskFields; + } else { + m_inputMask = maskFields.left(delimiter); + m_blank = (delimiter + 1 < maskFields.length()) ? maskFields[delimiter + 1] : QLatin1Char(' '); + } + + // calculate m_maxLength / m_maskData length + m_maxLength = 0; + QChar c = 0; + for (int i=0; i<m_inputMask.length(); i++) { + c = m_inputMask.at(i); + if (i > 0 && m_inputMask.at(i-1) == QLatin1Char('\\')) { + m_maxLength++; + continue; + } + if (c != QLatin1Char('\\') && c != QLatin1Char('!') && + c != QLatin1Char('<') && c != QLatin1Char('>') && + c != QLatin1Char('{') && c != QLatin1Char('}') && + c != QLatin1Char('[') && c != QLatin1Char(']')) + m_maxLength++; + } + + delete [] m_maskData; + m_maskData = new MaskInputData[m_maxLength]; + + MaskInputData::Casemode m = MaskInputData::NoCaseMode; + c = 0; + bool s; + bool escape = false; + int index = 0; + for (int i = 0; i < m_inputMask.length(); i++) { + c = m_inputMask.at(i); + if (escape) { + s = true; + m_maskData[index].maskChar = c; + m_maskData[index].separator = s; + m_maskData[index].caseMode = m; + index++; + escape = false; + } else if (c == QLatin1Char('<')) { + m = MaskInputData::Lower; + } else if (c == QLatin1Char('>')) { + m = MaskInputData::Upper; + } else if (c == QLatin1Char('!')) { + m = MaskInputData::NoCaseMode; + } else if (c != QLatin1Char('{') && c != QLatin1Char('}') && c != QLatin1Char('[') && c != QLatin1Char(']')) { + switch (c.unicode()) { + case 'A': + case 'a': + case 'N': + case 'n': + case 'X': + case 'x': + case '9': + case '0': + case 'D': + case 'd': + case '#': + case 'H': + case 'h': + case 'B': + case 'b': + s = false; + break; + case '\\': + escape = true; + default: + s = true; + break; + } + + if (!escape) { + m_maskData[index].maskChar = c; + m_maskData[index].separator = s; + m_maskData[index].caseMode = m; + index++; + } + } + } + internalSetText(m_text); +} + + +/*! + \internal + + checks if the key is valid compared to the inputMask +*/ +bool QLineControl::isValidInput(QChar key, QChar mask) const +{ + switch (mask.unicode()) { + case 'A': + if (key.isLetter()) + return true; + break; + case 'a': + if (key.isLetter() || key == m_blank) + return true; + break; + case 'N': + if (key.isLetterOrNumber()) + return true; + break; + case 'n': + if (key.isLetterOrNumber() || key == m_blank) + return true; + break; + case 'X': + if (key.isPrint()) + return true; + break; + case 'x': + if (key.isPrint() || key == m_blank) + return true; + break; + case '9': + if (key.isNumber()) + return true; + break; + case '0': + if (key.isNumber() || key == m_blank) + return true; + break; + case 'D': + if (key.isNumber() && key.digitValue() > 0) + return true; + break; + case 'd': + if ((key.isNumber() && key.digitValue() > 0) || key == m_blank) + return true; + break; + case '#': + if (key.isNumber() || key == QLatin1Char('+') || key == QLatin1Char('-') || key == m_blank) + return true; + break; + case 'B': + if (key == QLatin1Char('0') || key == QLatin1Char('1')) + return true; + break; + case 'b': + if (key == QLatin1Char('0') || key == QLatin1Char('1') || key == m_blank) + return true; + break; + case 'H': + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F'))) + return true; + break; + case 'h': + if (key.isNumber() || (key >= QLatin1Char('a') && key <= QLatin1Char('f')) || (key >= QLatin1Char('A') && key <= QLatin1Char('F')) || key == m_blank) + return true; + break; + default: + break; + } + return false; +} + +/*! + \internal + + Returns true if the given text \a str is valid for any + validator or input mask set for the line control. + + Otherwise returns false +*/ +bool QLineControl::hasAcceptableInput(const QString &str) const +{ +#ifndef QT_NO_VALIDATOR + QString textCopy = str; + int cursorCopy = m_cursor; + if (m_validator && m_validator->validate(textCopy, cursorCopy) + != QValidator::Acceptable) + return false; +#endif + + if (!m_maskData) + return true; + + if (str.length() != m_maxLength) + return false; + + for (int i=0; i < m_maxLength; ++i) { + if (m_maskData[i].separator) { + if (str.at(i) != m_maskData[i].maskChar) + return false; + } else { + if (!isValidInput(str.at(i), m_maskData[i].maskChar)) + return false; + } + } + return true; +} + +/*! + \internal + + Applies the inputMask on \a str starting from position \a pos in the mask. \a clear + specifies from where characters should be gotten when a separator is met in \a str - true means + that blanks will be used, false that previous input is used. + Calling this when no inputMask is set is undefined. +*/ +QString QLineControl::maskString(uint pos, const QString &str, bool clear) const +{ + if (pos >= (uint)m_maxLength) + return QString::fromLatin1(""); + + QString fill; + fill = clear ? clearString(0, m_maxLength) : m_text; + + int strIndex = 0; + QString s = QString::fromLatin1(""); + int i = pos; + while (i < m_maxLength) { + if (strIndex < str.length()) { + if (m_maskData[i].separator) { + s += m_maskData[i].maskChar; + if (str[(int)strIndex] == m_maskData[i].maskChar) + strIndex++; + ++i; + } else { + if (isValidInput(str[(int)strIndex], m_maskData[i].maskChar)) { + switch (m_maskData[i].caseMode) { + case MaskInputData::Upper: + s += str[(int)strIndex].toUpper(); + break; + case MaskInputData::Lower: + s += str[(int)strIndex].toLower(); + break; + default: + s += str[(int)strIndex]; + } + ++i; + } else { + // search for separator first + int n = findInMask(i, true, true, str[(int)strIndex]); + if (n != -1) { + if (str.length() != 1 || i == 0 || (i > 0 && (!m_maskData[i-1].separator || m_maskData[i-1].maskChar != str[(int)strIndex]))) { + s += fill.mid(i, n-i+1); + i = n + 1; // update i to find + 1 + } + } else { + // search for valid m_blank if not + n = findInMask(i, true, false, str[(int)strIndex]); + if (n != -1) { + s += fill.mid(i, n-i); + switch (m_maskData[n].caseMode) { + case MaskInputData::Upper: + s += str[(int)strIndex].toUpper(); + break; + case MaskInputData::Lower: + s += str[(int)strIndex].toLower(); + break; + default: + s += str[(int)strIndex]; + } + i = n + 1; // updates i to find + 1 + } + } + } + ++strIndex; + } + } else + break; + } + + return s; +} + + + +/*! + \internal + + Returns a "cleared" string with only separators and blank chars. + Calling this when no inputMask is set is undefined. +*/ +QString QLineControl::clearString(uint pos, uint len) const +{ + if (pos >= (uint)m_maxLength) + return QString(); + + QString s; + int end = qMin((uint)m_maxLength, pos + len); + for (int i = pos; i < end; ++i) + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; + else + s += m_blank; + + return s; +} + +/*! + \internal + + Strips blank parts of the input in a QLineControl when an inputMask is set, + separators are still included. Typically "127.0__.0__.1__" becomes "127.0.0.1". +*/ +QString QLineControl::stripString(const QString &str) const +{ + if (!m_maskData) + return str; + + QString s; + int end = qMin(m_maxLength, (int)str.length()); + for (int i = 0; i < end; ++i) + if (m_maskData[i].separator) + s += m_maskData[i].maskChar; + else + if (str[i] != m_blank) + s += str[i]; + + return s; +} + +/*! + \internal + searches forward/backward in m_maskData for either a separator or a m_blank +*/ +int QLineControl::findInMask(int pos, bool forward, bool findSeparator, QChar searchChar) const +{ + if (pos >= m_maxLength || pos < 0) + return -1; + + int end = forward ? m_maxLength : -1; + int step = forward ? 1 : -1; + int i = pos; + + while (i != end) { + if (findSeparator) { + if (m_maskData[i].separator && m_maskData[i].maskChar == searchChar) + return i; + } else { + if (!m_maskData[i].separator) { + if (searchChar.isNull()) + return i; + else if (isValidInput(searchChar, m_maskData[i].maskChar)) + return i; + } + } + i += step; + } + return -1; +} + +void QLineControl::internalUndo(int until) +{ + if (!isUndoAvailable()) + return; + internalDeselect(); + while (m_undoState && m_undoState > until) { + Command& cmd = m_history[--m_undoState]; + switch (cmd.type) { + case Insert: + m_text.remove(cmd.pos, 1); + m_cursor = cmd.pos; + break; + case SetSelection: + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case RemoveSelection: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos + 1; + break; + case Delete: + case DeleteSelection: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos; + break; + case Separator: + continue; + } + if (until < 0 && m_undoState) { + Command& next = m_history[m_undoState-1]; + if (next.type != cmd.type && next.type < RemoveSelection + && (cmd.type < RemoveSelection || next.type == Separator)) + break; + } + } + m_textDirty = true; + emitCursorPositionChanged(); +} + +void QLineControl::internalRedo() +{ + if (!isRedoAvailable()) + return; + internalDeselect(); + while (m_undoState < (int)m_history.size()) { + Command& cmd = m_history[m_undoState++]; + switch (cmd.type) { + case Insert: + m_text.insert(cmd.pos, cmd.uc); + m_cursor = cmd.pos + 1; + break; + case SetSelection: + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Remove: + case Delete: + case RemoveSelection: + case DeleteSelection: + m_text.remove(cmd.pos, 1); + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + case Separator: + m_selstart = cmd.selStart; + m_selend = cmd.selEnd; + m_cursor = cmd.pos; + break; + } + if (m_undoState < (int)m_history.size()) { + Command& next = m_history[m_undoState]; + if (next.type != cmd.type && cmd.type < RemoveSelection && next.type != Separator + && (next.type < RemoveSelection || cmd.type == Separator)) + break; + } + } + m_textDirty = true; + emitCursorPositionChanged(); +} + +/*! + \internal + + If the current cursor position differs from the last emitted cursor + position, emits cursorPositionChanged(). +*/ +void QLineControl::emitCursorPositionChanged() +{ + if (m_cursor != m_lastCursorPos) { + const int oldLast = m_lastCursorPos; + m_lastCursorPos = m_cursor; + cursorPositionChanged(oldLast, m_cursor); +#ifndef QT_NO_ACCESSIBILITY + QAccessible::updateAccessibility(parent(), 0, QAccessible::TextCaretMoved); +#endif + } +} + + +void QLineControl::setCursorBlinkPeriod(int msec) +{ + if (msec == m_blinkPeriod) + return; + if (m_blinkTimer) { + killTimer(m_blinkTimer); + } + if (msec) { + m_blinkTimer = startTimer(msec / 2); + m_blinkStatus = 1; + } else { + m_blinkTimer = 0; + if (m_blinkStatus == 1) + emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect()); + } + m_blinkPeriod = msec; +} + +void QLineControl::resetCursorBlinkTimer() +{ + if (m_blinkPeriod == 0 || m_blinkTimer == 0) + return; + killTimer(m_blinkTimer); + m_blinkTimer = startTimer(m_blinkPeriod / 2); + m_blinkStatus = 1; +} + +void QLineControl::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == m_blinkTimer) { + m_blinkStatus = !m_blinkStatus; + emit updateNeeded(inputMask().isEmpty() ? cursorRect() : QRect()); + } else if (event->timerId() == m_deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + clear(); + } else if (event->timerId() == m_tripleClickTimer) { + killTimer(m_tripleClickTimer); + m_tripleClickTimer = 0; + } +} + +bool QLineControl::processEvent(QEvent* ev) +{ +#ifdef QT_KEYPAD_NAVIGATION + if (QGuiApplication::keypadNavigationEnabled()) { + if ((ev->type() == QEvent::KeyPress) || (ev->type() == QEvent::KeyRelease)) { + QKeyEvent *ke = (QKeyEvent *)ev; + if (ke->key() == Qt::Key_Back) { + if (ke->isAutoRepeat()) { + // Swallow it. We don't want back keys running amok. + ke->accept(); + return true; + } + if ((ev->type() == QEvent::KeyRelease) + && !isReadOnly() + && m_deleteAllTimer) { + killTimer(m_deleteAllTimer); + m_deleteAllTimer = 0; + backspace(); + ke->accept(); + return true; + } + } + } + } +#endif + switch(ev->type()){ + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + processMouseEvent(static_cast<QMouseEvent*>(ev)); break; + case QEvent::KeyPress: + case QEvent::KeyRelease: + processKeyEvent(static_cast<QKeyEvent*>(ev)); break; + case QEvent::InputMethod: + processInputMethodEvent(static_cast<QInputMethodEvent*>(ev)); break; +#ifndef QT_NO_SHORTCUT + case QEvent::ShortcutOverride:{ + if (isReadOnly()) + return false; + QKeyEvent* ke = static_cast<QKeyEvent*>(ev); + 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::SelectAll + || ke == QKeySequence::SelectEndOfDocument) { + ke->accept(); + } else 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_Delete: + case Qt::Key_Home: + case Qt::Key_End: + case Qt::Key_Backspace: + case Qt::Key_Left: + case Qt::Key_Right: + ke->accept(); + default: + break; + } + } + } + } +#endif + default: + return false; + } + return true; +} + +void QLineControl::processMouseEvent(QMouseEvent* ev) +{ + + switch (ev->type()) { + case QEvent::MouseButtonPress:{ + if (m_tripleClickTimer + && (ev->pos() - m_tripleClick).manhattanLength() + < startDragDistance) { + selectAll(); + return; + } + if (ev->button() == Qt::RightButton) + return; + + bool mark = ev->modifiers() & Qt::ShiftModifier; + int cursor = xToPos(ev->pos().x()); + moveCursor(cursor, mark); + break; + } + case QEvent::MouseButtonDblClick: + if (ev->button() == Qt::LeftButton) { + selectWordAtPos(xToPos(ev->pos().x())); + if (m_tripleClickTimer) + killTimer(m_tripleClickTimer); + m_tripleClickTimer = startTimer(QGuiApplication::doubleClickInterval()); + m_tripleClick = ev->pos(); + } + break; + case QEvent::MouseButtonRelease: +#ifndef QT_NO_CLIPBOARD + if (QGuiApplication::clipboard()->supportsSelection()) { + if (ev->button() == Qt::LeftButton) { + copy(QClipboard::Selection); + } else if (!isReadOnly() && ev->button() == Qt::MidButton) { + deselect(); + insert(QGuiApplication::clipboard()->text(QClipboard::Selection)); + } + } +#endif + break; + case QEvent::MouseMove: + if (ev->buttons() & Qt::LeftButton) { + moveCursor(xToPos(ev->pos().x()), true); + } + break; + default: + break; + } +} + +void QLineControl::processKeyEvent(QKeyEvent* event) +{ + bool inlineCompletionAccepted = false; + + if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) { + if (hasAcceptableInput() || fixup()) { + emit accepted(); + emit editingFinished(); + } + if (inlineCompletionAccepted) + event->accept(); + else + event->ignore(); + return; + } + + if (echoMode() == PasswordEchoOnEdit + && !passwordEchoEditing() + && !isReadOnly() + && !event->text().isEmpty() +#ifdef QT_KEYPAD_NAVIGATION + && event->key() != Qt::Key_Select + && event->key() != Qt::Key_Up + && event->key() != Qt::Key_Down + && event->key() != Qt::Key_Back +#endif + && !(event->modifiers() & Qt::ControlModifier)) { + // Clear the edit and reset to normal echo mode while editing; the + // echo mode switches back when the edit loses focus + // ### resets current content. dubious code; you can + // navigate with keys up, down, back, and select(?), but if you press + // "left" or "right" it clears? + updatePasswordEchoEditing(true); + clear(); + } + + bool unknown = false; + bool visual = cursorMoveStyle() == Qt::VisualMoveStyle; + + if (false) { + } +#ifndef QT_NO_SHORTCUT + else if (event == QKeySequence::Undo) { + if (!isReadOnly()) + undo(); + } + else if (event == QKeySequence::Redo) { + if (!isReadOnly()) + redo(); + } + else if (event == QKeySequence::SelectAll) { + selectAll(); + } +#ifndef QT_NO_CLIPBOARD + else if (event == QKeySequence::Copy) { + copy(); + } + else if (event == QKeySequence::Paste) { + if (!isReadOnly()) { + QClipboard::Mode mode = QClipboard::Clipboard; +#ifdef Q_WS_X11 + if (event->modifiers() == (Qt::CTRL | Qt::SHIFT) && event->key() == Qt::Key_Insert) + mode = QClipboard::Selection; +#endif + paste(mode); + } + } + else if (event == QKeySequence::Cut) { + if (!isReadOnly()) { + copy(); + del(); + } + } + else if (event == QKeySequence::DeleteEndOfLine) { + if (!isReadOnly()) { + setSelection(cursor(), end()); + copy(); + del(); + } + } +#endif //QT_NO_CLIPBOARD + else if (event == QKeySequence::MoveToStartOfLine || event == QKeySequence::MoveToStartOfBlock) { + home(0); + } + else if (event == QKeySequence::MoveToEndOfLine || event == QKeySequence::MoveToEndOfBlock) { + end(0); + } + else if (event == QKeySequence::SelectStartOfLine || event == QKeySequence::SelectStartOfBlock) { + home(1); + } + else if (event == QKeySequence::SelectEndOfLine || event == QKeySequence::SelectEndOfBlock) { + end(1); + } + else if (event == QKeySequence::MoveToNextChar) { +#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) + if (hasSelectedText()) { +#else + if (hasSelectedText() && m_completer + && m_completer->completionMode() == QCompleter::InlineCompletion) { +#endif + moveCursor(selectionEnd(), false); + } else { + cursorForward(0, visual ? 1 : (layoutDirection() == Qt::LeftToRight ? 1 : -1)); + } + } + else if (event == QKeySequence::SelectNextChar) { + cursorForward(1, visual ? 1 : (layoutDirection() == Qt::LeftToRight ? 1 : -1)); + } + else if (event == QKeySequence::MoveToPreviousChar) { +#if !defined(Q_WS_WIN) || defined(QT_NO_COMPLETER) + if (hasSelectedText()) { +#else + if (hasSelectedText() && m_completer + && m_completer->completionMode() == QCompleter::InlineCompletion) { +#endif + moveCursor(selectionStart(), false); + } else { + cursorForward(0, visual ? -1 : (layoutDirection() == Qt::LeftToRight ? -1 : 1)); + } + } + else if (event == QKeySequence::SelectPreviousChar) { + cursorForward(1, visual ? -1 : (layoutDirection() == Qt::LeftToRight ? -1 : 1)); + } + else if (event == QKeySequence::MoveToNextWord) { + if (echoMode() == Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordForward(0) : cursorWordBackward(0); + else + layoutDirection() == Qt::LeftToRight ? end(0) : home(0); + } + else if (event == QKeySequence::MoveToPreviousWord) { + if (echoMode() == Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordBackward(0) : cursorWordForward(0); + else if (!isReadOnly()) { + layoutDirection() == Qt::LeftToRight ? home(0) : end(0); + } + } + else if (event == QKeySequence::SelectNextWord) { + if (echoMode() == Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordForward(1) : cursorWordBackward(1); + else + layoutDirection() == Qt::LeftToRight ? end(1) : home(1); + } + else if (event == QKeySequence::SelectPreviousWord) { + if (echoMode() == Normal) + layoutDirection() == Qt::LeftToRight ? cursorWordBackward(1) : cursorWordForward(1); + else + layoutDirection() == Qt::LeftToRight ? home(1) : end(1); + } + else if (event == QKeySequence::Delete) { + if (!isReadOnly()) + del(); + } + else if (event == QKeySequence::DeleteEndOfWord) { + if (!isReadOnly()) { + cursorWordForward(true); + del(); + } + } + else if (event == QKeySequence::DeleteStartOfWord) { + if (!isReadOnly()) { + cursorWordBackward(true); + del(); + } + } +#endif // QT_NO_SHORTCUT + else { + bool handled = false; +#ifdef Q_WS_MAC + if (event->key() == Qt::Key_Up || event->key() == Qt::Key_Down) { + Qt::KeyboardModifiers myModifiers = (event->modifiers() & ~Qt::KeypadModifier); + if (myModifiers & Qt::ShiftModifier) { + if (myModifiers == (Qt::ControlModifier|Qt::ShiftModifier) + || myModifiers == (Qt::AltModifier|Qt::ShiftModifier) + || myModifiers == Qt::ShiftModifier) { + + event->key() == Qt::Key_Up ? home(1) : end(1); + } + } else { + if ((myModifiers == Qt::ControlModifier + || myModifiers == Qt::AltModifier + || myModifiers == Qt::NoModifier)) { + event->key() == Qt::Key_Up ? home(0) : end(0); + } + } + handled = true; + } +#endif + if (event->modifiers() & Qt::ControlModifier) { + switch (event->key()) { + case Qt::Key_Backspace: + if (!isReadOnly()) { + cursorWordBackward(true); + del(); + } + break; +#if defined(Q_WS_X11) + case Qt::Key_E: + end(0); + break; + + case Qt::Key_U: + if (!isReadOnly()) { + setSelection(0, text().size()); +#ifndef QT_NO_CLIPBOARD + copy(); +#endif + del(); + } + break; +#endif + default: + if (!handled) + unknown = true; + } + } else { // ### check for *no* modifier + switch (event->key()) { + case Qt::Key_Backspace: + if (!isReadOnly()) { + backspace(); + } + break; +#ifdef QT_KEYPAD_NAVIGATION + case Qt::Key_Back: + if (QGuiApplication::keypadNavigationEnabled() && !event->isAutoRepeat() + && !isReadOnly()) { + if (text().length() == 0) { + setText(m_cancelText); + + if (passwordEchoEditing()) + updatePasswordEchoEditing(false); + + emit editFocusChange(false); + } else if (!m_deleteAllTimer) { + m_deleteAllTimer = startTimer(750); + } + } else { + unknown = true; + } + break; +#endif + default: + if (!handled) + unknown = true; + } + } + } + + if (event->key() == Qt::Key_Direction_L || event->key() == Qt::Key_Direction_R) { + setLayoutDirection((event->key() == Qt::Key_Direction_L) ? Qt::LeftToRight : Qt::RightToLeft); + unknown = false; + } + + if (unknown && !isReadOnly()) { + QString t = event->text(); + if (!t.isEmpty() && t.at(0).isPrint()) { + insert(t); + event->accept(); + return; + } + } + + if (unknown) + event->ignore(); + else + event->accept(); +} + + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/text/qlinecontrol_p.h b/src/gui/text/qlinecontrol_p.h new file mode 100644 index 0000000000..e5435c22f6 --- /dev/null +++ b/src/gui/text/qlinecontrol_p.h @@ -0,0 +1,455 @@ +/**************************************************************************** +** +** 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$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QLINECONTROL_P_H +#define QLINECONTROL_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/qglobal.h" + +#include "QtGui/qtextlayout.h" +#include "QtCore/qpointer.h" +#include "QtGui/qclipboard.h" +#include "QtGui/qvalidator.h" +#include "QtGui/qpalette.h" +#include "QtGui/qguiapplication.h" +#include "QtCore/qpoint.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QLineControl : public QObject +{ + Q_OBJECT + +public: + QLineControl(const QString &txt = QString()) + : m_cursor(0), m_preeditCursor(0), m_cursorWidth(0), m_layoutDirection(Qt::LayoutDirectionAuto), + m_hideCursor(false), m_separator(0), m_readOnly(0), + m_dragEnabled(0), m_echoMode(Normal), m_textDirty(0), m_selDirty(0), + m_validInput(1), m_blinkStatus(0), m_blinkPeriod(0), m_blinkTimer(0), m_deleteAllTimer(0), + m_ascent(0), m_maxLength(32767), m_lastCursorPos(-1), + m_tripleClickTimer(0), m_maskData(0), m_modifiedState(0), m_undoState(0), + m_selstart(0), m_selend(0), m_passwordEchoEditing(false) + { + init(txt); + } + + enum EchoMode { + Normal, + NoEcho, + Password, + PasswordEchoOnEdit + }; + + + ~QLineControl() + { + delete [] m_maskData; + } + + int nextMaskBlank(int pos) + { + int c = findInMask(pos, true, false); + m_separator |= (c != pos); + return (c != -1 ? c : m_maxLength); + } + + int prevMaskBlank(int pos) + { + int c = findInMask(pos, false, false); + m_separator |= (c != pos); + return (c != -1 ? c : 0); + } + + bool isUndoAvailable() const { return !m_readOnly && m_undoState; } + bool isRedoAvailable() const { return !m_readOnly && m_undoState < (int)m_history.size(); } + void clearUndo() { m_history.clear(); m_modifiedState = m_undoState = 0; } + + bool isModified() const { return m_modifiedState != m_undoState; } + void setModified(bool modified) { m_modifiedState = modified ? -1 : m_undoState; } + + bool allSelected() const { return !m_text.isEmpty() && m_selstart == 0 && m_selend == (int)m_text.length(); } + bool hasSelectedText() const { return !m_text.isEmpty() && m_selend > m_selstart; } + + int width() const { return qRound(m_textLayout.lineAt(0).width()) + 1; } + int height() const { return qRound(m_textLayout.lineAt(0).height()) + 1; } + int ascent() const { return m_ascent; } + qreal naturalTextWidth() const { return m_textLayout.lineAt(0).naturalTextWidth(); } + + void setSelection(int start, int length); + + inline QString selectedText() const { return hasSelectedText() ? m_text.mid(m_selstart, m_selend - m_selstart) : QString(); } + QString textBeforeSelection() const { return hasSelectedText() ? m_text.left(m_selstart) : QString(); } + QString textAfterSelection() const { return hasSelectedText() ? m_text.mid(m_selend) : QString(); } + + int selectionStart() const { return hasSelectedText() ? m_selstart : -1; } + int selectionEnd() const { return hasSelectedText() ? m_selend : -1; } + bool inSelection(int x) const + { + if (m_selstart >= m_selend) + return false; + int pos = xToPos(x, QTextLine::CursorOnCharacter); + return pos >= m_selstart && pos < m_selend; + } + + void removeSelection() + { + int priorState = m_undoState; + removeSelectedText(); + finishChange(priorState); + } + + int start() const { return 0; } + int end() const { return m_text.length(); } + +#ifndef QT_NO_CLIPBOARD + void copy(QClipboard::Mode mode = QClipboard::Clipboard) const; + void paste(QClipboard::Mode mode = QClipboard::Clipboard); +#endif + + int cursor() const{ return m_cursor; } + int preeditCursor() const { return m_preeditCursor; } + + int cursorWidth() const { return m_cursorWidth; } + void setCursorWidth(int value) { m_cursorWidth = value; } + + Qt::CursorMoveStyle cursorMoveStyle() const { return m_textLayout.cursorMoveStyle(); } + void setCursorMoveStyle(Qt::CursorMoveStyle style) { m_textLayout.setCursorMoveStyle(style); } + + void moveCursor(int pos, bool mark = false); + void cursorForward(bool mark, int steps) + { + int c = m_cursor; + if (steps > 0) { + while (steps--) + c = cursorMoveStyle() == Qt::VisualMoveStyle ? m_textLayout.rightCursorPosition(c) + : m_textLayout.nextCursorPosition(c); + } else if (steps < 0) { + while (steps++) + c = cursorMoveStyle() == Qt::VisualMoveStyle ? m_textLayout.leftCursorPosition(c) + : m_textLayout.previousCursorPosition(c); + } + moveCursor(c, mark); + } + + void cursorWordForward(bool mark) { moveCursor(m_textLayout.nextCursorPosition(m_cursor, QTextLayout::SkipWords), mark); } + void cursorWordBackward(bool mark) { moveCursor(m_textLayout.previousCursorPosition(m_cursor, QTextLayout::SkipWords), mark); } + + void home(bool mark) { moveCursor(0, mark); } + void end(bool mark) { moveCursor(text().length(), mark); } + + int xToPos(int x, QTextLine::CursorPosition = QTextLine::CursorBetweenCharacters) const; + QRect cursorRect() const; + + qreal cursorToX(int cursor) const { return m_textLayout.lineAt(0).cursorToX(cursor); } + qreal cursorToX() const + { + int cursor = m_cursor; + if (m_preeditCursor != -1) + cursor += m_preeditCursor; + return cursorToX(cursor); + } + + bool isReadOnly() const { return m_readOnly; } + void setReadOnly(bool enable) { m_readOnly = enable; } + + QString text() const + { + QString res = m_maskData ? stripString(m_text) : m_text; + return (res.isNull() ? QString::fromLatin1("") : res); + } + void setText(const QString &txt) { internalSetText(txt, -1, false); } + QString displayText() const { return m_textLayout.text(); } + + void backspace(); + void del(); + void deselect() { internalDeselect(); finishChange(); } + void selectAll() { m_selstart = m_selend = m_cursor = 0; moveCursor(m_text.length(), true); } + + void insert(const QString &); + void clear(); + void undo() { internalUndo(); finishChange(-1, true); } + void redo() { internalRedo(); finishChange(); } + void selectWordAtPos(int); + + EchoMode echoMode() const { return EchoMode(m_echoMode); } + void setEchoMode(EchoMode mode) + { + m_echoMode = mode; + m_passwordEchoEditing = false; + updateDisplayText(); + } + + int maxLength() const { return m_maxLength; } + void setMaxLength(int maxLength) + { + if (m_maskData) + return; + m_maxLength = maxLength; + setText(m_text); + } + +#ifndef QT_NO_VALIDATOR + const QValidator *validator() const { return m_validator; } + void setValidator(const QValidator *v) { m_validator = const_cast<QValidator*>(v); } +#endif + + int cursorPosition() const { return m_cursor; } + void setCursorPosition(int pos) { if (pos <= m_text.length()) moveCursor(qMax(0, pos)); } + + bool hasAcceptableInput() const { return hasAcceptableInput(m_text); } + bool fixup(); + + QString inputMask() const { return m_maskData ? m_inputMask + QLatin1Char(';') + m_blank : QString(); } + void setInputMask(const QString &mask) + { + parseInputMask(mask); + if (m_maskData) + moveCursor(nextMaskBlank(0)); + } + + // input methods +#ifndef QT_NO_IM + bool composeMode() const { return !m_textLayout.preeditAreaText().isEmpty(); } + void setPreeditArea(int cursor, const QString &text) { m_textLayout.setPreeditArea(cursor, text); } +#endif + + QString preeditAreaText() const { return m_textLayout.preeditAreaText(); } + + void updatePasswordEchoEditing(bool editing); + bool passwordEchoEditing() const { return m_passwordEchoEditing; } + + QChar passwordCharacter() const { return m_passwordCharacter; } + void setPasswordCharacter(const QChar &character) { m_passwordCharacter = character; updateDisplayText(); } + + Qt::LayoutDirection layoutDirection() const { + if (m_layoutDirection == Qt::LayoutDirectionAuto) { + if (m_text.isEmpty()) + return QGuiApplication::keyboardInputDirection(); + return m_text.isRightToLeft() ? Qt::RightToLeft : Qt::LeftToRight; + } + return m_layoutDirection; + } + void setLayoutDirection(Qt::LayoutDirection direction) + { + if (direction != m_layoutDirection) { + m_layoutDirection = direction; + updateDisplayText(); + } + } + + void setFont(const QFont &font) { m_textLayout.setFont(font); updateDisplayText(); } + + void processInputMethodEvent(QInputMethodEvent *event); + void processMouseEvent(QMouseEvent* ev); + void processKeyEvent(QKeyEvent* ev); + + int cursorBlinkPeriod() const { return m_blinkPeriod; } + void setCursorBlinkPeriod(int msec); + void resetCursorBlinkTimer(); + + bool cursorBlinkStatus() const { return m_blinkStatus; } + + QString cancelText() const { return m_cancelText; } + void setCancelText(const QString &text) { m_cancelText = text; } + + const QPalette &palette() const { return m_palette; } + void setPalette(const QPalette &p) { m_palette = p; } + + enum DrawFlags { + DrawText = 0x01, + DrawSelections = 0x02, + DrawCursor = 0x04, + DrawAll = DrawText | DrawSelections | DrawCursor + }; + void draw(QPainter *, const QPoint &, const QRect &, int flags = DrawAll); + + bool processEvent(QEvent *ev); + + QTextLayout *textLayout() + { + return &m_textLayout; + } + +private: + void init(const QString &txt); + void removeSelectedText(); + void internalSetText(const QString &txt, int pos = -1, bool edited = true); + void updateDisplayText(bool forceUpdate = false); + + void internalInsert(const QString &s); + void internalDelete(bool wasBackspace = false); + void internalRemove(int pos); + + inline void internalDeselect() + { + m_selDirty |= (m_selend > m_selstart); + m_selstart = m_selend = 0; + } + + void internalUndo(int until = -1); + void internalRedo(); + + QString m_text; + QPalette m_palette; + int m_cursor; + int m_preeditCursor; + int m_cursorWidth; + Qt::LayoutDirection m_layoutDirection; + uint m_hideCursor : 1; // used to hide the m_cursor inside preedit areas + uint m_separator : 1; + uint m_readOnly : 1; + uint m_dragEnabled : 1; + uint m_echoMode : 2; + uint m_textDirty : 1; + uint m_selDirty : 1; + uint m_validInput : 1; + uint m_blinkStatus : 1; + int m_blinkPeriod; // 0 for non-blinking cursor + int m_blinkTimer; + int m_deleteAllTimer; + int m_ascent; + int m_maxLength; + int m_lastCursorPos; + QList<int> m_transactions; + QPoint m_tripleClick; + int m_tripleClickTimer; + QString m_cancelText; + + void emitCursorPositionChanged(); + + bool finishChange(int validateFromState = -1, bool update = false, bool edited = true); + +#ifndef QT_NO_VALIDATOR + QPointer<QValidator> m_validator; +#endif + + struct MaskInputData { + enum Casemode { NoCaseMode, Upper, Lower }; + QChar maskChar; // either the separator char or the inputmask + bool separator; + Casemode caseMode; + }; + QString m_inputMask; + QChar m_blank; + MaskInputData *m_maskData; + + // undo/redo handling + enum CommandType { Separator, Insert, Remove, Delete, RemoveSelection, DeleteSelection, SetSelection }; + struct Command { + inline Command() {} + inline Command(CommandType t, int p, QChar c, int ss, int se) : type(t),uc(c),pos(p),selStart(ss),selEnd(se) {} + uint type : 4; + QChar uc; + int pos, selStart, selEnd; + }; + int m_modifiedState; + int m_undoState; + QVector<Command> m_history; + void addCommand(const Command& cmd); + + inline void separate() { m_separator = true; } + + // selection + int m_selstart; + int m_selend; + + // masking + void parseInputMask(const QString &maskFields); + bool isValidInput(QChar key, QChar mask) const; + bool hasAcceptableInput(const QString &text) const; + QString maskString(uint pos, const QString &str, bool clear = false) const; + QString clearString(uint pos, uint len) const; + QString stripString(const QString &str) const; + int findInMask(int pos, bool forward, bool findSeparator, QChar searchChar = QChar()) const; + + // complex text layout + QTextLayout m_textLayout; + + bool m_passwordEchoEditing; + QChar m_passwordCharacter; + +Q_SIGNALS: + void cursorPositionChanged(int, int); + void selectionChanged(); + + void displayTextChanged(const QString &); + void textChanged(const QString &); + void textEdited(const QString &); + + void resetInputContext(); + void updateMicroFocus(); + + void accepted(); + void editingFinished(); + void updateNeeded(const QRect &); + +#ifdef QT_KEYPAD_NAVIGATION + void editFocusChange(bool); +#endif +protected: + virtual void timerEvent(QTimerEvent *event); + +private Q_SLOTS: + void _q_clipboardChanged(); + void _q_deleteSelected(); + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLineControl_P_H diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp index 059dc3e188..7ad838561b 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.cpp +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -344,6 +344,30 @@ QString QPlatformFontDatabase::fontDir() const } /*! + Returns the default system font. + + \sa QGuiApplication::font() + \since 5.0 +*/ + +QFont QPlatformFontDatabase::defaultFont() const +{ + return QFont(QLatin1String("Helvetica")); +} + +/*! + Returns fonts for class names. + + \sa QGuiApplication::font() + \since 5.0 +*/ + +QHash<QByteArray, QFont> QPlatformFontDatabase::defaultFonts() const +{ + return QHash<QByteArray, QFont>(); +} + +/*! \class QPlatformFontDatabase \brief The QPlatformFontDatabase class makes it possible to customize how fonts are discovered and how they are rendered diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h index 1fb3c32fea..d34d602e43 100644 --- a/src/gui/text/qplatformfontdatabase_qpa.h +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -46,6 +46,7 @@ #include <QtCore/QString> #include <QtCore/QStringList> #include <QtCore/QList> +#include <QtCore/QHash> #include <QtGui/QFontDatabase> #include <QtGui/private/qfont_p.h> @@ -96,6 +97,9 @@ public: virtual QString fontDir() const; + virtual QFont defaultFont() const; + virtual QHash<QByteArray, QFont> defaultFonts() const; + //callback static void registerQPF2Font(const QByteArray &dataArray, void *handle); static void registerFont(const QString &familyname, const QString &foundryname, QFont::Weight weight, diff --git a/src/gui/text/qrawfont_mac.cpp b/src/gui/text/qrawfont_mac.cpp deleted file mode 100644 index 40c719a1af..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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, - qreal 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 6a69804fac..47815baf06 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, qreal pix { 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 d8aa557975..0000000000 --- a/src/gui/text/qrawfont_win.cpp +++ /dev/null @@ -1,709 +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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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) { - QFunctionPointer 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, - qreal 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) { - QFunctionPointer 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 388be3999c..10c494dec9 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 5d6c0052f4..5f1a53b556 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 9ee09c1f1d..1c421d1c26 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 index c29379ed28..9ca6a24ce7 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -51,43 +51,40 @@ #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 "qpagedpaintdevice.h" +#include "private/qpagedpaintdevice_p.h" #include <qtextformat.h> #include <qdatetime.h> #include <qbuffer.h> -#include <qapplication.h> +#include <qguiapplication.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 +// ### these should come from the application +const int startDragDistance = 10; +const int cursorFlashTime = 2000; +const int textCursorWidth = 1; +const bool fullWidthSelection = true; + +//#ifndef QT_NO_SHORTCUT +//#include "private/QGuiApplication_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 @@ -273,9 +270,9 @@ bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down; #ifdef QT_KEYPAD_NAVIGATION - ignoreNavigationEvents = ignoreNavigationEvents || QApplication::keypadNavigationEnabled(); + ignoreNavigationEvents = ignoreNavigationEvents || QGuiApplication::keypadNavigationEnabled(); isNavigationEvent = isNavigationEvent || - (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional + (QGuiApplication::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; @@ -427,7 +424,7 @@ void QTextControlPrivate::setContent(Qt::TextFormat format, const QString &text, doc = document; clearDocument = false; } else { - palette = QApplication::palette("QTextControl"); + palette = QGuiApplication::palette(); doc = new QTextDocument(q); } _q_documentLayoutChanged(); @@ -506,11 +503,11 @@ void QTextControlPrivate::startDrag() #ifndef QT_NO_DRAGANDDROP Q_Q(QTextControl); mousePressed = false; - if (!contextWidget) + if (!contextObject) return; QMimeData *data = q->createMimeDataFromSelection(); - QDrag *drag = new QDrag(contextWidget); + QDrag *drag = new QDrag(contextObject); drag->setMimeData(data); Qt::DropActions actions = Qt::CopyAction; @@ -522,7 +519,7 @@ void QTextControlPrivate::startDrag() action = drag->exec(actions, Qt::CopyAction); } - if (action == Qt::MoveAction && drag->target() != contextWidget) + if (action == Qt::MoveAction && drag->target() != contextObject) cursor.removeSelectedText(); #endif } @@ -606,7 +603,7 @@ void QTextControlPrivate::_q_updateCurrentCharFormatAndSelection() #ifndef QT_NO_CLIPBOARD void QTextControlPrivate::setClipboardSelection() { - QClipboard *clipboard = QApplication::clipboard(); + QClipboard *clipboard = QGuiApplication::clipboard(); if (!cursor.hasSelection() || !clipboard->supportsSelection()) return; Q_Q(QTextControl); @@ -638,8 +635,8 @@ void QTextControlPrivate::setBlinkingCursorEnabled(bool enable) { Q_Q(QTextControl); - if (enable && QApplication::cursorFlashTime() > 0) - cursorBlinkTimer.start(QApplication::cursorFlashTime() / 2, q); + if (enable && cursorFlashTime > 0) + cursorBlinkTimer.start(cursorFlashTime / 2, q); else cursorBlinkTimer.stop(); @@ -798,6 +795,18 @@ QTextControl::~QTextControl() { } +void QTextControl::setView(QObject *view) +{ + Q_D(QTextControl); + d->contextObject = view; +} + +QObject *QTextControl::view() const +{ + Q_D(const QTextControl); + return d->contextObject; +} + void QTextControl::setDocument(QTextDocument *document) { Q_D(QTextControl); @@ -859,12 +868,12 @@ void QTextControl::copy() if (!d->cursor.hasSelection()) return; QMimeData *data = createMimeDataFromSelection(); - QApplication::clipboard()->setMimeData(data); + QGuiApplication::clipboard()->setMimeData(data); } void QTextControl::paste(QClipboard::Mode mode) { - const QMimeData *md = QApplication::clipboard()->mimeData(mode); + const QMimeData *md = QGuiApplication::clipboard()->mimeData(mode); if (md) insertFromMimeData(md); } @@ -889,14 +898,14 @@ void QTextControl::selectAll() emit updateRequest(); } -void QTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset, QWidget *contextWidget) +void QTextControl::processEvent(QEvent *e, const QPointF &coordinateOffset) { QMatrix m; m.translate(coordinateOffset.x(), coordinateOffset.y()); - processEvent(e, m, contextWidget); + processEvent(e, m); } -void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *contextWidget) +void QTextControl::processEvent(QEvent *e, const QMatrix &matrix) { Q_D(QTextControl); if (d->interactionFlags == Qt::NoTextInteraction) { @@ -904,33 +913,6 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte 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)); @@ -958,12 +940,6 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte 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)); @@ -973,14 +949,6 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte 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); @@ -1005,61 +973,10 @@ void QTextControl::processEvent(QEvent *e, const QMatrix &matrix, QWidget *conte } #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()) + if (QGuiApplication::keypadNavigationEnabled()) d->editFocusEvent(e); break; #endif @@ -1130,9 +1047,10 @@ void QTextControl::timerEvent(QTimerEvent *e) if (e->timerId() == d->cursorBlinkTimer.timerId()) { d->cursorOn = !d->cursorOn; - if (d->cursor.hasSelection()) - d->cursorOn &= (QApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected) - != 0); + // ### +// if (d->cursor.hasSelection()) +// d->cursorOn &= (QGuiApplication::style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected) +// != 0); d->repaintCursor(); } else if (e->timerId() == d->trippleClickTimer.timerId()) { @@ -1313,7 +1231,7 @@ process: QVariant QTextControl::loadResource(int type, const QUrl &name) { -#ifdef QT_NO_TEXTEDIT +#if 1 Q_UNUSED(type); Q_UNUSED(name); #else @@ -1534,7 +1452,7 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con #endif if (trippleClickTimer.isActive() - && ((pos - trippleClickPoint).toPoint().manhattanLength() < QApplication::startDragDistance())) { + && ((pos - trippleClickPoint).toPoint().manhattanLength() < startDragDistance)) { cursor.movePosition(QTextCursor::StartOfBlock); cursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor); @@ -1632,7 +1550,7 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons const int oldCursorPos = cursor.position(); if (mightStartDrag) { - if ((mousePos.toPoint() - dragStartPos).manhattanLength() > QApplication::startDragDistance()) + if ((mousePos.toPoint() - dragStartPos).manhattanLength() > startDragDistance) startDrag(); return; } @@ -1665,8 +1583,8 @@ void QTextControlPrivate::mouseMoveEvent(QEvent *e, Qt::MouseButton button, cons if (cursor.position() != oldCursorPos) emit q->cursorPositionChanged(); _q_updateCurrentCharFormatAndSelection(); -#ifndef QT_NO_IM - if (contextWidget) { +#if 0 // ### ndef QT_NO_IM + if (contextObject) { if (QInputContext *ic = inputContext()) { ic->update(); } @@ -1709,9 +1627,9 @@ void QTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton button, c selectionChanged(true); } else if (button == Qt::MidButton && (interactionFlags & Qt::TextEditable) - && QApplication::clipboard()->supportsSelection()) { + && QGuiApplication::clipboard()->supportsSelection()) { setCursorPosition(pos); - const QMimeData *md = QApplication::clipboard()->mimeData(QClipboard::Selection); + const QMimeData *md = QGuiApplication::clipboard()->mimeData(QClipboard::Selection); if (md) q->insertFromMimeData(md); #endif @@ -1779,7 +1697,7 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto selectedWordOnDoubleClick = cursor; trippleClickPoint = pos; - trippleClickTimer.start(QApplication::doubleClickInterval(), q); + trippleClickTimer.start(QGuiApplication::doubleClickInterval(), q); if (doEmit) { selectionChanged(); #ifndef QT_NO_CLIPBOARD @@ -1793,11 +1711,11 @@ 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) +#if 0 // ### !defined(QT_NO_IM) Q_Q(QTextControl); QTextLayout *layout = cursor.block().layout(); - if (contextWidget && layout && !layout->preeditAreaText().isEmpty()) { + if (contextObject && layout && !layout->preeditAreaText().isEmpty()) { QInputContext *ctx = inputContext(); int cursorPos = q->hitTest(pos, Qt::FuzzyHit) - cursor.position(); @@ -1808,7 +1726,7 @@ bool QTextControlPrivate::sendMouseEventToInputContext( return true; } if (ctx) { - QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos, + QMouseEvent ev(eventType, contextObject->mapFromGlobal(globalPos), globalPos, button, buttons, modifiers); ctx->mouseHandler(cursorPos, &ev); e->setAccepted(ev.isAccepted()); @@ -1828,24 +1746,6 @@ bool QTextControlPrivate::sendMouseEventToInputContext( 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); @@ -1894,7 +1794,7 @@ bool QTextControlPrivate::dragMoveEvent(QEvent *e, const QMimeData *mimeData, co return true; // accept proposed action } -bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &pos, Qt::DropAction dropAction, QWidget *source) +bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &pos, Qt::DropAction dropAction, QObject *source) { Q_Q(QTextControl); dndFeedbackCursor = QTextCursor(); @@ -1907,7 +1807,7 @@ bool QTextControlPrivate::dropEvent(const QMimeData *mimeData, const QPointF &po QTextCursor insertionCursor = q->cursorForPosition(pos); insertionCursor.beginEditBlock(); - if (dropAction == Qt::MoveAction && source == contextWidget) + if (dropAction == Qt::MoveAction && source == contextObject) cursor.removeSelectedText(); cursor = insertionCursor; @@ -1981,8 +1881,9 @@ void QTextControlPrivate::inputMethodEvent(QInputMethodEvent *e) } layout->setAdditionalFormats(overrides); cursor.endEditBlock(); - if (cursor.d) - cursor.d->setX(); + QTextCursorPrivate *cursor_d = QTextCursorPrivate::getPrivate(&cursor); + if (cursor_d) + cursor_d->setX(); if (oldPreeditCursor != preeditCursor) emit q->microFocusChanged(); selectionChanged(forceSelectionChanged); @@ -2025,7 +1926,7 @@ void QTextControlPrivate::focusEvent(QFocusEvent *e) emit q->updateRequest(q->selectionRect()); if (e->gotFocus()) { #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason + if (!QGuiApplication::keypadNavigationEnabled() || (hasEditFocus && (e->reason() == Qt::PopupFocusReason #ifdef Q_OS_SYMBIAN || e->reason() == Qt::ActiveWindowFocusReason #endif @@ -2070,7 +1971,7 @@ void QTextControlPrivate::editFocusEvent(QEvent *e) { Q_Q(QTextControl); - if (QApplication::keypadNavigationEnabled()) { + if (QGuiApplication::keypadNavigationEnabled()) { if (e->type() == QEvent::EnterEditFocus && interactionFlags & Qt::TextEditable) { const QTextCursor oldSelection = cursor; const int oldCursorPos = cursor.position(); @@ -2093,87 +1994,6 @@ void QTextControlPrivate::editFocusEvent(QEvent *e) } #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); @@ -2250,7 +2070,7 @@ void QTextControl::setCursorWidth(int width) Q_UNUSED(width); #else if (width == -1) - width = QApplication::style()->pixelMetric(QStyle::PM_TextCursorWidth); + width = textCursorWidth; d->doc->documentLayout()->setProperty("cursorWidth", width); #endif d->repaintCursor(); @@ -2268,9 +2088,7 @@ void QTextControl::setAcceptRichText(bool accept) d->acceptRichText = accept; } -#ifndef QT_NO_TEXTEDIT - -void QTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelection> &selections) +void QTextControl::setExtraSelections(const QVector<QAbstractTextDocumentLayout::Selection> &selections) { Q_D(QTextControl); @@ -2281,7 +2099,7 @@ void QTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelection> &se } for (int i = 0; i < selections.count(); ++i) { - const QTextEdit::ExtraSelection &sel = selections.at(i); + const QAbstractTextDocumentLayout::Selection &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()); @@ -2309,28 +2127,15 @@ void QTextControl::setExtraSelections(const QList<QTextEdit::ExtraSelection> &se 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; - } + d->extraSelections = selections; } -QList<QTextEdit::ExtraSelection> QTextControl::extraSelections() const +QVector<QAbstractTextDocumentLayout::Selection> 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; + return d->extraSelections; } -#endif // QT_NO_TEXTEDIT - void QTextControl::setTextWidth(qreal width) { Q_D(QTextControl); @@ -2390,7 +2195,7 @@ bool QTextControl::canPaste() const #ifndef QT_NO_CLIPBOARD Q_D(const QTextControl); if (d->interactionFlags & Qt::TextEditable) { - const QMimeData *md = QApplication::clipboard()->mimeData(); + const QMimeData *md = QGuiApplication::clipboard()->mimeData(); return md && canInsertFromMimeData(md); } #endif @@ -2435,16 +2240,14 @@ bool QTextControl::isWordSelectionEnabled() const return d->wordSelectionEnabled; } -#ifndef QT_NO_PRINTER -void QTextControl::print(QPrinter *printer) const +void QTextControl::print(QPagedPaintDevice *printer) const { -#ifndef QT_NO_PRINTER Q_D(const QTextControl); - if (!printer || !printer->isValid()) + if (!printer) return; QTextDocument *tempDoc = 0; const QTextDocument *doc = d->doc; - if (printer->printRange() == QPrinter::Selection) { + if (QPagedPaintDevicePrivate::get(printer)->printSelectionOnly) { if (!d->cursor.hasSelection()) return; tempDoc = new QTextDocument(const_cast<QTextDocument *>(doc)); @@ -2460,9 +2263,7 @@ void QTextControl::print(QPrinter *printer) const } doc->print(printer); delete tempDoc; -#endif } -#endif // QT_NO_PRINTER QMimeData *QTextControl::createMimeDataFromSelection() const { @@ -2720,7 +2521,7 @@ void QTextControlPrivate::activateLinkUnderCursor(QString href) } repaintOldAndNewSelection(oldCursor); -#ifndef QT_NO_DESKTOPSERVICES +#if 0 // ###ndef QT_NO_DESKTOPSERVICES if (openExternalLinks) QDesktopServices::openUrl(href); else @@ -2728,16 +2529,6 @@ void QTextControlPrivate::activateLinkUnderCursor(QString href) 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); @@ -2974,7 +2765,7 @@ bool QTextControl::cursorOn() const return d->cursorOn; } -QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget *widget) const +QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext() const { Q_D(const QTextControl); @@ -2994,31 +2785,28 @@ QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget if (!d->dndFeedbackCursor.isNull()) ctx.cursorPosition = d->dndFeedbackCursor.position(); #ifdef QT_KEYPAD_NAVIGATION - if (!QApplication::keypadNavigationEnabled() || d->hasEditFocus) + if (!QGuiApplication::keypadNavigationEnabled() || d->hasEditFocus) #endif if (d->cursor.hasSelection()) { QAbstractTextDocumentLayout::Selection selection; selection.cursor = d->cursor; - if (d->cursorIsFocusIndicator) { + if (0 && d->cursorIsFocusIndicator) { +#if 0 + // ### QStyleOption opt; opt.palette = ctx.palette; QStyleHintReturnVariant ret; - QStyle *style = QApplication::style(); + QStyle *style = QGuiApplication::style(); if (widget) style = widget->style(); style->styleHint(QStyle::SH_TextControl_FocusIndicatorTextCharFormat, &opt, widget, &ret); selection.format = qvariant_cast<QTextFormat>(ret.variant).toCharFormat(); +#endif } 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)) + if (fullWidthSelection) selection.format.setProperty(QTextFormat::FullWidthSelection, true); } ctx.selections.append(selection); @@ -3027,11 +2815,11 @@ QAbstractTextDocumentLayout::PaintContext QTextControl::getPaintContext(QWidget return ctx; } -void QTextControl::drawContents(QPainter *p, const QRectF &rect, QWidget *widget) +void QTextControl::drawContents(QPainter *p, const QRectF &rect) { Q_D(QTextControl); p->save(); - QAbstractTextDocumentLayout::PaintContext ctx = getPaintContext(widget); + QAbstractTextDocumentLayout::PaintContext ctx = getPaintContext(); if (rect.isValid()) p->setClipRect(rect, Qt::IntersectClip); ctx.clip = rect; @@ -3045,16 +2833,21 @@ void QTextControlPrivate::_q_copyLink() #ifndef QT_NO_CLIPBOARD QMimeData *md = new QMimeData; md->setText(linkToCopy); - QApplication::clipboard()->setMimeData(md); + QGuiApplication::clipboard()->setMimeData(md); #endif } QInputContext *QTextControlPrivate::inputContext() { - QInputContext *ctx = contextWidget->inputContext(); - if (!ctx && contextWidget->parentWidget()) - ctx = contextWidget->parentWidget()->inputContext(); +#if 0 + // ### + QInputContext *ctx = contextObject->inputContext(); + if (!ctx && contextObject->parentWidget()) + ctx = contextObject->parentWidget()->inputContext(); return ctx; +#else + return 0; +#endif } int QTextControl::hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const @@ -3069,59 +2862,7 @@ QRectF QTextControl::blockBoundingRect(const QTextBlock &block) const 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 { diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index c5ed0ee1e0..bb91415fd2 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -57,18 +57,11 @@ #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 @@ -77,12 +70,12 @@ QT_MODULE(Gui) class QStyleSheet; class QTextDocument; -class QMenu; class QTextControlPrivate; class QMimeData; class QAbstractScrollArea; class QEvent; class QTimerEvent; +class QPagedPaintDevice; class Q_GUI_EXPORT QTextControl : public QObject { @@ -103,6 +96,9 @@ public: explicit QTextControl(QTextDocument *doc, QObject *parent = 0); virtual ~QTextControl(); + void setView(QObject *view); + QObject *view() const; + void setDocument(QTextDocument *document); QTextDocument *document() const; @@ -129,9 +125,6 @@ public: 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; @@ -153,10 +146,8 @@ public: 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 setExtraSelections(const QVector<QAbstractTextDocumentLayout::Selection> &selections); + QVector<QAbstractTextDocumentLayout::Selection> extraSelections() const; void setTextWidth(qreal width); qreal textWidth() const; @@ -181,13 +172,11 @@ public: bool isWordSelectionEnabled() const; void setWordSelectionEnabled(bool enabled); -#ifndef QT_NO_PRINTER - void print(QPrinter *printer) const; -#endif + void print(QPagedPaintDevice *printer) const; virtual int hitTest(const QPointF &point, Qt::HitTestAccuracy accuracy) const; virtual QRectF blockBoundingRect(const QTextBlock &block) const; - QAbstractTextDocumentLayout::PaintContext getPaintContext(QWidget *widget) const; + QAbstractTextDocumentLayout::PaintContext getPaintContext() const; public Q_SLOTS: void setPlainText(const QString &text); @@ -241,11 +230,11 @@ public: 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); + virtual void processEvent(QEvent *e, const QMatrix &matrix); + void processEvent(QEvent *e, const QPointF &coordinateOffset = QPointF()); // control methods - void drawContents(QPainter *painter, const QRectF &rect = QRectF(), QWidget *widget = 0); + void drawContents(QPainter *painter, const QRectF &rect = QRectF()); void setFocus(bool focus, Qt::FocusReason = Qt::OtherFocusReason); @@ -277,22 +266,6 @@ private: }; -#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 { @@ -312,4 +285,4 @@ QT_END_NAMESPACE QT_END_HEADER -#endif // QTEXTCONTROL_H +#endif // QTextControl_H diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index 1d7f9e9945..9c7ab56395 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -54,10 +54,8 @@ // #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" @@ -160,16 +158,12 @@ public: 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); + bool dropEvent(const QMimeData *mimeData, const QPointF &pos, Qt::DropAction dropAction, QObject *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(); @@ -194,7 +188,7 @@ public: bool mightStartDrag; QPoint dragStartPos; - QPointer<QWidget> contextWidget; + QPointer<QObject> contextObject; bool lastSelectionState; @@ -235,4 +229,4 @@ public: QT_END_NAMESPACE -#endif // QTEXTCONTROL_P_H +#endif // QTextControl_P_H diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index 697899bcfa..bc4cdb5fb6 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -228,9 +228,10 @@ public: private: QSharedDataPointer<QTextCursorPrivate> d; + friend class QTextCursorPrivate; friend class QTextDocumentFragmentPrivate; friend class QTextCopyHelper; - friend class QTextControlPrivate; + friend class QWidgetTextControlPrivate; }; QT_END_NAMESPACE diff --git a/src/gui/text/qtextcursor_p.h b/src/gui/text/qtextcursor_p.h index aae512b0d1..c612169acf 100644 --- a/src/gui/text/qtextcursor_p.h +++ b/src/gui/text/qtextcursor_p.h @@ -61,13 +61,15 @@ QT_BEGIN_NAMESPACE -class QTextCursorPrivate : public QSharedData +class Q_GUI_EXPORT QTextCursorPrivate : public QSharedData { public: QTextCursorPrivate(QTextDocumentPrivate *p); QTextCursorPrivate(const QTextCursorPrivate &rhs); ~QTextCursorPrivate(); + static inline QTextCursorPrivate *getPrivate(QTextCursor *c) { return c->d; } + enum AdjustResult { CursorMoved, CursorUnchanged }; AdjustResult adjustPosition(int positionOfChange, int charsAddedOrRemoved, QTextUndoCommand::Operation op); diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 143dc1ab8c..c1714edb0c 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -51,22 +51,20 @@ #include <qvarlengtharray.h> #include <qtextcodec.h> #include <qthread.h> +#include <qcoreapplication.h> + #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" -#include <private/qprinter_p.h> #include <private/qabstracttextdocumentlayout_p.h> +#include "qpagedpaintdevice.h" +#include "private/qpagedpaintdevice_p.h" #include <limits.h> @@ -1696,7 +1694,7 @@ static void printPage(int index, QPainter *painter, const QTextDocument *doc, co } /*! - Prints the document to the given \a printer. The QPrinter must be + Prints the document to the given \a device. The QPageablePaintDevice must be set up before being used with this function. This is only a convenience method to print the whole document to the printer. @@ -1706,33 +1704,32 @@ static void printPage(int index, QPainter *painter, const QTextDocument *doc, co If the document is not paginated, like for example a document used in a QTextEdit, then a temporary copy of the document is created and the copy is broken into - multiple pages according to the size of the QPrinter's paperRect(). By default + multiple pages according to the size of the paint device's paperRect(). By default a 2 cm margin is set around the document contents. In addition the current page number is printed at the bottom of each page. - Note that QPrinter::Selection is not supported as print range with this function since - the selection is a property of QTextCursor. If you have a QTextEdit associated with - your QTextDocument then you can use QTextEdit's print() function because QTextEdit has - access to the user's selection. - \sa QTextEdit::print() */ -void QTextDocument::print(QPrinter *printer) const +void QTextDocument::print(QPagedPaintDevice *printer) const { Q_D(const QTextDocument); - if (!printer || !printer->isValid()) + if (!printer) return; - if (!d->title.isEmpty()) - printer->setDocName(d->title); - bool documentPaginated = d->pageSize.isValid() && !d->pageSize.isNull() && d->pageSize.height() != INT_MAX; - if (!documentPaginated && !printer->fullPage() && !printer->d_func()->hasCustomPageMargins) - printer->setPageMargins(23.53, 23.53, 23.53, 23.53, QPrinter::Millimeter); + QPagedPaintDevicePrivate *pd = QPagedPaintDevicePrivate::get(printer); + + // ### set page size to paginated size? + QPagedPaintDevice::Margins m = printer->margins(); + if (!documentPaginated && m.left == 0. && m.right == 0. && m.top == 0. && m.bottom == 0.) { + m.left = m.right = m.top = m.bottom = 2.; + printer->setMargins(m); + } + // ### use the margins correctly QPainter p(printer); @@ -1767,7 +1764,7 @@ void QTextDocument::print(QPrinter *printer) const scaledPageSize.rwidth() *= dpiScaleX; scaledPageSize.rheight() *= dpiScaleY; - const QSizeF printerPageSize(printer->pageRect().size()); + const QSizeF printerPageSize(printer->width(), printer->height()); // scale to page p.scale(printerPageSize.width() / scaledPageSize.width(), @@ -1789,17 +1786,12 @@ void QTextDocument::print(QPrinter *printer) const layout->d_func()->handlers = documentLayout()->d_func()->handlers; int dpiy = p.device()->logicalDpiY(); - int margin = 0; - if (printer->fullPage() && !printer->d_func()->hasCustomPageMargins) { - // for compatibility - margin = (int) ((2/2.54)*dpiy); // 2 cm margins - QTextFrameFormat fmt = doc->rootFrame()->frameFormat(); - fmt.setMargin(margin); - doc->rootFrame()->setFrameFormat(fmt); - } + int margin = (int) ((2/2.54)*dpiy); // 2 cm margins + QTextFrameFormat fmt = doc->rootFrame()->frameFormat(); + fmt.setMargin(margin); + doc->rootFrame()->setFrameFormat(fmt); - QRectF pageRect(printer->pageRect()); - body = QRectF(0, 0, pageRect.width(), pageRect.height()); + body = QRectF(0, 0, printer->width(), printer->height()); pageNumberPos = QPointF(body.width() - margin, body.height() - margin + QFontMetrics(doc->defaultFont(), p.device()).ascent() @@ -1807,18 +1799,8 @@ void QTextDocument::print(QPrinter *printer) const clonedDoc->setPageSize(body.size()); } - int docCopies; - int pageCopies; - if (printer->collateCopies() == true){ - docCopies = 1; - pageCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount(); - } else { - docCopies = printer->supportsMultipleCopies() ? 1 : printer->copyCount(); - pageCopies = 1; - } - - int fromPage = printer->fromPage(); - int toPage = printer->toPage(); + int fromPage = pd->fromPage; + int toPage = pd->toPage; bool ascending = true; if (fromPage == 0 && toPage == 0) { @@ -1835,39 +1817,27 @@ void QTextDocument::print(QPrinter *printer) const return; } - if (printer->pageOrder() == QPrinter::LastPageFirst) { - int tmp = fromPage; - fromPage = toPage; - toPage = tmp; - ascending = false; - } - - for (int i = 0; i < docCopies; ++i) { +// if (printer->pageOrder() == QPrinter::LastPageFirst) { +// int tmp = fromPage; +// fromPage = toPage; +// toPage = tmp; +// ascending = false; +// } - int page = fromPage; - while (true) { - for (int j = 0; j < pageCopies; ++j) { - if (printer->printerState() == QPrinter::Aborted - || printer->printerState() == QPrinter::Error) - return; - printPage(page, &p, doc, body, pageNumberPos); - if (j < pageCopies - 1) - printer->newPage(); - } + int page = fromPage; + while (true) { + printPage(page, &p, doc, body, pageNumberPos); - if (page == toPage) - break; - - if (ascending) - ++page; - else - --page; + if (page == toPage) + break; - printer->newPage(); - } + if (ascending) + ++page; + else + --page; - if ( i < docCopies - 1) - printer->newPage(); + if (!printer->newPage()) + return; } } #endif @@ -1971,6 +1941,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); @@ -1978,10 +1950,11 @@ QVariant QTextDocument::loadResource(int type, const QUrl &name) } #endif #ifndef QT_NO_TEXTCONTROL - else if (QTextControl *control = qobject_cast<QTextControl *>(parent())) { + else if (QWidgetTextControl *control = qobject_cast<QWidgetTextControl *>(parent())) { 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/qtextdocument.h b/src/gui/text/qtextdocument.h index 268b72e514..363d7abb21 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -57,7 +57,7 @@ class QTextFormatCollection; class QTextListFormat; class QRect; class QPainter; -class QPrinter; +class QPagedPaintDevice; class QAbstractTextDocumentLayout; class QPoint; class QTextObject; @@ -206,9 +206,7 @@ public: bool isModified() const; -#ifndef QT_NO_PRINTER - void print(QPrinter *printer) const; -#endif + void print(QPagedPaintDevice *printer) const; enum ResourceType { HtmlResource = 1, diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index a50798834a..04bdfa8d30 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/qtextdocumentlayout_p.h b/src/gui/text/qtextdocumentlayout_p.h index 620b9bd7dd..b103d886be 100644 --- a/src/gui/text/qtextdocumentlayout_p.h +++ b/src/gui/text/qtextdocumentlayout_p.h @@ -63,7 +63,7 @@ class QTextListFormat; class QTextDocumentLayoutPrivate; -class Q_AUTOTEST_EXPORT QTextDocumentLayout : public QAbstractTextDocumentLayout +class Q_GUI_EXPORT QTextDocumentLayout : public QAbstractTextDocumentLayout { Q_DECLARE_PRIVATE(QTextDocumentLayout) Q_OBJECT diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index f7b7aa28a1..58cccfcbf7 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> @@ -1629,7 +1629,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 251d9b5072..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$ -** GNU Lesser General Public License Usage -** 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. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** $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 6e82de8f5c..325623fc63 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -93,7 +93,7 @@ class QAbstractTextDocumentLayout; // * negative yoff means the following stuff is drawn higher up. // the characters bounding rect is given by QRect(x,y,width,height), its advance by // xoo and yoff -struct glyph_metrics_t +struct Q_GUI_EXPORT glyph_metrics_t { inline glyph_metrics_t() : x(100000), y(100000) {} @@ -426,7 +426,7 @@ public: InLayout, LayoutFailed, }; - struct LayoutData { + struct Q_GUI_EXPORT LayoutData { LayoutData(const QString &str, void **stack_memory, int mem_size); LayoutData(); ~LayoutData(); @@ -650,7 +650,7 @@ private: int getClusterLength(unsigned short *logClusters, const HB_CharAttributes *attributes, int from, int to, int glyph_pos, int *start); }; -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 5b60dfaf69..41dc1130ee 100644 --- a/src/gui/text/qtexthtmlparser.cpp +++ b/src/gui/text/qtexthtmlparser.cpp @@ -43,10 +43,10 @@ #include <qbytearray.h> #include <qtextcodec.h> -#include <qapplication.h> #include <qstack.h> #include <qdebug.h> #include <qthread.h> +#include <qcoreapplication.h> #include "qtextdocument.h" #include "qtextformat_p.h" @@ -1055,7 +1055,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 +1406,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 78761184df..fcc13a58ff 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 8c5e63da54..25d7de827e 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -44,14 +44,12 @@ #include <qthread.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 d384cbeaee..fe58583d04 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 eb5937a493..5e5f8e31c8 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -9,9 +9,8 @@ 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/qlinecontrol_p.h \ + text/qtextengine_p.h \ text/qtextlayout.h \ text/qtextformat.h \ text/qtextformat_p.h \ @@ -24,7 +23,9 @@ HEADERS += \ text/qtexthtmlparser_p.h \ text/qabstracttextdocumentlayout.h \ text/qtextdocumentlayout_p.h \ - text/qtextcursor.h \ + text/qtextcontrol_p.h \ + text/qtextcontrol_p_p.h \ + text/qtextcursor.h \ text/qtextcursor_p.h \ text/qtextdocumentfragment.h \ text/qtextdocumentfragment_p.h \ @@ -52,8 +53,9 @@ SOURCES += \ text/qfontsubset.cpp \ text/qfontmetrics.cpp \ text/qfontdatabase.cpp \ - text/qtextcontrol.cpp \ - text/qtextengine.cpp \ + text/qlinecontrol.cpp \ + text/qtextcontrol.cpp \ + text/qtextengine.cpp \ text/qtextlayout.cpp \ text/qtextformat.cpp \ text/qtextobject.cpp \ @@ -78,7 +80,7 @@ SOURCES += \ text/qrawfont.cpp \ text/qglyphrun.cpp -win32 { +win32:!qpa { SOURCES += \ text/qfont_win.cpp \ text/qfontengine_win.cpp \ @@ -104,7 +106,7 @@ unix:x11 { text/qrawfont_ft.cpp } -!embedded:!qpa:!x11:mac { +!qpa:!x11:mac { HEADERS += \ text/qfontengine_mac_p.h OBJECTIVE_HEADERS += \ @@ -120,22 +122,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 \ @@ -233,9 +219,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 |