Add QFontMetrics (issue #799) (#803)

This commit is contained in:
Maks 2021-02-09 18:00:20 +01:00 committed by GitHub
parent 2ac83ca857
commit f13673bff1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 492 additions and 3 deletions

View File

@ -53,6 +53,7 @@ add_library(${CORE_WIDGETS_ADDON} SHARED
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QEvent/QDragMoveEvent/qdragmoveevent_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QEvent/QDragLeaveEvent/qdragleaveevent_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QFontDatabase/qfontdatabase_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QFontMetrics/qfontmetrics_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QPicture/qpicture_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QPixmap/qpixmap_wrap.cpp"
"${PROJECT_SOURCE_DIR}/src/cpp/lib/QtGui/QIcon/qicon_wrap.cpp"
@ -220,7 +221,7 @@ target_include_directories(${CORE_WIDGETS_ADDON} PRIVATE
)
if (WIN32)
if (WIN32)
add_definitions(/bigobj)
target_compile_definitions(${CORE_WIDGETS_ADDON} PRIVATE
ENABLE_DLL_EXPORT=1
@ -236,4 +237,3 @@ target_link_libraries(${CORE_WIDGETS_ADDON} PRIVATE
Qt5::Gui
Qt5::Svg
)

View File

@ -0,0 +1,40 @@
#pragma once
#include <napi.h>
#include <QFontMetrics>
#include "Extras/Export/export.h"
#include "core/Component/component_macro.h"
class DLL_EXPORT QFontMetricsWrap : public Napi::ObjectWrap<QFontMetricsWrap> {
COMPONENT_WRAPPED_METHODS_DECLARATION
private:
std::unique_ptr<QFontMetrics> instance;
public:
static Napi::FunctionReference constructor;
static Napi::Object init(Napi::Env env, Napi::Object exports);
QFontMetricsWrap(const Napi::CallbackInfo& info);
QFontMetrics* getInternalInstance();
// Wrapped methods
Napi::Value ascent(const Napi::CallbackInfo& info);
Napi::Value averageCharWidth(const Napi::CallbackInfo& info);
Napi::Value capHeight(const Napi::CallbackInfo& info);
Napi::Value descent(const Napi::CallbackInfo& info);
Napi::Value fontDpi(const Napi::CallbackInfo& info);
Napi::Value height(const Napi::CallbackInfo& info);
Napi::Value horizontalAdvance(const Napi::CallbackInfo& info);
Napi::Value inFont(const Napi::CallbackInfo& info);
Napi::Value leading(const Napi::CallbackInfo& info);
Napi::Value leftBearing(const Napi::CallbackInfo& info);
Napi::Value lineSpacing(const Napi::CallbackInfo& info);
Napi::Value lineWidth(const Napi::CallbackInfo& info);
Napi::Value overlinePos(const Napi::CallbackInfo& info);
Napi::Value rightBearing(const Napi::CallbackInfo& info);
Napi::Value size(const Napi::CallbackInfo& info);
Napi::Value strikeOutPos(const Napi::CallbackInfo& info);
Napi::Value swap(const Napi::CallbackInfo& info);
Napi::Value underlinePos(const Napi::CallbackInfo& info);
};

View File

@ -0,0 +1,221 @@
#include "QtGui/QFontMetrics/qfontmetrics_wrap.h"
#include "Extras/Utils/nutils.h"
#include "QtCore/QSize/qsize_wrap.h"
#include "QtGui/QFont/qfont_wrap.h"
Napi::FunctionReference QFontMetricsWrap::constructor;
Napi::Object QFontMetricsWrap::init(Napi::Env env, Napi::Object exports) {
Napi::HandleScope scope(env);
char CLASSNAME[] = "QFontMetrics";
Napi::Function func = DefineClass(
env, CLASSNAME,
{InstanceMethod("ascent", &QFontMetricsWrap::ascent),
InstanceMethod("averageCharWidth", &QFontMetricsWrap::averageCharWidth),
InstanceMethod("capHeight", &QFontMetricsWrap::capHeight),
InstanceMethod("descent", &QFontMetricsWrap::descent),
InstanceMethod("fontDpi", &QFontMetricsWrap::fontDpi),
InstanceMethod("height", &QFontMetricsWrap::height),
InstanceMethod("horizontalAdvance",
&QFontMetricsWrap::horizontalAdvance),
InstanceMethod("inFont", &QFontMetricsWrap::inFont),
InstanceMethod("leading", &QFontMetricsWrap::leading),
InstanceMethod("leftBearing", &QFontMetricsWrap::leftBearing),
InstanceMethod("lineSpacing", &QFontMetricsWrap::lineSpacing),
InstanceMethod("lineWidth", &QFontMetricsWrap::lineWidth),
InstanceMethod("overlinePos", &QFontMetricsWrap::overlinePos),
InstanceMethod("rightBearing", &QFontMetricsWrap::rightBearing),
InstanceMethod("size", &QFontMetricsWrap::size),
InstanceMethod("strikeOutPos", &QFontMetricsWrap::strikeOutPos),
InstanceMethod("swap", &QFontMetricsWrap::swap),
InstanceMethod("underlinePos", &QFontMetricsWrap::underlinePos),
COMPONENT_WRAPPED_METHODS_EXPORT_DEFINE(QFontMetricsWrap)});
constructor = Napi::Persistent(func);
exports.Set(CLASSNAME, func);
return exports;
}
QFontMetricsWrap::QFontMetricsWrap(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<QFontMetricsWrap>(info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (info.Length() == 1) {
if (info[0].IsExternal()) {
this->instance = std::unique_ptr<QFontMetrics>(
info[0].As<Napi::External<QFontMetrics>>().Data());
} else {
Napi::Object wrap0_0 = info[0].As<Napi::Object>();
QFontWrap* wrap0_1 = Napi::ObjectWrap<QFontWrap>::Unwrap(wrap0_0);
this->instance =
std::make_unique<QFontMetrics>(*wrap0_1->getInternalInstance());
}
} else {
Napi::TypeError::New(env, "Wrong number of arguments")
.ThrowAsJavaScriptException();
}
this->rawData = extrautils::configureComponent(this->getInternalInstance());
}
QFontMetrics* QFontMetricsWrap::getInternalInstance() {
return this->instance.get();
}
Napi::Value QFontMetricsWrap::ascent(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->ascent());
}
Napi::Value QFontMetricsWrap::averageCharWidth(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->averageCharWidth());
}
Napi::Value QFontMetricsWrap::capHeight(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->capHeight());
}
Napi::Value QFontMetricsWrap::descent(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->descent());
}
Napi::Value QFontMetricsWrap::fontDpi(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->fontDpi());
}
Napi::Value QFontMetricsWrap::height(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->height());
}
Napi::Value QFontMetricsWrap::horizontalAdvance(
const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
std::string format = info[0].As<Napi::String>().Utf8Value();
QString text = QString::fromUtf8(format.c_str());
if (info.Length() <= 2 && text.length() == 1) {
return Napi::Value::From(env, this->instance->horizontalAdvance(text[0]));
} else if (info.Length() == 2) {
int len = info[1].As<Napi::Number>().Int32Value();
return Napi::Value::From(env, this->instance->horizontalAdvance(text, len));
} else {
Napi::TypeError::New(env,
"Invalid number of arguments to horizontalAdvance")
.ThrowAsJavaScriptException();
return env.Null();
}
}
Napi::Value QFontMetricsWrap::inFont(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
char ch = info[0].As<Napi::String>().Utf8Value()[0];
return Napi::Boolean::New(env, this->instance->inFont(ch));
}
Napi::Value QFontMetricsWrap::leading(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->leading());
}
Napi::Value QFontMetricsWrap::leftBearing(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
char ch = info[0].As<Napi::String>().Utf8Value()[0];
return Napi::Boolean::New(env, this->instance->leftBearing(ch));
}
Napi::Value QFontMetricsWrap::lineSpacing(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->lineSpacing());
}
Napi::Value QFontMetricsWrap::lineWidth(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->lineWidth());
}
Napi::Value QFontMetricsWrap::overlinePos(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->overlinePos());
}
Napi::Value QFontMetricsWrap::rightBearing(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
char ch = info[0].As<Napi::String>().Utf8Value()[0];
return Napi::Boolean::New(env, this->instance->rightBearing(ch));
}
Napi::Value QFontMetricsWrap::size(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
if (info.Length() != 2 && info.Length() != 3) {
Napi::TypeError::New(env, "Invalid number of arguments to size")
.ThrowAsJavaScriptException();
return env.Null();
}
int flags = info[0].As<Napi::Number>().Int32Value();
std::string format = info[1].As<Napi::String>().Utf8Value();
QString text = QString::fromUtf8(format.c_str());
int tabStops = info[2].As<Napi::Number>().Int32Value();
QSize size = this->instance->size(flags, text, tabStops);
auto instance = QSizeWrap::constructor.New(
{Napi::External<QSize>::New(env, new QSize(size))});
return instance;
}
Napi::Value QFontMetricsWrap::strikeOutPos(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->strikeOutPos());
}
Napi::Value QFontMetricsWrap::swap(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
Napi::Object wrap0_0 = info[0].As<Napi::Object>();
QFontMetricsWrap* wrap0_1 =
Napi::ObjectWrap<QFontMetricsWrap>::Unwrap(wrap0_0);
this->instance->swap(*wrap0_1->getInternalInstance());
return env.Null();
}
Napi::Value QFontMetricsWrap::underlinePos(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
Napi::HandleScope scope(env);
return Napi::Value::From(env, this->instance->underlinePos());
}

