FreeTypeを使う 新しいページはコチラ

提供: yonewiki
移動: 案内, 検索
(サンプル4.公式サイトのErik Mollerさん作成その2 Qt版)
(サンプル4.公式サイトのErik Mollerさん作成その2 Qt版)
1,230行: 1,230行:
 
 こういう作業をすることは勉強にはなりません。これを当たり前のようにこなしてから、どうすることが正しかったのかを考えることが大事です。でも今回は管理人には必要ない知識なので、ここではやりません。人が作ったものを使いこなすのは大変だということです。ユーザ数が少ない。文献がすくなければなおさら面倒です。必要に駆られるまで手は出さない。動けばいいな。程度。1週間やってもだめなら諦めますね。パズルと同じです。
 
 こういう作業をすることは勉強にはなりません。これを当たり前のようにこなしてから、どうすることが正しかったのかを考えることが大事です。でも今回は管理人には必要ない知識なので、ここではやりません。人が作ったものを使いこなすのは大変だということです。ユーザ数が少ない。文献がすくなければなおさら面倒です。必要に駆られるまで手は出さない。動けばいいな。程度。1週間やってもだめなら諦めますね。パズルと同じです。
  
 
+
 
 +
=== ''' サンプル5.公式サイトのRóbert Márkiさん作成 ''' ===
 +
 Róbertが作成したQtプロジェクトでのサンプルですが、プロジェクトファイルが配布されているわけでもないので、再現するのにはどうすればいいのかが、よくわからなかったので、自分でイチカラQt Guiプロジェクト作りこみながら、再現してみました。qmakeファイル配布されてましたけど、何をどうしろというのかというような内容でして、ここまで来て思ったんですけど、FreeTypeのサンプル集はどれも冷たい。どうやってビルドするべきかを環境とツールごとに分けて記述しているプロジェクトもある昨今なのに、ソースファイルとよくわからない*.proファイルの配布。冷たい。
 +
 
 +
 
 +
 不満を並べてもしょうがないので、ビルド手順を簡単に。
 +
 
 +
 1.VisualStudioでQt Wigets Applicatioの新規作成を始めます。
 +
 
 +
 2.今回の場合Wizardがいろいろと分類してくれるのは、ありがたくないのですが、Wizardのいうとおりに作るので、BaseClassを指定するところだけQMainWindowではなく、QWidgetに変更します。あとは規定値でよいです。
 +
 
 +
 3.したらばプログラムを書きます。分割プログラムの形式なのでやや複雑ですが、以下の通り記述します。
 +
 
 +
 まずmain.cpp
 +
 
 +
<Syntaxhighlight2 lang="cpp" line start="1">
 +
#include "QtSampleProject.h"
 +
#include <QtWidgets/QApplication>
 +
 
 +
#include <QPainter>
 +
#include <QFile>
 +
 
 +
#include <iostream>
 +
 
 +
#include <ft2build.h>
 +
#include FT_FREETYPE_H
 +
#include FT_OUTLINE_H
 +
 
 +
QString g_usageText =
 +
"usage:\n"
 +
"example4 FONT_PATH CHARACTER SIZE DIRECT_RENDERING_MODE(1|0)";
 +
 
 +
int main(int argc, char *argv[])
 +
{
 +
    bool status = false;
 +
    bool isSizeOk = false;
 +
    QString path = "C:\\Windows\\Fonts\\BIZ-UDGothicR.ttc";
 +
    QChar character = 'm';
 +
    int size = QString("60").toInt(&isSizeOk);
 +
    bool directRender = QString("1").toInt();
 +
 
 +
    if (QFile::exists(path) && isSizeOk) {
 +
        status = true;
 +
        QApplication a(argc, argv);
 +
        QtSampleProject w(path, character, size, directRender);
 +
        w.show();
 +
        return a.exec();
 +
    }
 +
    if (!status) {
 +
        std::cout << qPrintable(g_usageText) << std::endl;
 +
        return 0;
 +
    }
 +
}
 +
 
 +
 
 +
</Syntaxhighlight2>
 +
 
 +
 
 +
プロジェクト名.cpp ここでは仮にQtSampleProjectとしておきます。
 +
 
 +
<Syntaxhighlight2 lang="cpp" line start="1">
 +
#include "QtSampleProject.h"
 +
 
 +
QtSampleProject::QtSampleProject(QWidget *parent)
 +
    : QWidget(parent)
 +
{
 +
    m_face = 0;
 +
    m_library = 0;
 +
    m_directRender = 0;
 +
    ui.setupUi(this);
 +
}
 +
