Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
33
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/README.md
vendored
Normal file
33
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/README.md
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# font-view
|
||||
|
||||
A simple tool to preview all glyphs in the font using `ttf-parser`, `freetype` and `harfbuzz`.
|
||||
|
||||
## Build
|
||||
|
||||
```sh
|
||||
# build ttf-parser C API first
|
||||
cargo build --release --manifest-path ../../c-api/Cargo.toml
|
||||
|
||||
# build only with ttf-parser support
|
||||
qmake
|
||||
make
|
||||
|
||||
# or build with freetype support
|
||||
qmake DEFINES+=WITH_FREETYPE
|
||||
make
|
||||
|
||||
# or build with harfbuzz support
|
||||
# note that harfbuzz should be built from sources using meson,
|
||||
# because we're using an unstable API
|
||||
#
|
||||
# build harfbuzz first
|
||||
meson builddir -Dexperimental_api=true --buildtype release
|
||||
ninja -C builddir
|
||||
# build font-view
|
||||
qmake DEFINES+=WITH_HARFBUZZ HARFBUZZ_SRC=/path/to/harfbuzz-master/
|
||||
make
|
||||
|
||||
# or with all
|
||||
qmake DEFINES+=WITH_FREETYPE DEFINES+=WITH_HARFBUZZ HARFBUZZ_SRC=/path/to/harfbuzz-master/
|
||||
make
|
||||
```
|
||||
50
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/font-view.pro
vendored
Normal file
50
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/font-view.pro
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
QT += widgets
|
||||
|
||||
CONFIG += c++14
|
||||
|
||||
CONFIG(release, debug|release): LIBS += -L$$PWD/../../c-api/target/release/ -lttfparser
|
||||
else:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../c-api/target/debug/ -lttfparser
|
||||
|
||||
INCLUDEPATH += $$PWD/../../c-api
|
||||
DEPENDPATH += $$PWD/../../c-api
|
||||
|
||||
SOURCES += \
|
||||
glyphsview.cpp \
|
||||
main.cpp \
|
||||
mainwindow.cpp \
|
||||
ttfparserfont.cpp
|
||||
|
||||
HEADERS += \
|
||||
glyph.h \
|
||||
glyphsview.h \
|
||||
mainwindow.h \
|
||||
ttfparserfont.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui
|
||||
|
||||
macx {
|
||||
QT_CONFIG -= no-pkg-config
|
||||
PKG_CONFIG = /opt/homebrew/bin/pkg-config
|
||||
}
|
||||
|
||||
# qmake DEFINES+=WITH_FREETYPE
|
||||
contains(DEFINES, WITH_FREETYPE) {
|
||||
SOURCES += freetypefont.cpp
|
||||
HEADERS += freetypefont.h
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += freetype2
|
||||
}
|
||||
|
||||
# qmake DEFINES+=WITH_HARFBUZZ HARFBUZZ_SRC=/path/to/harfbuzz-master/
|
||||
contains(DEFINES, WITH_HARFBUZZ) {
|
||||
DEFINES += HB_EXPERIMENTAL_API
|
||||
|
||||
SOURCES += harfbuzzfont.cpp
|
||||
HEADERS += harfbuzzfont.h
|
||||
|
||||
# harfbuzz should be built with meson
|
||||
LIBS += -L$$HARFBUZZ_SRC/builddir/src/ -lharfbuzz
|
||||
INCLUDEPATH += $$HARFBUZZ_SRC/src
|
||||
}
|
||||
175
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/freetypefont.cpp
vendored
Normal file
175
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/freetypefont.cpp
vendored
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
// Based on https://www.freetype.org/freetype2/docs/tutorial/example5.cpp
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "freetypefont.h"
|
||||
|
||||
const FT_Fixed MULTIPLIER_FT = 65536L;
|
||||
|
||||
const char* getErrorMessage(FT_Error err)
|
||||
{
|
||||
#undef __FTERRORS_H__
|
||||
#define FT_ERRORDEF( e, v, s ) case e: return s;
|
||||
#define FT_ERROR_START_LIST switch (err) {
|
||||
#define FT_ERROR_END_LIST }
|
||||
#include FT_ERRORS_H
|
||||
return "(Unknown error)";
|
||||
}
|
||||
|
||||
struct Outliner
|
||||
{
|
||||
static int moveToFn(const FT_Vector *to, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.moveTo(to->x, to->y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lineToFn(const FT_Vector *to, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.lineTo(to->x, to->y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int quadToFn(const FT_Vector *control, const FT_Vector *to, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.quadTo(control->x, control->y, to->x, to->y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cubicToFn(const FT_Vector *controlOne,
|
||||
const FT_Vector *controlTwo,
|
||||
const FT_Vector *to,
|
||||
void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.cubicTo(controlOne->x, controlOne->y, controlTwo->x, controlTwo->y, to->x, to->y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
};
|
||||
|
||||
FreeTypeFont::FreeTypeFont()
|
||||
{
|
||||
const auto error = FT_Init_FreeType(&m_ftLibrary);
|
||||
if (error) {
|
||||
throw tr("Failed to init FreeType.\n%1").arg(getErrorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
FreeTypeFont::~FreeTypeFont()
|
||||
{
|
||||
if (m_ftFace) {
|
||||
FT_Done_Face(m_ftFace);
|
||||
}
|
||||
|
||||
FT_Done_FreeType(m_ftLibrary);
|
||||
}
|
||||
|
||||
void FreeTypeFont::open(const QString &path, const quint32 index)
|
||||
{
|
||||
if (isOpen()) {
|
||||
FT_Done_Face(m_ftFace);
|
||||
m_ftFace = nullptr;
|
||||
}
|
||||
|
||||
const auto utf8Path = path.toUtf8();
|
||||
const auto error = FT_New_Face(m_ftLibrary, utf8Path.constData(), index, &m_ftFace);
|
||||
if (error) {
|
||||
throw tr("Failed to open a font.\n%1").arg(getErrorMessage(error));
|
||||
}
|
||||
}
|
||||
|
||||
bool FreeTypeFont::isOpen() const
|
||||
{
|
||||
return m_ftFace != nullptr;
|
||||
}
|
||||
|
||||
FontInfo FreeTypeFont::fontInfo() const
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
return FontInfo {
|
||||
m_ftFace->ascender,
|
||||
m_ftFace->height,
|
||||
(quint16)m_ftFace->num_glyphs, // TrueType allows only u16.
|
||||
};
|
||||
}
|
||||
|
||||
Glyph FreeTypeFont::outline(const quint16 gid) const
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
auto error = FT_Load_Glyph(m_ftFace, gid, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
|
||||
if (error) {
|
||||
throw tr("Failed to load a glyph.\n%1").arg(getErrorMessage(error));
|
||||
}
|
||||
|
||||
Outliner outliner;
|
||||
|
||||
FT_Outline_Funcs funcs;
|
||||
funcs.move_to = outliner.moveToFn;
|
||||
funcs.line_to = outliner.lineToFn;
|
||||
funcs.conic_to = outliner.quadToFn;
|
||||
funcs.cubic_to = outliner.cubicToFn;
|
||||
funcs.shift = 0;
|
||||
funcs.delta = 0;
|
||||
|
||||
auto slot = m_ftFace->glyph;
|
||||
auto &outline = slot->outline;
|
||||
|
||||
// Flip outline around x-axis.
|
||||
FT_Matrix matrix;
|
||||
matrix.xx = 1L * MULTIPLIER_FT;
|
||||
matrix.xy = 0L * MULTIPLIER_FT;
|
||||
matrix.yx = 0L * MULTIPLIER_FT;
|
||||
matrix.yy = -1L * MULTIPLIER_FT;
|
||||
FT_Outline_Transform(&outline, &matrix);
|
||||
|
||||
FT_BBox bboxFt;
|
||||
FT_Outline_Get_BBox(&outline, &bboxFt);
|
||||
|
||||
const QRect bbox(
|
||||
(int)bboxFt.xMin,
|
||||
(int)bboxFt.yMin,
|
||||
(int)bboxFt.xMax - (int)bboxFt.xMin,
|
||||
(int)bboxFt.yMax - (int)bboxFt.yMin
|
||||
);
|
||||
|
||||
error = FT_Outline_Decompose(&outline, &funcs, &outliner);
|
||||
if (error) {
|
||||
throw tr("Failed to outline a glyph.\n%1").arg(getErrorMessage(error));
|
||||
}
|
||||
|
||||
outliner.path.setFillRule(Qt::WindingFill);
|
||||
|
||||
return Glyph {
|
||||
outliner.path,
|
||||
bbox,
|
||||
};
|
||||
}
|
||||
|
||||
void FreeTypeFont::setVariations(const QVector<Variation> &variations)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
QVector<FT_Fixed> ftCoords;
|
||||
|
||||
for (const auto &var : variations) {
|
||||
ftCoords << var.value * MULTIPLIER_FT;
|
||||
}
|
||||
|
||||
const auto error = FT_Set_Var_Design_Coordinates(m_ftFace, ftCoords.size(), ftCoords.data());
|
||||
if (error) {
|
||||
throw tr("Failed to set variation.\n%1").arg(getErrorMessage(error));
|
||||
}
|
||||
}
|
||||
32
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/freetypefont.h
vendored
Normal file
32
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/freetypefont.h
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_BBOX_H
|
||||
#include FT_MULTIPLE_MASTERS_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "glyph.h"
|
||||
|
||||
class FreeTypeFont
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(FreeTypeFont)
|
||||
|
||||
public:
|
||||
FreeTypeFont();
|
||||
~FreeTypeFont();
|
||||
|
||||
void open(const QString &path, const quint32 index = 0);
|
||||
bool isOpen() const;
|
||||
|
||||
FontInfo fontInfo() const;
|
||||
Glyph outline(const quint16 gid) const;
|
||||
|
||||
void setVariations(const QVector<Variation> &variations);
|
||||
|
||||
private:
|
||||
FT_Library m_ftLibrary = nullptr;
|
||||
FT_Face m_ftFace = nullptr;
|
||||
};
|
||||
48
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/glyph.h
vendored
Normal file
48
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/glyph.h
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include <QPainterPath>
|
||||
|
||||
struct Tag
|
||||
{
|
||||
Tag(quint32 v) : value(v) {}
|
||||
|
||||
QString toString() const
|
||||
{
|
||||
QString s;
|
||||
s.append(QChar(value >> 24 & 0xff));
|
||||
s.append(QChar(value >> 16 & 0xff));
|
||||
s.append(QChar(value >> 8 & 0xff));
|
||||
s.append(QChar(value >> 0 & 0xff));
|
||||
return s;
|
||||
}
|
||||
|
||||
quint32 value;
|
||||
};
|
||||
|
||||
struct FontInfo
|
||||
{
|
||||
qint16 ascender = 0;
|
||||
qint16 height = 1000;
|
||||
quint16 numberOfGlyphs = 0;
|
||||
};
|
||||
|
||||
struct Glyph
|
||||
{
|
||||
QPainterPath outline;
|
||||
QRect bbox;
|
||||
};
|
||||
|
||||
struct VariationInfo
|
||||
{
|
||||
QString name;
|
||||
Tag tag;
|
||||
qint16 min = 0;
|
||||
qint16 def = 0;
|
||||
qint16 max = 0;
|
||||
};
|
||||
|
||||
struct Variation
|
||||
{
|
||||
Tag tag;
|
||||
int value;
|
||||
};
|
||||
286
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/glyphsview.cpp
vendored
Normal file
286
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/glyphsview.cpp
vendored
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
#include <QDebug>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "glyphsview.h"
|
||||
|
||||
static const int COLUMNS_COUNT = 100;
|
||||
|
||||
GlyphsView::GlyphsView(QWidget *parent) : QAbstractScrollArea(parent)
|
||||
{
|
||||
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
}
|
||||
|
||||
void GlyphsView::setFontInfo(const FontInfo &fi)
|
||||
{
|
||||
m_fontInfo = fi;
|
||||
m_glyphs.resize(fi.numberOfGlyphs);
|
||||
#ifdef WITH_FREETYPE
|
||||
m_ftGlyphs.resize(fi.numberOfGlyphs);
|
||||
#endif
|
||||
#ifdef WITH_HARFBUZZ
|
||||
m_hbGlyphs.resize(fi.numberOfGlyphs);
|
||||
#endif
|
||||
|
||||
m_indexes.clear();
|
||||
for (int i = 0; i < fi.numberOfGlyphs; ++i) {
|
||||
QStaticText text(QString::number(i));
|
||||
text.prepare();
|
||||
m_indexes << text;
|
||||
}
|
||||
|
||||
updateScrollBars();
|
||||
horizontalScrollBar()->setValue(0);
|
||||
verticalScrollBar()->setValue(0);
|
||||
}
|
||||
|
||||
void GlyphsView::setGlyph(int idx, const Glyph &glyph)
|
||||
{
|
||||
m_glyphs.replace(idx, glyph);
|
||||
}
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
void GlyphsView::setFTGlyph(int idx, const Glyph &glyph)
|
||||
{
|
||||
m_ftGlyphs.replace(idx, glyph);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HARFBUZZ
|
||||
void GlyphsView::setHBGlyph(int idx, const Glyph &glyph)
|
||||
{
|
||||
m_hbGlyphs.replace(idx, glyph);
|
||||
}
|
||||
#endif
|
||||
|
||||
void GlyphsView::setDrawBboxes(const bool flag)
|
||||
{
|
||||
m_drawBboxes = flag;
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void GlyphsView::setDrawGlyphs(const bool flag)
|
||||
{
|
||||
m_drawGlyphs = flag;
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void GlyphsView::setDrawFTGlyphs(const bool flag)
|
||||
{
|
||||
m_drawFTGlyphs = flag;
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void GlyphsView::setDrawHBGlyphs(const bool flag)
|
||||
{
|
||||
m_drawHBGlyphs = flag;
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void GlyphsView::paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(viewport());
|
||||
p.translate(-horizontalScrollBar()->value(), -verticalScrollBar()->value());
|
||||
|
||||
const double cellHeight = m_fontInfo.height * m_scale;
|
||||
drawGrid(p, cellHeight);
|
||||
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
{
|
||||
auto font = p.font();
|
||||
font.setPointSize(10);
|
||||
p.setFont(font);
|
||||
}
|
||||
|
||||
int x = 0;
|
||||
int y = m_fontInfo.ascender;
|
||||
int num_y = m_fontInfo.height;
|
||||
for (int i = 0; i < m_glyphs.size(); ++i) {
|
||||
// Text rendering is the slowest part, so we are using preprocessed text.
|
||||
p.setPen(palette().color(QPalette::Text));
|
||||
p.drawStaticText(
|
||||
qRound(x * m_scale + 1),
|
||||
qRound(num_y * m_scale - p.fontMetrics().ascent() - 2),
|
||||
m_indexes.at(i)
|
||||
);
|
||||
|
||||
if (m_drawGlyphs) {
|
||||
p.save();
|
||||
|
||||
const int dx = qRound((m_fontInfo.height - m_glyphs.at(i).bbox.width()) / 2.0)
|
||||
- m_glyphs.at(i).bbox.x();
|
||||
|
||||
p.scale(m_scale, m_scale);
|
||||
p.translate(x + dx, y);
|
||||
|
||||
if (m_drawBboxes) {
|
||||
p.setPen(QPen(Qt::darkGreen, 0.5 / m_scale));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawRect(m_glyphs.at(i).bbox);
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setPen(Qt::NoPen);
|
||||
if (m_drawFTGlyphs || m_drawHBGlyphs) {
|
||||
p.setBrush(Qt::red);
|
||||
} else {
|
||||
p.setBrush(palette().color(QPalette::Text));
|
||||
}
|
||||
|
||||
p.drawPath(m_glyphs.at(i).outline);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
|
||||
#ifdef WITH_HARFBUZZ
|
||||
if (m_drawHBGlyphs) {
|
||||
p.save();
|
||||
|
||||
const int dx = qRound((m_fontInfo.height - m_hbGlyphs.at(i).bbox.width()) / 2.0)
|
||||
- m_hbGlyphs.at(i).bbox.x();
|
||||
|
||||
p.scale(m_scale, m_scale);
|
||||
p.translate(x + dx, y);
|
||||
|
||||
if (m_drawBboxes) {
|
||||
p.setPen(QPen(Qt::darkGreen, 0.5 / m_scale));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawRect(m_hbGlyphs.at(i).bbox);
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
if (m_drawFTGlyphs) {
|
||||
p.setBrush(Qt::blue);
|
||||
} else {
|
||||
p.setBrush(palette().color(QPalette::Text));
|
||||
}
|
||||
|
||||
p.drawPath(m_hbGlyphs.at(i).outline);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
if (m_drawFTGlyphs) {
|
||||
p.save();
|
||||
|
||||
const int dx = qRound((m_fontInfo.height - m_ftGlyphs.at(i).bbox.width()) / 2.0)
|
||||
- m_ftGlyphs.at(i).bbox.x();
|
||||
|
||||
p.scale(m_scale, m_scale);
|
||||
p.translate(x + dx, y);
|
||||
|
||||
if (m_drawBboxes) {
|
||||
p.setPen(QPen(Qt::darkGreen, 0.5 / m_scale));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.drawRect(m_ftGlyphs.at(i).bbox);
|
||||
}
|
||||
|
||||
p.setPen(Qt::NoPen);
|
||||
p.setBrush(palette().color(QPalette::Text));
|
||||
|
||||
if (m_drawGlyphs || m_drawHBGlyphs) {
|
||||
p.setBrush(palette().color(QPalette::Base));
|
||||
}
|
||||
|
||||
p.drawPath(m_ftGlyphs.at(i).outline);
|
||||
|
||||
p.restore();
|
||||
}
|
||||
#endif
|
||||
|
||||
x += m_fontInfo.height;
|
||||
if (i > 0 && (i + 1) % COLUMNS_COUNT == 0) {
|
||||
x = 0;
|
||||
y += m_fontInfo.height;
|
||||
num_y += m_fontInfo.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphsView::drawGrid(QPainter &p, const double cellHeight)
|
||||
{
|
||||
p.setRenderHint(QPainter::Antialiasing, false);
|
||||
p.setPen(QPen(palette().color(QPalette::Text), 0.25));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
const int rows = qRound(floor(m_glyphs.size() / COLUMNS_COUNT)) + 1;
|
||||
const auto maxH = qMin(rows * cellHeight, (double)horizontalScrollBar()->maximum());
|
||||
|
||||
double x = cellHeight;
|
||||
for (int c = 1; c < COLUMNS_COUNT; ++c) {
|
||||
p.drawLine(QLineF(x, 0, x, maxH));
|
||||
x += cellHeight;
|
||||
}
|
||||
|
||||
double y = cellHeight;
|
||||
for (int r = 1; r <= rows; ++r) {
|
||||
p.drawLine(QLineF(0, y, horizontalScrollBar()->maximum() + viewport()->width(), y));
|
||||
y += cellHeight;
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphsView::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
if (e->button() & Qt::LeftButton) {
|
||||
m_mousePressPos = e->pos();
|
||||
m_origOffset = QPoint(horizontalScrollBar()->value(), verticalScrollBar()->value());
|
||||
}
|
||||
}
|
||||
|
||||
void GlyphsView::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
if (m_mousePressPos.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto diff = m_mousePressPos - e->pos();
|
||||
horizontalScrollBar()->setValue(m_origOffset.x() + diff.x());
|
||||
verticalScrollBar()->setValue(m_origOffset.y() + diff.y());
|
||||
}
|
||||
|
||||
void GlyphsView::mouseReleaseEvent(QMouseEvent *)
|
||||
{
|
||||
m_mousePressPos = QPoint();
|
||||
m_origOffset = QPoint();
|
||||
}
|
||||
|
||||
void GlyphsView::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
e->accept();
|
||||
|
||||
if (e->angleDelta().y() > 0) {
|
||||
m_scale += 0.01;
|
||||
} else {
|
||||
m_scale -= 0.01;
|
||||
}
|
||||
|
||||
m_scale = qBound(0.03, m_scale, 1.0);
|
||||
|
||||
updateScrollBars();
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
void GlyphsView::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
QAbstractScrollArea::resizeEvent(e);
|
||||
updateScrollBars();
|
||||
}
|
||||
|
||||
void GlyphsView::updateScrollBars()
|
||||
{
|
||||
const double cellHeight = m_fontInfo.height * m_scale;
|
||||
const int rows = qRound(floor(m_glyphs.size() / COLUMNS_COUNT)) + 1;
|
||||
const auto w = COLUMNS_COUNT * cellHeight - viewport()->width();
|
||||
const auto h = rows * cellHeight - viewport()->height();
|
||||
horizontalScrollBar()->setMinimum(0);
|
||||
verticalScrollBar()->setMinimum(0);
|
||||
horizontalScrollBar()->setMaximum(qMax(0, qRound(w)));
|
||||
verticalScrollBar()->setMaximum(qMax(0, qRound(h)));
|
||||
}
|
||||
61
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/glyphsview.h
vendored
Normal file
61
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/glyphsview.h
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
#include <QAbstractScrollArea>
|
||||
#include <QStaticText>
|
||||
|
||||
#include "glyph.h"
|
||||
|
||||
class GlyphsView : public QAbstractScrollArea
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GlyphsView(QWidget *parent = nullptr);
|
||||
|
||||
void setFontInfo(const FontInfo &fi);
|
||||
void setGlyph(int idx, const Glyph &glyph);
|
||||
#ifdef WITH_FREETYPE
|
||||
void setFTGlyph(int idx, const Glyph &glyph);
|
||||
#endif
|
||||
#ifdef WITH_HARFBUZZ
|
||||
void setHBGlyph(int idx, const Glyph &glyph);
|
||||
#endif
|
||||
|
||||
void setDrawBboxes(const bool flag);
|
||||
void setDrawGlyphs(const bool flag);
|
||||
void setDrawFTGlyphs(const bool flag);
|
||||
void setDrawHBGlyphs(const bool flag);
|
||||
|
||||
private:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void drawGrid(QPainter &p, const double cellHeight);
|
||||
|
||||
void mousePressEvent(QMouseEvent *e);
|
||||
void mouseMoveEvent(QMouseEvent *e);
|
||||
void mouseReleaseEvent(QMouseEvent *e);
|
||||
void wheelEvent(QWheelEvent *e);
|
||||
|
||||
void resizeEvent(QResizeEvent *);
|
||||
|
||||
void updateScrollBars();
|
||||
|
||||
private:
|
||||
QPoint m_mousePressPos;
|
||||
QPoint m_origOffset;
|
||||
|
||||
double m_scale = 0.05;
|
||||
bool m_drawBboxes = true;
|
||||
bool m_drawGlyphs = true;
|
||||
bool m_drawFTGlyphs = false;
|
||||
bool m_drawHBGlyphs = false;
|
||||
|
||||
FontInfo m_fontInfo;
|
||||
QVector<Glyph> m_glyphs;
|
||||
#ifdef WITH_FREETYPE
|
||||
QVector<Glyph> m_ftGlyphs;
|
||||
#endif
|
||||
#ifdef WITH_HARFBUZZ
|
||||
QVector<Glyph> m_hbGlyphs;
|
||||
#endif
|
||||
QVector<QStaticText> m_indexes;
|
||||
};
|
||||
160
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/harfbuzzfont.cpp
vendored
Normal file
160
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/harfbuzzfont.cpp
vendored
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#include <QTransform>
|
||||
#include <QDebug>
|
||||
|
||||
#include <hb.h>
|
||||
|
||||
#include "harfbuzzfont.h"
|
||||
|
||||
struct Outliner
|
||||
{
|
||||
static void moveToFn(hb_position_t to_x, hb_position_t to_y, Outliner &outliner)
|
||||
{
|
||||
outliner.path.moveTo(to_x, to_y);
|
||||
}
|
||||
|
||||
static void lineToFn(hb_position_t to_x, hb_position_t to_y, Outliner &outliner)
|
||||
{
|
||||
outliner.path.lineTo(to_x, to_y);
|
||||
}
|
||||
|
||||
static void quadToFn(hb_position_t control_x, hb_position_t control_y,
|
||||
hb_position_t to_x, hb_position_t to_y,
|
||||
Outliner &outliner)
|
||||
{
|
||||
outliner.path.quadTo(control_x, control_y, to_x, to_y);
|
||||
}
|
||||
|
||||
static void cubicToFn(hb_position_t control1_x, hb_position_t control1_y,
|
||||
hb_position_t control2_x, hb_position_t control2_y,
|
||||
hb_position_t to_x, hb_position_t to_y,
|
||||
Outliner &outliner)
|
||||
{
|
||||
outliner.path.cubicTo(control1_x, control1_y, control2_x, control2_y, to_x, to_y);
|
||||
}
|
||||
|
||||
static void closePathFn(Outliner &outliner)
|
||||
{
|
||||
outliner.path.closeSubpath();
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
};
|
||||
|
||||
HarfBuzzFont::HarfBuzzFont()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
HarfBuzzFont::~HarfBuzzFont()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void HarfBuzzFont::open(const QString &path, const quint32 index)
|
||||
{
|
||||
if (isOpen()) {
|
||||
reset();
|
||||
}
|
||||
|
||||
const auto utf8Path = path.toUtf8();
|
||||
hb_blob_t *blob = hb_blob_create_from_file(utf8Path.constData());
|
||||
if (!blob) {
|
||||
throw tr("Failed to open a font.");
|
||||
}
|
||||
|
||||
hb_face_t *face = hb_face_create(blob, index);
|
||||
if (!face) {
|
||||
throw tr("Failed to open a font.");
|
||||
}
|
||||
|
||||
hb_font_t *font = hb_font_create(face);
|
||||
if (!font) {
|
||||
throw tr("Failed to open a font.");
|
||||
}
|
||||
|
||||
m_blob = blob;
|
||||
m_face = face;
|
||||
m_font = font;
|
||||
}
|
||||
|
||||
bool HarfBuzzFont::isOpen() const
|
||||
{
|
||||
return m_font != nullptr;
|
||||
}
|
||||
|
||||
Glyph HarfBuzzFont::outline(const quint16 gid) const
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
Outliner outliner;
|
||||
|
||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create();
|
||||
hb_draw_funcs_set_move_to_func(funcs, (hb_draw_move_to_func_t)outliner.moveToFn);
|
||||
hb_draw_funcs_set_line_to_func(funcs, (hb_draw_line_to_func_t)outliner.lineToFn);
|
||||
hb_draw_funcs_set_quadratic_to_func(funcs, (hb_draw_quadratic_to_func_t)outliner.quadToFn);
|
||||
hb_draw_funcs_set_cubic_to_func(funcs, (hb_draw_cubic_to_func_t)outliner.cubicToFn);
|
||||
hb_draw_funcs_set_close_path_func(funcs, (hb_draw_close_path_func_t)outliner.closePathFn);
|
||||
|
||||
if (!hb_font_draw_glyph(m_font, gid, funcs, &outliner)) {
|
||||
throw tr("Failed to outline a glyph %1.").arg(gid);
|
||||
}
|
||||
|
||||
hb_draw_funcs_destroy(funcs);
|
||||
|
||||
hb_glyph_extents_t extents = {0, 0, 0, 0};
|
||||
if (!hb_font_get_glyph_extents(m_font, gid, &extents)) {
|
||||
throw tr("Failed to query glyph extents.");
|
||||
}
|
||||
|
||||
const QRect bbox(
|
||||
extents.x_bearing,
|
||||
-extents.y_bearing,
|
||||
extents.width,
|
||||
-extents.height
|
||||
);
|
||||
|
||||
// Flip outline around x-axis.
|
||||
QTransform ts(1, 0, 0, -1, 0, 0);
|
||||
outliner.path = ts.map(outliner.path);
|
||||
|
||||
outliner.path.setFillRule(Qt::WindingFill);
|
||||
|
||||
return Glyph {
|
||||
outliner.path,
|
||||
bbox,
|
||||
};
|
||||
}
|
||||
|
||||
void HarfBuzzFont::setVariations(const QVector<Variation> &variations)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
QVector<hb_variation_t> hbVariations;
|
||||
for (const auto &var : variations) {
|
||||
hbVariations.append({ var.tag.value, (float)var.value });
|
||||
}
|
||||
|
||||
hb_font_set_variations(m_font, hbVariations.constData(), hbVariations.size());
|
||||
}
|
||||
|
||||
void HarfBuzzFont::reset()
|
||||
{
|
||||
if (m_blob) {
|
||||
hb_blob_destroy(m_blob);
|
||||
m_blob = nullptr;
|
||||
}
|
||||
|
||||
if (m_font) {
|
||||
hb_font_destroy(m_font);
|
||||
m_font = nullptr;
|
||||
}
|
||||
|
||||
if (m_face) {
|
||||
hb_face_destroy(m_face);
|
||||
m_face = nullptr;
|
||||
}
|
||||
}
|
||||
34
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/harfbuzzfont.h
vendored
Normal file
34
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/harfbuzzfont.h
vendored
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "glyph.h"
|
||||
|
||||
struct hb_blob_t;
|
||||
struct hb_face_t;
|
||||
struct hb_font_t;
|
||||
struct hb_draw_funcs_t;
|
||||
|
||||
class HarfBuzzFont
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(HarfBuzzFont)
|
||||
|
||||
public:
|
||||
HarfBuzzFont();
|
||||
~HarfBuzzFont();
|
||||
|
||||
void open(const QString &path, const quint32 index = 0);
|
||||
bool isOpen() const;
|
||||
|
||||
Glyph outline(const quint16 gid) const;
|
||||
|
||||
void setVariations(const QVector<Variation> &variations);
|
||||
|
||||
private:
|
||||
void reset();
|
||||
|
||||
private:
|
||||
hb_blob_t *m_blob = nullptr;
|
||||
hb_face_t *m_face = nullptr;
|
||||
hb_font_t *m_font = nullptr;
|
||||
};
|
||||
13
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/main.cpp
vendored
Normal file
13
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/main.cpp
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include <QApplication>
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
162
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/mainwindow.cpp
vendored
Normal file
162
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/mainwindow.cpp
vendored
Normal file
|
|
@ -0,0 +1,162 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QSlider>
|
||||
#include <QTimer>
|
||||
#include <QMessageBox>
|
||||
#include <QDebug>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
#ifndef WITH_FREETYPE
|
||||
ui->chBoxDrawFreeType->hide();
|
||||
#endif
|
||||
|
||||
#ifndef WITH_HARFBUZZ
|
||||
ui->chBoxDrawHarfBuzz->hide();
|
||||
#endif
|
||||
|
||||
if (qApp->arguments().size() == 2) {
|
||||
QTimer::singleShot(1, this, [this](){
|
||||
loadFont(qApp->arguments().at(1));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::loadFont(const QString &path)
|
||||
{
|
||||
try {
|
||||
m_ttfpFont.open(path);
|
||||
|
||||
const auto variations = m_ttfpFont.loadVariations();
|
||||
if (!variations.isEmpty()) {
|
||||
ui->widgetVariations->show();
|
||||
|
||||
// Clear layout.
|
||||
while (ui->layVariations->count()) {
|
||||
delete ui->layVariations->takeAt(0);
|
||||
}
|
||||
|
||||
m_variationSliders.clear();
|
||||
|
||||
QVector<Variation> newVariations;
|
||||
|
||||
for (const auto &var : variations) {
|
||||
auto hlay = new QHBoxLayout();
|
||||
hlay->setContentsMargins(0, 0, 0, 0);
|
||||
hlay->addWidget(new QLabel(var.name));
|
||||
|
||||
auto slider = new QSlider(Qt::Horizontal);
|
||||
slider->setMinimum(var.min);
|
||||
slider->setMaximum(var.max);
|
||||
slider->setValue(var.def);
|
||||
hlay->addWidget(slider);
|
||||
ui->layVariations->addLayout(hlay);
|
||||
|
||||
m_variationSliders.append({ slider, var.tag });
|
||||
|
||||
connect(slider, &QSlider::valueChanged, this, &MainWindow::onVariationChanged);
|
||||
|
||||
newVariations.append({ var.tag, var.def });
|
||||
}
|
||||
|
||||
m_ttfpFont.setVariations(newVariations);
|
||||
} else {
|
||||
ui->widgetVariations->hide();
|
||||
}
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
m_ftFont.open(path);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HARFBUZZ
|
||||
m_hbFont.open(path);
|
||||
#endif
|
||||
|
||||
ui->glyphsView->setFontInfo(m_ttfpFont.fontInfo());
|
||||
reloadGlyphs();
|
||||
} catch (const QString &err) {
|
||||
QMessageBox::warning(this, tr("Error"), err);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::reloadGlyphs()
|
||||
{
|
||||
const auto fi = m_ttfpFont.fontInfo();
|
||||
for (quint16 i = 0; i < fi.numberOfGlyphs; ++i) {
|
||||
try {
|
||||
ui->glyphsView->setGlyph(i, m_ttfpFont.outline(i));
|
||||
} catch (...) {
|
||||
}
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
try {
|
||||
ui->glyphsView->setFTGlyph(i, m_ftFont.outline(i));
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HARFBUZZ
|
||||
try {
|
||||
ui->glyphsView->setHBGlyph(i, m_hbFont.outline(i));
|
||||
} catch (...) {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ui->glyphsView->viewport()->update();
|
||||
}
|
||||
|
||||
void MainWindow::onVariationChanged()
|
||||
{
|
||||
try {
|
||||
QVector<Variation> variations;
|
||||
|
||||
for (auto var : m_variationSliders) {
|
||||
variations.append({ var.tag, var.slider->value() });
|
||||
}
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
m_ftFont.setVariations(variations);
|
||||
#endif
|
||||
|
||||
#ifdef WITH_HARFBUZZ
|
||||
m_hbFont.setVariations(variations);
|
||||
#endif
|
||||
m_ttfpFont.setVariations(variations);
|
||||
|
||||
reloadGlyphs();
|
||||
} catch (const QString &err) {
|
||||
QMessageBox::warning(this, tr("Error"), err);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_chBoxDrawBboxes_stateChanged(int flag)
|
||||
{
|
||||
ui->glyphsView->setDrawBboxes(flag);
|
||||
}
|
||||
|
||||
void MainWindow::on_chBoxDrawTtfParser_stateChanged(int flag)
|
||||
{
|
||||
ui->glyphsView->setDrawGlyphs(flag);
|
||||
}
|
||||
|
||||
void MainWindow::on_chBoxDrawFreeType_stateChanged(int flag)
|
||||
{
|
||||
ui->glyphsView->setDrawFTGlyphs(flag);
|
||||
}
|
||||
|
||||
void MainWindow::on_chBoxDrawHarfBuzz_stateChanged(int flag)
|
||||
{
|
||||
ui->glyphsView->setDrawHBGlyphs(flag);
|
||||
}
|
||||
54
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/mainwindow.h
vendored
Normal file
54
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/mainwindow.h
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
#include "freetypefont.h"
|
||||
#endif
|
||||
|
||||
#ifdef WITH_FREETYPE
|
||||
#include "harfbuzzfont.h"
|
||||
#endif
|
||||
|
||||
#include "ttfparserfont.h"
|
||||
|
||||
namespace Ui { class MainWindow; }
|
||||
|
||||
class QSlider;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
void loadFont(const QString &path);
|
||||
void reloadGlyphs();
|
||||
void onVariationChanged();
|
||||
|
||||
private slots:
|
||||
void on_chBoxDrawBboxes_stateChanged(int flag);
|
||||
void on_chBoxDrawTtfParser_stateChanged(int flag);
|
||||
void on_chBoxDrawFreeType_stateChanged(int flag);
|
||||
void on_chBoxDrawHarfBuzz_stateChanged(int flag);
|
||||
|
||||
private:
|
||||
struct VariationSlider
|
||||
{
|
||||
QSlider *slider;
|
||||
Tag tag;
|
||||
};
|
||||
|
||||
Ui::MainWindow * const ui;
|
||||
QVector<VariationSlider> m_variationSliders;
|
||||
TtfParserFont m_ttfpFont;
|
||||
#ifdef WITH_FREETYPE
|
||||
FreeTypeFont m_ftFont;
|
||||
#endif
|
||||
#ifdef WITH_HARFBUZZ
|
||||
HarfBuzzFont m_hbFont;
|
||||
#endif
|
||||
};
|
||||
156
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/mainwindow.ui
vendored
Normal file
156
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/mainwindow.ui
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>FontView</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="GlyphsView" name="glyphsView" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="sidebar" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chBoxDrawTtfParser">
|
||||
<property name="text">
|
||||
<string>Draw ttf-parser</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chBoxDrawFreeType">
|
||||
<property name="text">
|
||||
<string>Draw FreeType</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chBoxDrawHarfBuzz">
|
||||
<property name="text">
|
||||
<string>Draw HarfBuzz</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="chBoxDrawBboxes">
|
||||
<property name="text">
|
||||
<string>Draw bboxes</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widgetVariations" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Variations:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layVariations"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>GlyphsView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>glyphsview.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
165
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/ttfparserfont.cpp
vendored
Normal file
165
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/ttfparserfont.cpp
vendored
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
#include <QTransform>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
|
||||
#include "ttfparserfont.h"
|
||||
|
||||
struct Outliner
|
||||
{
|
||||
static void moveToFn(float x, float y, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.moveTo(double(x), double(y));
|
||||
}
|
||||
|
||||
static void lineToFn(float x, float y, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.lineTo(double(x), double(y));
|
||||
}
|
||||
|
||||
static void quadToFn(float x1, float y1, float x, float y, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.quadTo(double(x1), double(y1), double(x), double(y));
|
||||
}
|
||||
|
||||
static void curveToFn(float x1, float y1, float x2, float y2, float x, float y, void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.cubicTo(double(x1), double(y1), double(x2), double(y2), double(x), double(y));
|
||||
}
|
||||
|
||||
static void closePathFn(void *user)
|
||||
{
|
||||
auto self = static_cast<Outliner *>(user);
|
||||
self->path.closeSubpath();
|
||||
}
|
||||
|
||||
QPainterPath path;
|
||||
};
|
||||
|
||||
TtfParserFont::TtfParserFont()
|
||||
{
|
||||
}
|
||||
|
||||
void TtfParserFont::open(const QString &path, const quint32 index)
|
||||
{
|
||||
if (isOpen()) {
|
||||
m_face.reset();
|
||||
}
|
||||
|
||||
QFile file(path);
|
||||
file.open(QFile::ReadOnly);
|
||||
m_fontData = file.readAll();
|
||||
|
||||
m_face.reset((ttfp_face*)malloc(ttfp_face_size_of()));
|
||||
const auto res = ttfp_face_init(m_fontData.constData(), m_fontData.size(), index, m_face.get());
|
||||
|
||||
if (!res) {
|
||||
throw tr("Failed to open a font.");
|
||||
}
|
||||
}
|
||||
|
||||
bool TtfParserFont::isOpen() const
|
||||
{
|
||||
return m_face != nullptr;
|
||||
}
|
||||
|
||||
FontInfo TtfParserFont::fontInfo() const
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
return FontInfo {
|
||||
ttfp_get_ascender(m_face.get()),
|
||||
ttfp_get_height(m_face.get()),
|
||||
ttfp_get_number_of_glyphs(m_face.get()),
|
||||
};
|
||||
}
|
||||
|
||||
Glyph TtfParserFont::outline(const quint16 gid) const
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
Outliner outliner;
|
||||
ttfp_outline_builder builder;
|
||||
builder.move_to = outliner.moveToFn;
|
||||
builder.line_to = outliner.lineToFn;
|
||||
builder.quad_to = outliner.quadToFn;
|
||||
builder.curve_to = outliner.curveToFn;
|
||||
builder.close_path = outliner.closePathFn;
|
||||
|
||||
ttfp_rect rawBbox;
|
||||
|
||||
const bool ok = ttfp_outline_glyph(
|
||||
m_face.get(),
|
||||
builder,
|
||||
&outliner,
|
||||
gid,
|
||||
&rawBbox
|
||||
);
|
||||
|
||||
if (!ok) {
|
||||
return Glyph {
|
||||
QPainterPath(),
|
||||
QRect(),
|
||||
};
|
||||
}
|
||||
|
||||
const QRect bbox(
|
||||
rawBbox.x_min,
|
||||
-rawBbox.y_max,
|
||||
rawBbox.x_max - rawBbox.x_min,
|
||||
rawBbox.y_max - rawBbox.y_min
|
||||
);
|
||||
|
||||
// Flip outline around x-axis.
|
||||
QTransform ts(1, 0, 0, -1, 0, 0);
|
||||
outliner.path = ts.map(outliner.path);
|
||||
|
||||
outliner.path.setFillRule(Qt::WindingFill);
|
||||
|
||||
return Glyph {
|
||||
outliner.path,
|
||||
bbox,
|
||||
};
|
||||
}
|
||||
|
||||
QVector<VariationInfo> TtfParserFont::loadVariations()
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
QVector<VariationInfo> variations;
|
||||
|
||||
for (uint16_t i = 0; i < ttfp_get_variation_axes_count(m_face.get()); ++i) {
|
||||
ttfp_variation_axis axis;
|
||||
ttfp_get_variation_axis(m_face.get(), i, &axis);
|
||||
|
||||
variations.append(VariationInfo {
|
||||
Tag(axis.tag).toString(),
|
||||
{ static_cast<quint32>(axis.tag) },
|
||||
static_cast<qint16>(axis.min_value),
|
||||
static_cast<qint16>(axis.def_value),
|
||||
static_cast<qint16>(axis.max_value),
|
||||
});
|
||||
}
|
||||
|
||||
return variations;
|
||||
}
|
||||
|
||||
void TtfParserFont::setVariations(const QVector<Variation> &variations)
|
||||
{
|
||||
if (!isOpen()) {
|
||||
throw tr("Font is not loaded.");
|
||||
}
|
||||
|
||||
for (const auto &variation : variations) {
|
||||
ttfp_set_variation(m_face.get(), variation.tag.value, variation.value);
|
||||
}
|
||||
}
|
||||
35
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/ttfparserfont.h
vendored
Normal file
35
third-party/vendor/ttf-parser-0.15.2/testing-tools/font-view/ttfparserfont.h
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QPainterPath>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#define TTFP_VARIABLE_FONTS
|
||||
#include <ttfparser.h>
|
||||
|
||||
#include "glyph.h"
|
||||
|
||||
class TtfParserFont
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(TtfParserFont)
|
||||
|
||||
public:
|
||||
TtfParserFont();
|
||||
|
||||
void open(const QString &path, const quint32 index = 0);
|
||||
bool isOpen() const;
|
||||
|
||||
FontInfo fontInfo() const;
|
||||
Glyph outline(const quint16 gid) const;
|
||||
|
||||
QVector<VariationInfo> loadVariations();
|
||||
void setVariations(const QVector<Variation> &variations);
|
||||
|
||||
private:
|
||||
struct FreeCPtr
|
||||
{ void operator()(void* x) { free(x); } };
|
||||
|
||||
QByteArray m_fontData;
|
||||
std::unique_ptr<ttfp_face, FreeCPtr> m_face;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue