mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2024-11-27 21:24:48 +01:00
Added font properties handling
Added support for boolean functions
This commit is contained in:
parent
f376a9235a
commit
c97f2235a9
@ -17,7 +17,8 @@ HEADERS += src/pbfhandler.h \
|
|||||||
src/tile.h \
|
src/tile.h \
|
||||||
src/function.h \
|
src/function.h \
|
||||||
src/textpathitem.h \
|
src/textpathitem.h \
|
||||||
src/textitem.h
|
src/textitem.h \
|
||||||
|
src/font.h
|
||||||
SOURCES += src/pbfplugin.cpp \
|
SOURCES += src/pbfplugin.cpp \
|
||||||
src/pbfhandler.cpp \
|
src/pbfhandler.cpp \
|
||||||
src/gzip.cpp \
|
src/gzip.cpp \
|
||||||
@ -27,7 +28,8 @@ SOURCES += src/pbfplugin.cpp \
|
|||||||
src/text.cpp \
|
src/text.cpp \
|
||||||
src/function.cpp \
|
src/function.cpp \
|
||||||
src/textpathitem.cpp \
|
src/textpathitem.cpp \
|
||||||
src/textitem.cpp
|
src/textitem.cpp \
|
||||||
|
src/font.cpp
|
||||||
RESOURCES += pbfplugin.qrc
|
RESOURCES += pbfplugin.qrc
|
||||||
|
|
||||||
unix {
|
unix {
|
||||||
|
61
src/font.cpp
Normal file
61
src/font.cpp
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include <QString>
|
||||||
|
#include <QFontDatabase>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include "font.h"
|
||||||
|
|
||||||
|
|
||||||
|
static const QStringList &fonts()
|
||||||
|
{
|
||||||
|
static QStringList l(QFontDatabase().families());
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString fontFamily(const QString &str)
|
||||||
|
{
|
||||||
|
const QStringList &fl = fonts();
|
||||||
|
|
||||||
|
QString family(str.left(str.lastIndexOf(' ')));
|
||||||
|
for (int j = 0; j < fl.size(); j++)
|
||||||
|
if (fl.at(j).startsWith(family))
|
||||||
|
return family;
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setType(QFont &font, const QString &str)
|
||||||
|
{
|
||||||
|
QString type(str.right(str.length() - str.lastIndexOf(' ') - 1));
|
||||||
|
|
||||||
|
if (type == "Italic")
|
||||||
|
font.setItalic(true);
|
||||||
|
else if (type == "Bold")
|
||||||
|
font.setWeight(QFont::Bold);
|
||||||
|
else if (type == "Medium")
|
||||||
|
font.setWeight(QFont::Medium);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFont Font::fromJsonArray(const QJsonArray &json)
|
||||||
|
{
|
||||||
|
if (json.isEmpty())
|
||||||
|
return QFont();
|
||||||
|
|
||||||
|
// Try exact match from the layout font list
|
||||||
|
for (int i = 0; i < json.size(); i++) {
|
||||||
|
if (!json.at(i).isString())
|
||||||
|
return QFont();
|
||||||
|
QString str(json.at(i).toString());
|
||||||
|
QString family(fontFamily(str));
|
||||||
|
if (!family.isNull()) {
|
||||||
|
QFont font(family);
|
||||||
|
setType(font, str);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use Qt's font matching logic on the first font in the list
|
||||||
|
QString str(json.first().toString());
|
||||||
|
QFont font(str.left(str.lastIndexOf(' ')));
|
||||||
|
setType(font, str);
|
||||||
|
|
||||||
|
return font;
|
||||||
|
}
|
13
src/font.h
Normal file
13
src/font.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef FONT_H
|
||||||
|
#define FONT_H
|
||||||
|
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
|
class QJsonArray;
|
||||||
|
|
||||||
|
namespace Font
|
||||||
|
{
|
||||||
|
QFont fromJsonArray(const QJsonArray &json);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // FONT_H
|
@ -117,3 +117,36 @@ QColor FunctionC::value(qreal x) const
|
|||||||
|
|
||||||
return _stops.last().second;
|
return _stops.last().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FunctionB::FunctionB(const QJsonObject &json, bool dflt) : _default(dflt)
|
||||||
|
{
|
||||||
|
if (!(json.contains("stops") && json["stops"].isArray()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QJsonArray stops = json["stops"].toArray();
|
||||||
|
for (int i = 0; i < stops.size(); i++) {
|
||||||
|
if (!stops.at(i).isArray())
|
||||||
|
return;
|
||||||
|
QJsonArray stop = stops.at(i).toArray();
|
||||||
|
if (stop.size() != 2)
|
||||||
|
return;
|
||||||
|
_stops.append(QPair<qreal, bool>(stop.at(0).toDouble(),
|
||||||
|
stop.at(1).toBool()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FunctionB::value(qreal x) const
|
||||||
|
{
|
||||||
|
if (_stops.isEmpty())
|
||||||
|
return _default;
|
||||||
|
|
||||||
|
QPair<qreal, bool> v0(_stops.first());
|
||||||
|
for (int i = 0; i < _stops.size(); i++) {
|
||||||
|
if (x < _stops.at(i).first)
|
||||||
|
return v0.second;
|
||||||
|
else
|
||||||
|
v0 = _stops.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _stops.last().second;
|
||||||
|
}
|
||||||
|
@ -7,6 +7,18 @@
|
|||||||
|
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
|
|
||||||
|
class FunctionB {
|
||||||
|
public:
|
||||||
|
FunctionB(bool deflt = true) : _default(deflt) {}
|
||||||
|
FunctionB(const QJsonObject &json, bool dflt = true);
|
||||||
|
|
||||||
|
bool value(qreal x) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<QPair<qreal, bool> > _stops;
|
||||||
|
bool _default;
|
||||||
|
};
|
||||||
|
|
||||||
class FunctionF {
|
class FunctionF {
|
||||||
public:
|
public:
|
||||||
FunctionF(qreal deflt = 0) : _default(deflt), _base(1.0) {}
|
FunctionF(qreal deflt = 0) : _default(deflt), _base(1.0) {}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include "text.h"
|
#include "text.h"
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "font.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
|
|
||||||
@ -134,7 +135,7 @@ bool Style::Layer::Filter::match(const QVariantMap &tags) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
Style::Layer::Paint::Paint(const QJsonObject &json)
|
Style::Layer::Paint::Paint(const QJsonObject &json)
|
||||||
: _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0), _fillAntialias(true)
|
: _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0)
|
||||||
{
|
{
|
||||||
if (json.contains("fill-opacity") && json["fill-opacity"].isDouble())
|
if (json.contains("fill-opacity") && json["fill-opacity"].isDouble())
|
||||||
_fillOpacity = FunctionF(json["fill-opacity"].toDouble());
|
_fillOpacity = FunctionF(json["fill-opacity"].toDouble());
|
||||||
@ -156,7 +157,9 @@ Style::Layer::Paint::Paint(const QJsonObject &json)
|
|||||||
&& json["fill-outline-color"].isObject())
|
&& json["fill-outline-color"].isObject())
|
||||||
_fillOutlineColor = FunctionC(json["fill-outline-color"].toObject());
|
_fillOutlineColor = FunctionC(json["fill-outline-color"].toObject());
|
||||||
if (json.contains("fill-antialias") && json["fill-antialias"].isBool())
|
if (json.contains("fill-antialias") && json["fill-antialias"].isBool())
|
||||||
_fillAntialias = json["fill-antialias"].toBool();
|
_fillAntialias = FunctionB(json["fill-antialias"].toBool());
|
||||||
|
else if (json.contains("fill-antialias") && json["fill-antialias"].isObject())
|
||||||
|
_fillAntialias = FunctionB(json["fill-antialias"].toObject());
|
||||||
if (json.contains("fill-pattern")) {
|
if (json.contains("fill-pattern")) {
|
||||||
_fillColor = FunctionC(QColor());
|
_fillColor = FunctionC(QColor());
|
||||||
_fillOutlineColor = FunctionC(QColor());
|
_fillOutlineColor = FunctionC(QColor());
|
||||||
@ -256,11 +259,11 @@ qreal Style::Layer::Paint::opacity(Type type, int zoom) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Style::Layer::Paint::antialias(Layer::Type type) const
|
bool Style::Layer::Paint::antialias(Layer::Type type, int zoom) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Fill:
|
case Fill:
|
||||||
return _fillAntialias;
|
return _fillAntialias.value(zoom);
|
||||||
case Line:
|
case Line:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@ -297,7 +300,8 @@ Style::Layer::Layout::Layout(const QJsonObject &json)
|
|||||||
_textMaxWidth = FunctionF(json["text-max-angle"].toObject());
|
_textMaxWidth = FunctionF(json["text-max-angle"].toObject());
|
||||||
else if (json.contains("text-max-angle") && json["text-max-angle"].isDouble())
|
else if (json.contains("text-max-angle") && json["text-max-angle"].isDouble())
|
||||||
_textMaxWidth = json["text-max-angle"].toDouble();
|
_textMaxWidth = json["text-max-angle"].toDouble();
|
||||||
|
if (json.contains("text-font") && json["text-font"].isArray())
|
||||||
|
_font = Font::fromJsonArray(json["text-font"].toArray());
|
||||||
if (json.contains("text-transform") && json["text-transform"].isString())
|
if (json.contains("text-transform") && json["text-transform"].isString())
|
||||||
_capitalize = json["text-transform"].toString() == "uppercase";
|
_capitalize = json["text-transform"].toString() == "uppercase";
|
||||||
|
|
||||||
@ -317,8 +321,8 @@ Style::Layer::Layout::Layout(const QJsonObject &json)
|
|||||||
|
|
||||||
QFont Style::Layer::Layout::font(int zoom) const
|
QFont Style::Layer::Layout::font(int zoom) const
|
||||||
{
|
{
|
||||||
QFont font;
|
QFont font(_font);
|
||||||
font.setPixelSize(_textSize.value(zoom));
|
font.setPixelSize(qRound(_textSize.value(zoom)));
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
@ -385,7 +389,7 @@ void Style::Layer::drawPath(int zoom, const QPainterPath &path,
|
|||||||
pen.setCapStyle(_layout.lineCap());
|
pen.setCapStyle(_layout.lineCap());
|
||||||
|
|
||||||
QPainter &p = tile.painter();
|
QPainter &p = tile.painter();
|
||||||
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type));
|
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, zoom));
|
||||||
p.setPen(pen);
|
p.setPen(pen);
|
||||||
p.setBrush(brush);
|
p.setBrush(brush);
|
||||||
p.setOpacity(_paint.opacity(_type, zoom));
|
p.setOpacity(_paint.opacity(_type, zoom));
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QPen>
|
#include <QPen>
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
|
#include <QFont>
|
||||||
#include "function.h"
|
#include "function.h"
|
||||||
|
|
||||||
|
|
||||||
@ -102,19 +103,19 @@ private:
|
|||||||
FunctionF _textMaxAngle;
|
FunctionF _textMaxAngle;
|
||||||
Qt::PenCapStyle _lineCap;
|
Qt::PenCapStyle _lineCap;
|
||||||
Qt::PenJoinStyle _lineJoin;
|
Qt::PenJoinStyle _lineJoin;
|
||||||
|
QFont _font;
|
||||||
bool _capitalize;
|
bool _capitalize;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Paint {
|
class Paint {
|
||||||
public:
|
public:
|
||||||
Paint() : _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0),
|
Paint() : _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0) {}
|
||||||
_fillAntialias(true) {}
|
|
||||||
Paint(const QJsonObject &json);
|
Paint(const QJsonObject &json);
|
||||||
|
|
||||||
QPen pen(Layer::Type type, int zoom) const;
|
QPen pen(Layer::Type type, int zoom) const;
|
||||||
QBrush brush(Layer::Type type, int zoom) const;
|
QBrush brush(Layer::Type type, int zoom) const;
|
||||||
qreal opacity(Layer::Type type, int zoom) const;
|
qreal opacity(Layer::Type type, int zoom) const;
|
||||||
bool antialias(Layer::Type type) const;
|
bool antialias(Layer::Type type, int zoom) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FunctionC _textColor;
|
FunctionC _textColor;
|
||||||
@ -125,7 +126,7 @@ private:
|
|||||||
FunctionF _fillOpacity;
|
FunctionF _fillOpacity;
|
||||||
FunctionF _lineOpacity;
|
FunctionF _lineOpacity;
|
||||||
FunctionF _lineWidth;
|
FunctionF _lineWidth;
|
||||||
bool _fillAntialias;
|
FunctionB _fillAntialias;
|
||||||
QVector<qreal> _lineDasharray;
|
QVector<qreal> _lineDasharray;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -10,9 +10,16 @@ TextItem::TextItem(const QString &text, const QPointF &pos, const QFont &font,
|
|||||||
{
|
{
|
||||||
QFontMetrics fm(font);
|
QFontMetrics fm(font);
|
||||||
int limit = font.pixelSize() * maxTextWidth;
|
int limit = font.pixelSize() * maxTextWidth;
|
||||||
|
// Italic fonts overflow the computed bounding rect, so reduce it
|
||||||
|
// a little bit.
|
||||||
|
if (font.italic())
|
||||||
|
limit -= fm.averageCharWidth();
|
||||||
|
|
||||||
QRect br = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, text);
|
QRect br = fm.boundingRect(QRect(0, 0, limit, 0), FLAGS, text);
|
||||||
Q_ASSERT(br.isValid());
|
Q_ASSERT(br.isValid());
|
||||||
|
// Expand the bounding rect back to the real content size
|
||||||
|
if (font.italic())
|
||||||
|
br.adjust(-fm.averageCharWidth() / 2, 0, fm.averageCharWidth() / 2, 0);
|
||||||
setPos((pos - QPointF(br.width() / 2.0, br.height() / 2.0)).toPoint());
|
setPos((pos - QPointF(br.width() / 2.0, br.height() / 2.0)).toPoint());
|
||||||
_boundingRect = QRectF(0, 0, br.width(), br.height());
|
_boundingRect = QRectF(0, 0, br.width(), br.height());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user