Merge branch 'master' into features/effectnode

This commit is contained in:
Uwe Rathmann 2025-02-06 13:51:58 +01:00
commit 4438498e6f
18 changed files with 1001 additions and 0 deletions

View File

@ -36,3 +36,9 @@ c) Segoe-UI Fonts
Code: https://github.com/mrbvrz/segoe-ui-linux
License: https://github.com/mrbvrz/segoe-ui-linux/blob/master/license.txt
d) Font Awesome
Code: https://fontawesome.com/
SPDX-License-Identifier: OFL-1.1-RFN
Copyright (c) 2024 Fonticons, Inc.

View File

@ -3,6 +3,7 @@ add_subdirectory(dials)
add_subdirectory(dialogbuttons)
add_subdirectory(fonts)
add_subdirectory(gradients)
add_subdirectory(iconbrowser)
add_subdirectory(invoker)
add_subdirectory(shadows)
add_subdirectory(shapes)

View File

@ -0,0 +1,15 @@
############################################################################
# QSkinny - Copyright (C) The authors
# SPDX-License-Identifier: BSD-3-Clause
############################################################################
set(SOURCES
GlyphListView.h GlyphListView.cpp
main.cpp
)
qt_add_resources(SOURCES
fonts.qrc
)
qsk_add_example(iconbrowser ${SOURCES})

View File

@ -0,0 +1,120 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "GlyphListView.h"
#include <QskFunctions.h>
#include <QskGraphic.h>
#include <QskFontRole.h>
#include <QFontMetricsF>
#include <QRawFont>
constexpr int glyphSize = 100;
GlyphListView::GlyphListView( QQuickItem* parentItem )
: Inherited( parentItem )
{
}
GlyphListView::GlyphListView( const QString& fontName, QQuickItem* parentItem )
: GlyphListView( parentItem )
{
setFont( QRawFont( fontName, 16 ) );
setFontRoleHint( Text, QskFontRole::Title );
}
void GlyphListView::setFontPath( const QString& fontPath )
{
setFont( QRawFont( fontPath, 16 ) );
}
void GlyphListView::setFont( const QRawFont& font )
{
m_glyphTable.setIconFont( font );
const auto names = m_glyphTable.nameTable();
m_nameTable.clear();
m_nameTable.reserve( names.size() );
m_maxNameWidth = 0;
{
const QFontMetricsF fm( effectiveFont( Text ) );
for ( auto it = names.constBegin(); it != names.constEnd(); ++it )
{
m_nameTable.insert( it.value(), it.key() );
const qreal w = qskHorizontalAdvance( fm, it.key() );
if ( w > m_maxNameWidth )
m_maxNameWidth = w;
}
}
updateScrollableSize();
update();
}
QRawFont GlyphListView::font() const
{
return m_glyphTable.iconFont();
}
int GlyphListView::rowCount() const
{
return m_glyphTable.glyphCount() - 1;
}
int GlyphListView::columnCount() const
{
return 3;
}
qreal GlyphListView::columnWidth( int col ) const
{
switch( col )
{
case 0:
{
const QFontMetricsF fm( effectiveFont( Text ) );
return qskHorizontalAdvance( fm, "999999" );
}
case 1:
return glyphSize;
case 2:
return m_maxNameWidth;
}
return 0;
}
qreal GlyphListView::rowHeight() const
{
return glyphSize + 20;
}
QVariant GlyphListView::valueAt( int row, int col ) const
{
const auto glyphIndex = row + 1;
switch( col )
{
case 0:
return QVariant::fromValue( QString::number( glyphIndex ) );
case 1:
return QVariant::fromValue( m_glyphTable.glyphGraphic( glyphIndex ) );
case 2:
return QVariant::fromValue( m_nameTable.value( glyphIndex ) );
}
return QVariant();
}
#include "moc_GlyphListView.cpp"

View File