QtSampleProject::QtSampleProject(const QString& fileName, QChar character, int pointSize, bool directRender, QWidget* parent) : QWidget(parent), m_directRender(directRender)
 +
{
 +
    FT_Error error = FT_Err_Ok;
 +
    m_face = 0;
 +
    m_library = 0;
 +
    error = FT_Init_FreeType(&m_library);
 +
    if(!error){
 +
        error = FT_New_Face(m_library, fileName.toLatin1().constData(), 0, &m_face);
 +
 
 +
        if (!error) {
 +
            error = FT_Set_Char_Size(m_face, 0, pointSize * 64, physicalDpiX(), physicalDpiY());
 +
            if (!error) {
 +
                FT_UInt glyph_index = 0;
 +
                glyph_index = FT_Get_Char_Index(m_face, character.unicode());
 +
                error = FT_Load_Glyph(m_face, glyph_index, FT_LOAD_DEFAULT);
 +
                if (!error) {
 +
                    FT_Pos left = m_face->glyph->metrics.horiBearingX;
 +
                    FT_Pos right = left + m_face->glyph->metrics.width;
 +
                    FT_Pos top = m_face->glyph->metrics.horiBearingY;
 +
                    FT_Pos bottom = top - m_face->glyph->metrics.height;
 +
 
 +
                    m_glyphRect = QRect(QPoint(TRUNC(left),
 +
                        -TRUNC(top) + 1),
 +
                        QSize (TRUNC(right - left) + 1,
 +
                            TRUNC(top - bottom) + 1)
 +
                    );
 +
                    setFixedSize(m_glyphRect.width(), m_glyphRect.height());
 +
                }
 +
            }
 +
        }
 +
    }
 +
    ui.setupUi(this);
 +
}
 +
QtSampleProject::~QtSampleProject()
 +
{
 +
    if(m_face){
 +
        FT_Done_Face(m_face);
 +
    }
 +
    if(m_library){
 +
        FT_Done_FreeType(m_library);
 +
    }
 +
   
 +
}
 +
 
 +
void QtSampleProject::graySpans(int y, int count, const FT_Span_* spans, void* user) {
 +
    QPainter* painter = (QPainter*)user;
 +
    y = -y;
 +
 
 +
    for (int i = 0; i < count; i++) {
 +
        const FT_Span span = spans[i];
 +
        qreal opacity = qreal(span.coverage) / 255.0;
 +
 
 +
        painter->setOpacity(opacity);
 +
 
 +
        if (span.len > 1) {
 +
            painter->drawLine(span.x, y, span.x + span.len - 1, y);
 +
        }
 +
        else {
 +
            painter->drawPoint(span.x, y);
 +
        }
 +
    }
 +
}
 +
 
 +
void QtSampleProject::paintEvent(QPaintEvent* event) {
 +
    QWidget::paintEvent(event);
 +
 
 +
    if (m_library && m_face) {
 +
        FT_Error error = FT_Err_Ok;
 +
        QPainter painter(this);
 +
        painter.translate(-m_glyphRect.x(), -m_glyphRect.y());
 +
        if (m_directRender) {
 +
            painter.setPen(Qt::black);
 +
            FT_Raster_Params params;
 +
 
 +
            params.target = 0;
 +
            params.flags = FT_RASTER_FLAG_DIRECT | FT_RASTER_FLAG_AA;
 +
            params.user = &painter;
 +
            params.gray_spans = &QtSampleProject::graySpans;
 +
            params.black_spans = 0;
 +
            params.bit_set = 0;
 +
            params.bit_test = 0;
 +
 
 +
            FT_Outline* outline = &m_face->glyph->outline;
 +
            FT_Outline_Render(m_library, outline, &params);
 +
        }
 +
        else {
 +
            error = FT_Render_Glyph(m_face->glyph, FT_RENDER_MODE_NORMAL);
 +
            QImage glyphImage(m_face->glyph->bitmap.buffer,
 +
                m_face->glyph->bitmap.width,
 +
                m_face->glyph->bitmap.rows,
 +
                m_face->glyph->bitmap.pitch,
 +
                QImage::Format_Indexed8);
 +
            painter.translate(m_glyphRect.x(), m_glyphRect.y());
 +
 
 +
            QVector<QRgb> colorTable;
 +
            for (int i = 0; i < 256; ++i) {
 +
                colorTable << qRgba(0, 0, 0, i);
 +
            }
 +
            glyphImage.setColorTable(colorTable);
 +
            painter.drawImage(QPoint(0, 0), glyphImage);
 +
        }
 +
    }
 +
}
 +
</Syntaxhighlight2>
 +
 
 +
プロジェクト名.h
 +
 
 +
<Syntaxhighlight2 lang="cpp" line start="1">
 +
#pragma once
 +
 
 +
#include <QtWidgets/QWidget>
 +
#include "ui_QtSampleProject.h"
 +
 
 +
#include <QPainter>
 +
#include <QFile>
 +
 
 +
#include <iostream>
 +
 
 +
#include <ft2build.h>
 +
#include FT_FREETYPE_H
 +
#include FT_OUTLINE_H
 +
 
 +
#define TRUNC(x) ((x) >> 6)
 +
 
 +
class QtSampleProject : public QWidget
 +
{
 +
    Q_OBJECT
 +
 
 +
public:
 +
    QtSampleProject(QWidget* parent = nullptr);
 +
    QtSampleProject(const QString& fileName, QChar character, int pointSize, bool directRender, QWidget* parent = 0);
 +
  ~QtSampleProject();
 +
 
 +
private:
 +
    bool m_directRender = 0;
 +
    FT_Library m_library = 0;
 +
    FT_Face m_face = 0;
 +
    QRect m_glyphRect;
 +
 
 +
    static void graySpans(int y, int count, const FT_Span_* spans, void* user);
 +
    Ui::QtSampleProjectClass ui;
 +
 
 +
protected:
 +
    void paintEvent(QPaintEvent* event);
 +
};
 +
 
 +
</Syntaxhighlight2>
 +
 
  
 
[[フォント TrueType 構造解析]]に戻る。
 
[[フォント TrueType 構造解析]]に戻る。

2022年8月22日 (月) 00:00時点における版



個人用ツール
名前空間

変種
操作
案内
ツールボックス