View File

@ -31,6 +31,7 @@
#include "QtGui/QEvent/QWheelEvent/qwheelevent_wrap.h"
#include "QtGui/QFont/qfont_wrap.h"
#include "QtGui/QFontDatabase/qfontdatabase_wrap.h"
#include "QtGui/QFontMetrics/qfontmetrics_wrap.h"
#include "QtGui/QIcon/qicon_wrap.h"
#include "QtGui/QImage/qimage_wrap.h"
#include "QtGui/QKeySequence/qkeysequence_wrap.h"
@ -137,6 +138,7 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) {
QPixmapWrap::init(env, exports);
QKeySequenceWrap::init(env, exports);
QFontDatabaseWrap::init(env, exports);
QFontMetricsWrap::init(env, exports);
QIconWrap::init(env, exports);
QImageWrap::init(env, exports);
QFontWrap::init(env, exports);
@ -217,4 +219,4 @@ Napi::Object Main(Napi::Env env, Napi::Object exports) {
return exports;
}
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Main)
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Main)

View File

@ -18,6 +18,7 @@ export { QTextOptionWrapMode } from './lib/QtGui/QTextOption';
export { QClipboard, QClipboardMode } from './lib/QtGui/QClipboard';
export { QStyle, QStylePixelMetric } from './lib/QtGui/QStyle';
export { QFontDatabase, SystemFont, WritingSystem } from './lib/QtGui/QFontDatabase';
export { QFontMetrics } from './lib/QtGui/QFontMetrics';
// Events: Maybe a separate module ?
export { QKeyEvent } from './lib/QtGui/QEvent/QKeyEvent';
export { QMouseEvent } from './lib/QtGui/QEvent/QMouseEvent';

