StrataSource / vtex2

A VTF converter and editor
MIT License
41 stars 6 forks source link

worldtext font atlas creation #1

Open JJL772 opened 2 years ago

JJL772 commented 2 years ago

Hammer and in-game world text entities use a basic font atlas to draw fonts in game. vtex2 should add an action to generate a font atlas from a .ttf or .otf file.

worldtextsheet.vtf looks like this for example: image

Trico-Everfire commented 4 months ago

I have code for this for the GUI, TTF and OTF. this is only because QT is quite excellent at rasterizing fonts. Trust me, this took me longer than I'd like to admit.

    int id = QFontDatabase::addApplicationFont( filepath );
    QString family = QFontDatabase::applicationFontFamilies( id ).at( 0 );
    QString charList = R"( !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|})";

    QTextOption opts;

    QBuffer buff;
    QImage image( QSize( 1024, 1024 ), QImage::Format_RGBA8888 );

    QPainter painter;
    painter.begin( &image );
    // This fixes a weird issue where background will become garbage data
    // if not cleared first. 
    painter.setCompositionMode( QPainter::CompositionMode_Source );
    painter.fillRect( QRect( 0, 0, 1024, 1024 ), QColor( 0, 0, 0, 0 ) );
    painter.setCompositionMode( QPainter::CompositionMode_SourceOver );
    painter.setBrush( Qt::transparent );
    painter.setPen( QPen( Qt::white ) );
    auto font = QFont( family );
    auto offset = 32;
    font.setPointSize( offset );
    painter.setFont( font );

    //  painter.drawRect( 0, 0, 1024, 1024 );
    for ( int i = 0, j = 0, k = 0; k < charList.length(); i++, k++ )
    {
        if ( i > 15 )
        {
            j++;
            i = 0;
        }
        painter.drawText( ( i * 64 ) + offset / 2, ( j * 64 ) + offset * 1.5, charList[k] );
    }
    painter.end();

    QByteArray im;
    QBuffer bufferrgb( &im );
    bufferrgb.open( QIODevice::WriteOnly );

    image.save( &bufferrgb, "PNG" );

    int x, y, n;

    stbi_uc *data = stbi_load_from_memory( reinterpret_cast<const stbi_uc *>( bufferrgb.data().constData() ), bufferrgb.size(), &x, &y, &n, 4 );
    QFontDatabase::removeApplicationFont( id );

For the CLI it'd be really difficult unless the CLI becomes a QT application itself.