libui/qt5/drawtext.cpp

191 lines
5.2 KiB
C++

#include "uipriv_qt5.hpp"
#include "draw.hpp" // draw context
#include <QFontDatabase>
#include <QFontMetricsF>
#include <QTextLayout>
struct uiDrawFontFamilies : public QStringList
{
uiDrawFontFamilies(const QStringList &stringList)
: QStringList(stringList) {}
};
struct uiDrawTextLayout : public QTextLayout
{
uiDrawTextLayout(const QString& text, const QFont &font, double width)
: QTextLayout(text, font)
, width_(width)
{
// qWarning("TODO: figure out wtf width is for: %f", width_);
}
double width_ = 0.0;
};
uiDrawFontFamilies *uiDrawListFontFamilies(void)
{
return new uiDrawFontFamilies(QFontDatabase().families());
}
uintmax_t uiDrawFontFamiliesNumFamilies(uiDrawFontFamilies *ff)
{
return ff->count();
}
char *uiDrawFontFamiliesFamily(uiDrawFontFamilies *ff, uintmax_t n)
{
return uiQt5StrdupQString(ff->value(n));
}
void uiDrawFreeFontFamilies(uiDrawFontFamilies *ff)
{
delete ff;
}
static int uiDrawTextWeightToFontWeight(uiDrawTextWeight weight)
{
switch (weight)
{
case uiDrawTextWeightThin: return QFont::Thin;
case uiDrawTextWeightUltraLight: return QFont::ExtraLight;
case uiDrawTextWeightLight: return QFont::Light;
case uiDrawTextWeightBook: return (QFont::Light+QFont::Normal)/2;
case uiDrawTextWeightNormal: return QFont::Normal;
case uiDrawTextWeightMedium: return QFont::Medium;
case uiDrawTextWeightSemiBold: return QFont::DemiBold;
case uiDrawTextWeightBold: return QFont::Bold;
case uiDrawTextWeightUtraBold: return QFont::ExtraBold;
case uiDrawTextWeightHeavy: return (QFont::ExtraBold+QFont::Black)/2;
case uiDrawTextWeightUltraHeavy: return QFont::Black;
default:
qWarning("Unknown uiDrawTextWeight: %d", weight);
}
return QFont::Normal;
}
static int uiDrawTextItalicToFontStyle(uiDrawTextItalic italic)
{
switch(italic)
{
case uiDrawTextItalicNormal: return QFont::StyleNormal;
case uiDrawTextItalicOblique: return QFont::StyleOblique;
case uiDrawTextItalicItalic: return QFont::StyleItalic;
default:
qWarning("Unknown uiDrawTextItalic: %d", italic);
}
return QFont::StyleNormal;
}
static int uiDrawTextStretchToFont(uiDrawTextStretch stretch)
{
switch(stretch)
{
case uiDrawTextStretchUltraCondensed: return QFont::UltraCondensed;
case uiDrawTextStretchExtraCondensed: return QFont::ExtraCondensed;
case uiDrawTextStretchCondensed: return QFont::Condensed;
case uiDrawTextStretchSemiCondensed: return QFont::SemiCondensed;
case uiDrawTextStretchNormal: return QFont::Unstretched;
case uiDrawTextStretchSemiExpanded: return QFont::SemiExpanded;
case uiDrawTextStretchExpanded: return QFont::Expanded;
case uiDrawTextStretchExtraExpanded: return QFont::ExtraExpanded;
case uiDrawTextStretchUltraExpanded: return QFont::UltraExpanded;
default:
qWarning("Unknown uiDrawTextStretch: %d", stretch);
}
return QFont::Unstretched;
}
uiDrawTextFont *uiDrawLoadClosestFont(const uiDrawTextFontDescriptor *desc)
{
QFont font(QString::fromUtf8(desc->Family));
font.setPointSizeF(desc->Size);
font.setWeight(uiDrawTextWeightToFontWeight(desc->Weight));
font.setItalic(uiDrawTextItalicToFontStyle(desc->Italic));
font.setStretch(uiDrawTextStretchToFont(desc->Stretch));
return new uiDrawTextFont(font);
}
void uiDrawFreeTextFont(uiDrawTextFont *font)
{
delete font;
}
uintptr_t uiDrawTextFontHandle(uiDrawTextFont *font)
{
qWarning("TODO: %p", (void *)font);
return 0;
}
void uiDrawTextFontDescribe(uiDrawTextFont *font, uiDrawTextFontDescriptor *desc)
{
qWarning("TODO: %p %p", (void *)font, (void *)desc);
}
void uiDrawTextFontGetMetrics(uiDrawTextFont *font, uiDrawTextFontMetrics *metrics)
{
if (font) {
QFontMetricsF fontMetrics(*font);
metrics->Ascent = fontMetrics.ascent();
metrics->Descent = fontMetrics.descent();
metrics->Leading = fontMetrics.leading();
metrics->UnderlinePos = fontMetrics.underlinePos();
metrics->UnderlineThickness = 0; // TODO?
}
}
uiDrawTextLayout *uiDrawNewTextLayout(const char *text, uiDrawTextFont *defaultFont, double width)
{
return new uiDrawTextLayout(QString::fromUtf8(text), *defaultFont, width);
}
void uiDrawFreeTextLayout(uiDrawTextLayout *layout)
{
delete layout;
}
void uiDrawTextLayoutSetWidth(uiDrawTextLayout *layout, double width)
{
layout->width_ = width;
}
static void runLayouting(uiDrawTextLayout *layout)
{
layout->setCacheEnabled(true);
layout->beginLayout();
forever {
QTextLine line = layout->createLine();
if (!line.isValid()) {
break;
}
// TODO: shift by line height?
}
layout->endLayout();
}
void uiDrawTextLayoutExtents(uiDrawTextLayout *layout, double *width, double *height)
{
runLayouting(layout);
auto boundingRect = layout->boundingRect();
*width = boundingRect.width();
*height = boundingRect.height();
}
void uiDrawText(uiDrawContext *c, double x, double y, uiDrawTextLayout *layout)
{
runLayouting(layout);
layout->draw(c, {x,y});
}
void uiDrawTextLayoutSetColor(uiDrawTextLayout *layout, intmax_t startChar, intmax_t endChar, double r, double g, double b, double a)
{
// ineffective..? but works
auto additionalFormats = layout->additionalFormats();
QTextCharFormat format;
format.setForeground(QColor::fromRgbF(r,g,b,a));
additionalFormats.append(QTextLayout::FormatRange{(int)startChar,(int)(1+endChar-startChar),format});
layout->setAdditionalFormats(additionalFormats);
}