View File

@ -1,4 +1,5 @@
export enum TextFlag {
None = 0x0,
TextSingleLine = 0x0100,
TextDontClip = 0x0200,
TextExpandTabs = 0x0400,

View File

@ -0,0 +1,118 @@
import addon from '../utils/addon';
import { Component, NativeElement } from '../core/Component';
import { QFont } from './QFont';
import { checkIfNativeElement } from '../utils/helpers';
import { QSize } from '../QtCore/QSize';
import { TextFlag } from '../QtEnums';
export class QFontMetrics extends Component {
native: NativeElement;
constructor(native: NativeElement);
constructor(qfont: QFont);
constructor(qfontmetrics: QFontMetrics);
constructor(arg: QFont | QFontMetrics | NativeElement) {
super();
if (checkIfNativeElement(arg)) {
this.native = arg as NativeElement;
} else if (arg instanceof QFontMetrics) {
this.native = arg.native;
} else {
this.native = new addon.QFontMetrics(arg.native);
}
}
/** Returns the ascent of the font */
ascent(): number {
return this.native.ascent();
}
/** Returns the average width of glyphs in the font */
averageCharWidth(): number {
return this.native.averageCharWidth();
}
/** Returns the cap height of the font */
capHeight(): number {
return this.native.capHeight();
}
/** Returns the descent of the font */
descent(): number {
return this.native.descent();
}
/** Returns the font DPI */
fontDpi(): number {
return this.native.fontDpi();
}
/** Returns the height of the font */
height(): number {
return this.native.height();
}
/** Returns the horizontal advance in pixels of the first len characters of text. If len is negative (the default), the entire string is used */
horizontalAdvance(text: string, len = -1): number {
return this.native.horizontalAdvance(text, len);
}
/** Returns true if character ch is a valid character in the font; otherwise returns false */
inFont(text: string): number {
return this.native.inFont(text);
}
/** Returns the leading of the font */
leading(): number {
return this.native.leading();
}
/** Returns the left bearing of character ch in the font */
leftBearing(text: string): number {
return this.native.leftBearing(text);
}
/** Returns the distance from one base line to the next */
lineSpacing(): number {
return this.native.lineSpacing();
}
/** Returns the width of the underline and strikeout lines, adjusted for the point size of the font */
lineWidth(): number {
return this.native.lineWidth();
}
/** Returns the distance from the base line to where an overline should be drawn */
overlinePos(): number {
return this.native.overlinePos();
}
/** Returns the right bearing of character ch in the font */
rightBearing(text: string): number {
return this.native.rightBearing(text);
}
/**
* Returns the size in pixels of text
*
* See QtEnums::TextFlag for flags
*/
size(flags: TextFlag, text: string, tabStops = 0): QSize {
const native = this.native.size(flags, text, tabStops);
return new QSize(native);
}
/** Returns the distance from the base line to where the strikeout line should be drawn */
strikeOutPos(): number {
return this.native.strikeOutPos();
}
/** Swaps metrics other with this metrics. This operation is very fast and never fails */
swap(other: QFontMetrics): void {
return this.native.swap(other.native);
}
/** Returns the distance from the base line to where an underscore should be drawn */
underlinePos(): number {
return this.native.underlinePos();
}
}

View File

@ -0,0 +1,106 @@
import { TextFlag } from '../../QtEnums';
import { QFont } from '../QFont';
import { QFontMetrics } from '../QFontMetrics';
describe('QFontMetrics', () => {
// Helvetica is Qt's default sans-serif font
const qfont = new QFont('Helvetica');
it('initialize with QFont', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics).toBeTruthy();
expect(metrics.native).toBeTruthy();
});
it('averageCharWidth', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.averageCharWidth).toBeTruthy();
expect(metrics.averageCharWidth()).not.toBeNaN();
});
it('capHeight', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.capHeight).toBeTruthy();
expect(metrics.capHeight()).not.toBeNaN();
});
it('descent', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.descent).toBeTruthy();
expect(metrics.descent()).not.toBeNaN();
});
it('fontDpi', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.fontDpi).toBeTruthy();
expect(metrics.fontDpi()).not.toBeNaN();
});
it('height', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.height).toBeTruthy();
expect(metrics.height()).not.toBeNaN();
});
it('horizontalAdvance', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.horizontalAdvance).toBeTruthy();
expect(metrics.horizontalAdvance('a')).not.toBeNaN();
expect(metrics.horizontalAdvance('aaa')).not.toBeNaN();
});
it('inFont', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.inFont).toBeTruthy();
expect(metrics.inFont('a')).toBe(true);
});
it('leading', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.leading).toBeTruthy();
expect(metrics.leading()).not.toBeNaN();
});
it('leftBearing', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.leftBearing).toBeTruthy();
expect(metrics.leftBearing('a')).not.toBeNaN();
});
it('lineSpacing', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.lineSpacing).toBeTruthy();
expect(metrics.lineSpacing()).not.toBeNaN();
});
it('lineWidth', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.lineWidth).toBeTruthy();
expect(metrics.lineWidth()).not.toBeNaN();
});
it('overlinePos', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.overlinePos).toBeTruthy();
expect(metrics.overlinePos()).not.toBeNaN();
});
it('rightBearing', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.rightBearing).toBeTruthy();
expect(metrics.rightBearing('a')).not.toBeNaN();
});
it('size', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.size).toBeTruthy();
const sizeDefault = metrics.size(TextFlag.None, 'abc');
expect(sizeDefault.height()).toBeGreaterThan(0);
expect(sizeDefault.width()).toBeGreaterThan(0);
const sizeFlag1 = metrics.size(TextFlag.TextExpandTabs, '\tabc', 1);
const sizeFlag10 = metrics.size(TextFlag.TextExpandTabs, '\tabc', 10);
expect(sizeFlag1.width()).toBeGreaterThan(sizeDefault.width());
expect(sizeFlag10.width()).toBeGreaterThan(sizeFlag1.width());
});
it('strikeOutPos', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.strikeOutPos).toBeTruthy();
expect(metrics.strikeOutPos()).not.toBeNaN();
});
it('swap', () => {
const metrics = new QFontMetrics(qfont);
const metrics2 = new QFontMetrics(qfont);
expect(metrics.swap).toBeTruthy();
expect(() => metrics.swap(metrics2)).not.toThrow();
});
it('underlinePos', () => {
const metrics = new QFontMetrics(qfont);
expect(metrics.underlinePos).toBeTruthy();
expect(metrics.underlinePos()).not.toBeNaN();
});
});