@ -0,0 +1,38 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#pragma once
#include <QskListView.h>
#include <QskGlyphTable.h>
#include <QHash>
class GlyphListView : public QskListView
{
Q_OBJECT
using Inherited = QskListView;
public:
GlyphListView( QQuickItem* = nullptr);
GlyphListView( const QString&, QQuickItem* = nullptr);
void setFontPath( const QString& );
void setFont( const QRawFont& );
QRawFont font() const;
int rowCount() const override;
int columnCount() const override;
virtual qreal columnWidth( int col ) const override;
virtual qreal rowHeight() const override;
QVariant valueAt( int row, int col ) const override;
private:
QskGlyphTable m_glyphTable;
QHash< uint, QString > m_nameTable;
int m_maxNameWidth = 0;
};

View File

@ -0,0 +1,11 @@
<RCC>
<qresource prefix="/iconfonts">
<file alias="FluentIcons.ttf">fonts/FluentSystemIcons-Resizable.ttf</file>
<file alias="FontAwesomeIcons.otf">fonts/Font Awesome 6 Free-Regular-400.otf</file>
<file alias="IcoMoonIcons.ttf">fonts/IcoMoon-Free.ttf</file>
<file alias="MaterialIcons.ttf">fonts/MaterialSymbolsOutlined.ttf</file>
<file alias="OctIcons.ttf">fonts/Octicons.ttf</file>
</qresource>
</RCC>

Binary file not shown.

View File

@ -0,0 +1,26 @@
a) Material3
Code: https://github.com/google/material-design-icons
SPDX-License-Identifier: Apache License 2.0
b) Fluent2
Code: https://github.com/microsoft/fluentui-system-icons
SPDX-License-Identifier: MIT License
c) Font Awesome
Code: https://fontawesome.com/
SPDX-License-Identifier: OFL-1.1-RFN
Copyright (c) 2024 Fonticons, Inc.
d) IcoMoon
Code: https://github.com/Keyamoon/IcoMoon-Free
SPDX-License-Identifier: CC-BY-4.0
e) Octicons
Code: https://github.com/primer/octicons
SPDX-License-Identifier: MIT License

Binary file not shown.

View File

@ -0,0 +1,100 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "GlyphListView.h"
#include <SkinnyShortcut.h>
#include <QskMainView.h>
#include <QskFocusIndicator.h>
#include <QskObjectCounter.h>
#include <QskWindow.h>
#include <QskComboBox.h>
#include <QGuiApplication>
#include <QRawFont>
#include <QDir>
namespace
{
class Header : public QskLinearBox
{
Q_OBJECT
public:
Header( QQuickItem* parent = nullptr )
: QskLinearBox( Qt::Horizontal, parent )
{
setPaddingHint( QskBox::Panel, 5 );
initSizePolicy( QskSizePolicy::Ignored, QskSizePolicy::Fixed );
setPanel( true );
m_comboBox = new QskComboBox( this );
const auto entries = QDir( ":iconfonts" ).entryInfoList();
for ( const auto& entry : entries )
m_comboBox->addOption( QUrl(), entry.absoluteFilePath() );
m_comboBox->setCurrentIndex( 0 );
connect( m_comboBox, &QskComboBox::currentIndexChanged,
this, &Header::comboBoxChanged );
}
QString fontPath() const { return m_comboBox->currentText(); }
Q_SIGNALS:
void fontChanged( const QString& );
private:
void comboBoxChanged() { Q_EMIT fontChanged( fontPath() ); }
QskComboBox* m_comboBox;
};
class MainView : public QskMainView
{
public:
MainView( QQuickItem* parent = nullptr )
: QskMainView( parent )
{
auto listView = new GlyphListView( this );
auto header = new Header( this );
setHeader( header );
setBody( listView );
listView->setFontPath( header->fontPath() );
connect( header, &Header::fontChanged,
listView, &GlyphListView::setFontPath );
}
};
}
int main( int argc, char* argv[] )
{
#ifdef ITEM_STATISTICS
QskObjectCounter counter( true );
#endif
QGuiApplication app( argc, argv );
SkinnyShortcut::enable( SkinnyShortcut::AllShortcuts );
auto mainView = new QskMainView();
mainView->setBody( new GlyphListView( ":/fonts/Octicons.ttf" ) );
QskWindow window;
window.addItem( new MainView() );
window.addItem( new QskFocusIndicator() );
window.resize( 600, 400 );
window.show();
return app.exec();
}
#include "main.moc"

View File

