mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2024-11-24 03:35:54 +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/function.h \
|
||||
src/textpathitem.h \
|
||||
src/textitem.h
|
||||
src/textitem.h \
|
||||
src/font.h
|
||||
SOURCES += src/pbfplugin.cpp \
|
||||
src/pbfhandler.cpp \
|
||||
src/gzip.cpp \
|
||||
@ -27,7 +28,8 @@ SOURCES += src/pbfplugin.cpp \
|
||||
src/text.cpp \
|
||||
src/function.cpp \
|
||||
src/textpathitem.cpp \
|
||||
src/textitem.cpp
|
||||
src/textitem.cpp \
|
||||
src/font.cpp
|
||||
RESOURCES += pbfplugin.qrc
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 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 {
|
||||
public:
|
||||
FunctionF(qreal deflt = 0) : _default(deflt), _base(1.0) {}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QDebug>
|
||||
#include "text.h"
|
||||
#include "color.h"
|
||||
#include "font.h"
|
||||
#include "tile.h"
|
||||
#include "style.h"
|
||||
|
||||
@ -134,7 +135,7 @@ bool Style::Layer::Filter::match(const QVariantMap &tags) const
|
||||
}
|
||||
|
||||
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())
|
||||
_fillOpacity = FunctionF(json["fill-opacity"].toDouble());
|
||||
@ -156,7 +157,9 @@ Style::Layer::Paint::Paint(const QJsonObject &json)
|
||||
&& json["fill-outline-color"].isObject())
|
||||
_fillOutlineColor = FunctionC(json["fill-outline-color"].toObject());
|
||||
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")) {
|
||||
_fillColor = 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) {
|
||||
case Fill:
|
||||
return _fillAntialias;
|
||||
return _fillAntialias.value(zoom);
|
||||
case Line:
|
||||
return true;
|
||||
default:
|
||||
@ -297,7 +300,8 @@ Style::Layer::Layout::Layout(const QJsonObject &json)
|
||||
_textMaxWidth = FunctionF(json["text-max-angle"].toObject());
|
||||
else if (json.contains("text-max-angle") && json["text-max-angle"].isDouble())
|
||||
_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())
|
||||
_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 font;
|
||||
font.setPixelSize(_textSize.value(zoom));
|
||||
QFont font(_font);
|
||||
font.setPixelSize(qRound(_textSize.value(zoom)));
|
||||
|
||||
return font;
|
||||
}
|
||||
@ -385,7 +389,7 @@ void Style::Layer::drawPath(int zoom, const QPainterPath &path,
|
||||
pen.setCapStyle(_layout.lineCap());
|
||||
|
||||
QPainter &p = tile.painter();
|
||||
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type));
|
||||
p.setRenderHint(QPainter::Antialiasing, _paint.antialias(_type, zoom));
|
||||
p.setPen(pen);
|
||||
p.setBrush(brush);
|
||||
p.setOpacity(_paint.opacity(_type, zoom));
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <QSet>
|
||||
#include <QPen>
|
||||
#include <QBrush>
|
||||
#include <QFont>
|
||||
#include "function.h"
|
||||
|
||||
|
||||
@ -102,19 +103,19 @@ private:
|
||||
FunctionF _textMaxAngle;
|
||||
Qt::PenCapStyle _lineCap;
|
||||
Qt::PenJoinStyle _lineJoin;
|
||||
QFont _font;
|
||||
bool _capitalize;
|
||||
};
|
||||
|
||||
class Paint {
|
||||
public:
|
||||
Paint() : _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0),
|
||||
_fillAntialias(true) {}
|
||||
Paint() : _fillOpacity(1.0), _lineOpacity(1.0), _lineWidth(1.0) {}
|
||||
Paint(const QJsonObject &json);
|
||||
|
||||
QPen pen(Layer::Type type, int zoom) const;
|
||||
QBrush brush(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:
|
||||
FunctionC _textColor;
|
||||
@ -125,7 +126,7 @@ private:
|
||||
FunctionF _fillOpacity;
|
||||
FunctionF _lineOpacity;
|
||||
FunctionF _lineWidth;
|
||||
bool _fillAntialias;
|
||||
FunctionB _fillAntialias;
|
||||
QVector<qreal> _lineDasharray;
|
||||
};
|
||||
|
||||
|
@ -10,9 +10,16 @@ TextItem::TextItem(const QString &text, const QPointF &pos, const QFont &font,
|
||||
{
|
||||
QFontMetrics fm(font);
|
||||
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);
|
||||
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());
|
||||
_boundingRect = QRectF(0, 0, br.width(), br.height());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user