@ -77,6 +77,8 @@ list(APPEND PRIVATE_HEADERS
list(APPEND HEADERS
graphic/QskColorFilter.h
graphic/QskGlyphGraphicProvider.h
graphic/QskGlyphTable.h
graphic/QskGraphic.h
graphic/QskGraphicImageProvider.h
graphic/QskGraphicIO.h
@ -91,6 +93,8 @@ list(APPEND HEADERS
list(APPEND SOURCES
graphic/QskColorFilter.cpp
graphic/QskGlyphGraphicProvider.cpp
graphic/QskGlyphTable.cpp
graphic/QskGraphic.cpp
graphic/QskGraphicImageProvider.cpp
graphic/QskGraphicIO.cpp

View File

@ -0,0 +1,84 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskGlyphGraphicProvider.h"
#include "QskGraphic.h"
#include "QskGlyphTable.h"
#include <qrawfont.h>
#include <qpainter.h>
#include <qpainterpath.h>
class QskGlyphGraphicProvider::PrivateData
{
public:
QskGlyphTable glyphTable;
};
QskGlyphGraphicProvider::QskGlyphGraphicProvider( QObject* parent )
: QskGraphicProvider( parent )
, m_data( new PrivateData )
{
}
QskGlyphGraphicProvider::~QskGlyphGraphicProvider()
{
}
void QskGlyphGraphicProvider::setIconFont( const QRawFont& font )
{
m_data->glyphTable.setIconFont( font );
}
QRawFont QskGlyphGraphicProvider::iconFont() const
{
return m_data->glyphTable.iconFont();
}
QskGraphic QskGlyphGraphicProvider::glyphGraphic( uint index ) const
{
return m_data->glyphTable.glyphGraphic( index );
}
const QskGraphic* QskGlyphGraphicProvider::loadGraphic( const QString& key ) const
{
if ( const auto index = glyphIndex( key ) )
{
const auto graphic = glyphGraphic( index );
if ( !graphic.isNull() )
return new QskGraphic( graphic );
}
return nullptr;
}
uint QskGlyphGraphicProvider::glyphIndex( const QString& key ) const
{
const auto& table = m_data->glyphTable;
if ( ( table.glyphCount() > 0 ) && !key.isEmpty() )
{
if ( key.startsWith( '#' ) )
{
bool ok;
const auto glyphIndex = key.toUInt( &ok );
if ( ok )
return glyphIndex;
}
else if ( key.startsWith( "U+" ) )
{
bool ok;
const char32_t code = key.mid( 2 ).toUInt( &ok, 16 );
if ( ok )
return table.codeToIndex( code );
}
else
{
return table.nameToIndex( key );
}
}
return 0;
}

View File

@ -0,0 +1,35 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_GLYPH_GRAPHIC_PROVIDER_H
#define QSK_GLYPH_GRAPHIC_PROVIDER_H
#include "QskGraphicProvider.h"
class QRawFont;
class QSK_EXPORT QskGlyphGraphicProvider : public QskGraphicProvider
{
using Inherited = QskGraphicProvider;
public:
QskGlyphGraphicProvider( QObject* parent = nullptr );
~QskGlyphGraphicProvider() override;
void setIconFont( const QRawFont& );
QRawFont iconFont() const;
QskGraphic glyphGraphic( uint glyphIndex ) const;
protected:
const QskGraphic* loadGraphic( const QString& ) const override final;
virtual uint glyphIndex( const QString& ) const;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
#endif

View File

@ -0,0 +1,489 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#include "QskGlyphTable.h"
#include "QskGraphic.h"
#include "QskInternalMacros.h"
#include <qrawfont.h>
#include <qpainter.h>
#include <qpainterpath.h>
#include <qendian.h>
QSK_QT_PRIVATE_BEGIN
#include <private/qrawfont_p.h>
QSK_QT_PRIVATE_END
typedef QHash< QString, uint > GlyphNameTable;
/*
The "parsers" below do no validation checks as the font has
already been validated by QRawFont
Hope QRawFont will extend its API some day ( the underlying
font libraries do support glyph names ) and we can remove the nasty
code below. see https://bugreports.qt.io/browse/QTBUG-132629
*/
namespace PostTableParser
{
// https://learn.microsoft.com/en-us/typography/opentype/spec/post
static inline QString toString( const uint8_t* s )
{
// Pascal string. Valid characters are: [AZ] [az] [09] '.' '_'
return QString::fromUtf8(
reinterpret_cast< const char* > ( s + 1 ), *s );
}
static GlyphNameTable glyphNames( const QByteArray& blob )
{
GlyphNameTable names;
const auto* glyphData = reinterpret_cast< const uint16_t* >( blob.constData() + 32 );
if ( const auto nglyphs = qFromBigEndian( *glyphData++ ) )
{
QVarLengthArray< const uint8_t* > strings;
strings.reserve( nglyphs );
const auto from = reinterpret_cast< const uint8_t* >( glyphData + nglyphs );
const auto to = reinterpret_cast< const uint8_t* >( blob.data() + blob.size() );
for ( auto s = from; s < to; s += *s + 1 )
strings += s;
for ( int i = 0; i < nglyphs; i++ )
{
const int idx = qFromBigEndian( glyphData[i] ) - 258;
if ( idx >= 0 )
names.insert( toString( strings[idx] ), i );
}
}
return names;
}
}
namespace CFFTableParser
{
// https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf
static uint32_t offsetAt( const uint8_t* d, int size )
{
switch (size)
{
case 0:
return 0;
case 1:
return d[0];
case 2:
return ( d[0] << 8 ) | d[1];
case 3:
return ( d[0] << 16 ) | ( d[1] << 8 ) | d[2];
default:
return ( d[0] << 24 ) | ( d[1] << 16 ) | ( d[2] << 8 ) | d[3];
}
}
static int indexDataSize( const uint8_t* d )
{
const int nitems = ( d[0] << 8 ) | d[1];
if ( nitems == 0 )
return 2;
const int size = d[2];
const uint8_t* lx = d + 3 + nitems * size;
return lx + size - 1 + offsetAt( lx, size ) - d;
}
static const uint8_t* indexData( const uint8_t* d )
{
const int nitems = ( d[0] << 8 ) | d[1];
d += 2;
if ( nitems == 0 )
return d;
const int size = d[0];
const uint8_t* _contents = d + ( nitems + 1 ) * size;
return _contents + offsetAt(d + 1, size);
}
static const uint8_t* skipHeader( const uint8_t* d )
{
return d + d[2];
}
static const uint8_t* skipIndex( const uint8_t* d )
{
return d + indexDataSize( d );
}
static QVector< int > stringIds( const uint8_t* data, int nglyphs )
{
const int format = data[0];
QVector< int > _sids;
_sids += 0;
const uint8_t* p = data + 1;
switch( format )
{
case 0:
{
for (; _sids.size() < nglyphs; p += 2)
{
int sid = ( p[0] << 8 ) | p[1];
_sids += sid;
}
break;
}
case 1:
{
for (; _sids.size() < nglyphs; p += 3)
{
const int sid = ( p[0] << 8 ) | p[1];
const int n = p[2];
for ( int i = 0; i <= n; i++ )
_sids += sid + i;
}
break;
}
case 2:
{
for (; _sids.size() < nglyphs; p += 4)
{
const int sid = ( p[0] << 8 ) | p[1];
const int n = ( p[2] << 8 ) | p[3];
for ( int i = 0; i <= n; i++ )
_sids += sid + i;
}
break;
}
}
return _sids;
}
static int dictValue( const uint8_t* d, int op )
{
/*
see https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf
We are intersted in the offset ( operator 15 ).
*/
const uint8_t* data = indexData( d );
int value = 0;
Q_FOREVER
{
// operand
const auto valueType = data[0];
if ( valueType == 28 )
{
value = ( data[1] << 8 ) | data[2];
data += 3;
}
else if ( valueType == 29 )
{
value = ( data[1] << 24 ) | ( data[2] << 16 )
| ( data[3] << 8 ) | data[4];
data += 5;
}
else if ( valueType == 30 )
{
/*
Assuming, that an offset is never a double
we skip the operand without reading it
*/
while( ++data )
{
const int b = *data;
if ( ( b & 0x0f ) == 0x0f || ( b & 0xf0 ) == 0xf0 )
break; // 0xf nibble indicating the end
}
data++;
}
else if ( valueType >= 31 && valueType <= 246 )
{
value = data[0] - 139;
data++;
}
else if ( valueType >= 247 && valueType <= 250 )
{
value = ( ( data[0] - 247 ) << 8 ) + data[1] + 108;
data += 2;
}
else if ( valueType >= 251 && valueType <= 254 )
{
value = -( ( data[0] - 251 ) << 8 ) - data[1] - 108;
data += 2;
}
// operator
if ( op == data[0] )
return value;
data += ( data[0] == 12 ) ? 2 : 1;
}
return 0; // default value
}
class StringTable
{
public:
StringTable( const uint8_t* data )
{
const int nitems = ( data[0] << 8 ) | data[1];
if ( nitems == 0 )
{
_contents = data + 2;
_offset = nullptr;
_offsize = 0;
}
else
{
_offsize = data[2];
_offset = data + 3;
_contents = _offset + nitems * _offsize + _offsize - 1;
}
}
inline QString operator[]( int which ) const
{
const auto x = _offset + which * _offsize;
const auto d1 = _contents + offsetAt(x, _offsize);
const auto d2 = _contents + offsetAt(x + _offsize, _offsize);
return QString::fromUtf8(
reinterpret_cast< const char* >( d1 ), d2 - d1 );
}
private:
const uint8_t* _contents = nullptr;
const uint8_t* _offset = nullptr;
int _offsize = -1;
};
static GlyphNameTable glyphNames( const QByteArray& blob, int glyphCount )
{
auto data = reinterpret_cast< const uint8_t* >( blob.constData() );
auto nameIndex = skipHeader( data );
auto dictIndex = skipIndex( nameIndex );
auto stringIndex = skipIndex( dictIndex );
auto charset = data + dictValue( dictIndex, 15 ); // 15: charset offset
const QVector< int > sids = stringIds( charset, glyphCount );
const StringTable table( stringIndex );
GlyphNameTable names;
for ( int i = 0; i < glyphCount; i++ )
{
/*
The first 391 SIDs are reserved for standard strings
( Appendix A ) that are not from the charset table.
*/
const auto idx = sids[i] - 391;
if ( idx >= 0 )
names.insert( table[idx], i );
}
return names;
}
}
static uint qskGlyphCount( const QRawFont& font )
{
/*
we could also read the count from the "maxp" table:
https://learn.microsoft.com/en-us/typography/opentype/spec/maxp
*/
const auto fontEngine = QRawFontPrivate::get( font )->fontEngine;
return fontEngine ? fontEngine->glyphCount() : 0;
}
static GlyphNameTable qskGlyphNameTable( const QRawFont& font )
{
const auto count = qskGlyphCount( font );
if ( count > 0 )
{
/*
The Compact Font Format ( CFF ) table has been introduced with
the OpenType specification. For not complying fonts the names
might be found in the Post table
*/
auto blob = font.fontTable( "CFF ");
if ( !blob.isEmpty() )
return CFFTableParser::glyphNames( blob, count );
blob = font.fontTable( "post" );
if ( !blob.isEmpty() )
return PostTableParser::glyphNames( blob );
}
return GlyphNameTable();
}
static inline quint32 qskGlyphIndex( const QRawFont& font, char32_t ucs4 )
{
if ( qskGlyphCount( font ) == 0 )
return 0;
const auto idxs = font.glyphIndexesForString(
QString::fromUcs4( &ucs4, 1 ) );
// fingers crossed: icon fonts will map code points to single glyphs only
Q_ASSERT( idxs.size() == 1 );
return idxs.size() == 1 ? idxs[0] : 0;
}
class QskGlyphTable::PrivateData
{
public:
inline const GlyphNameTable& glyphNameTable() const
{
if ( !validNames )
{
auto that = const_cast< PrivateData* >( this );
that->nameTable = qskGlyphNameTable( font );
that->validNames = true;
}
return nameTable;
}
QRawFont font;
GlyphNameTable nameTable;
bool validNames = false;
};
QskGlyphTable::QskGlyphTable()
: m_data( new PrivateData )
{
}
QskGlyphTable::QskGlyphTable( const QRawFont& font )
: QskGlyphTable()
{
m_data->font = font;
}
QskGlyphTable::QskGlyphTable( const QskGlyphTable& other )
: QskGlyphTable()
{
*m_data = *other.m_data;
}
QskGlyphTable::~QskGlyphTable()
{
}
QskGlyphTable& QskGlyphTable::operator=( const QskGlyphTable& other )
{
if ( m_data != other.m_data )
*m_data = *other.m_data;
return *this;
}
void QskGlyphTable::setIconFont( const QRawFont& font )
{
if ( font != m_data->font )
{
m_data->font = font;
m_data->nameTable.clear();
m_data->validNames = false;
}
}
QRawFont QskGlyphTable::iconFont() const
{
return m_data->font;
}
QPainterPath QskGlyphTable::glyphPath( uint glyphIndex ) const
{
QPainterPath path;
/*
Unfortunately QRawFont::pathForGlyph runs into failing checks
when being called from a different thread - f.e the scene graph thread.
So we need to bypass QRawFont and retrieve from its fontEngine.
*/
if ( auto fontEngine = QRawFontPrivate::get( m_data->font )->fontEngine )
{
QFixedPoint position;
quint32 idx = glyphIndex;
fontEngine->addGlyphsToPath( &idx, &position, 1, &path, {} );
}
return path;
}
QskGraphic QskGlyphTable::glyphGraphic( uint glyphIndex ) const
{
QskGraphic graphic;
if ( glyphIndex > 0 && qskGlyphCount( m_data->font ) > 0 )
{
const auto path = glyphPath( glyphIndex );
if ( !path.isEmpty() )
{
QPainter painter( &graphic );
painter.setRenderHint( QPainter::Antialiasing, true );
painter.fillPath( path, Qt::black );
}
}
return graphic;
}
uint QskGlyphTable::glyphCount() const
{
return qskGlyphCount( m_data->font );
}
uint QskGlyphTable::codeToIndex( char32_t ucs4 ) const
{
return qskGlyphIndex( m_data->font, ucs4 );
}
uint QskGlyphTable::nameToIndex( const QString& name ) const
{
/*
Names/Codes that do not correspond to any glyph in should
be mapped to glyph index 0.
see https://learn.microsoft.com/en-us/typography/opentype/spec/cmap
*/
return m_data->glyphNameTable().value( name.toLatin1(), 0 );
}
QHash< QString, uint > QskGlyphTable::nameTable() const
{
return m_data->glyphNameTable();
}

View File

@ -0,0 +1,72 @@
/******************************************************************************
* QSkinny - Copyright (C) The authors
* SPDX-License-Identifier: BSD-3-Clause
*****************************************************************************/
#ifndef QSK_GLYPH_TABLE_H
#define QSK_GLYPH_TABLE_H
#include "QskGlobal.h"
#include <memory>
class QskGraphic;
class QRawFont;
class QString;
class QPainterPath;
class QByteArray;
class QChar;
template< typename Key, typename T > class QHash;
class QSK_EXPORT QskGlyphTable
{
public:
QskGlyphTable();
QskGlyphTable( const QRawFont& );
QskGlyphTable( const QskGlyphTable& );
~QskGlyphTable();
QskGlyphTable& operator=( const QskGlyphTable& );
bool isValid() const;
void setIconFont( const QRawFont& );
QRawFont iconFont() const;
uint glyphCount() const;
QPainterPath glyphPath( uint glyphIndex ) const;
QskGraphic glyphGraphic( uint glyphIndex ) const;
/*
Most icon fonts use code points from the Unicode Private Use Areas (PUA)
( see https://en.wikipedia.org/wiki/Private_Use_Areas ):
- [0x00e000, 0x00f8ff]
- [0x0f0000, 0x0ffffd]
- [0x100000, 0x10fffd]
Note that QChar is 16-bit entity only that does not cover the higher PUA blocks.
*/
uint codeToIndex( char32_t ) const;
/*
True/OpenType fonts often include a table with glyph names, that can be used
instead of the glyph index
*/
uint nameToIndex( const QString& ) const;
QHash< QString, uint > nameTable() const;
private:
class PrivateData;
std::unique_ptr< PrivateData > m_data;
};
inline bool QskGlyphTable::isValid() const
{
return glyphCount() > 0;
}
#endif