⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qopentype.cpp

📁 基础c代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************
**
** Copyright (C) 1992-2006 Trolltech AS. All rights reserved.
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** This file may be used under the terms of the GNU General Public
** License version 2.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.  Please review the following information to ensure GNU
** General Public Licensing requirements will be met:
** http://www.trolltech.com/products/qt/opensource.html
**
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://www.trolltech.com/products/qt/licensing.html or contact the
** sales department at sales@trolltech.com.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/

#include "qopentype_p.h"
#include "qfontengine_p.h"
#include "qscriptengine_p.h"

#ifndef QT_NO_FREETYPE
//  --------------------------------------------------------------------------------------------------------------------
// Open type support
//  --------------------------------------------------------------------------------------------------------------------

//#define OT_DEBUG

#ifdef OT_DEBUG
static inline char *tag_to_string(FT_ULong tag)
{
    static char string[5];
    string[0] = (tag >> 24)&0xff;
    string[1] = (tag >> 16)&0xff;
    string[2] = (tag >> 8)&0xff;
    string[3] = tag&0xff;
    string[4] = 0;
    return string;
}
#endif

#define DefaultLangSys 0xffff
#define DefaultScript FT_MAKE_TAG('D', 'F', 'L', 'T')

enum {
    RequiresGsub = 1,
    RequiresGpos = 2
};

struct OTScripts {
    unsigned int tag;
    int flags;
};
static const OTScripts ot_scripts [] = {
    // Common
    { FT_MAKE_TAG('D', 'F', 'L', 'T'), 0 },
    // Hebrew
    { FT_MAKE_TAG('h', 'e', 'b', 'r'), 1 },
    // Arabic
    { FT_MAKE_TAG('a', 'r', 'a', 'b'), 1 },
    // Syriac
    { FT_MAKE_TAG('s', 'y', 'r', 'c'), 1 },
    // Thaana
    { FT_MAKE_TAG('t', 'h', 'a', 'a'), 1 },
    // Devanagari
    { FT_MAKE_TAG('d', 'e', 'v', 'a'), 1 },
    // Bengali
    { FT_MAKE_TAG('b', 'e', 'n', 'g'), 1 },
    // Gurmukhi
    { FT_MAKE_TAG('g', 'u', 'r', 'u'), 1 },
    // Gujarati
    { FT_MAKE_TAG('g', 'u', 'j', 'r'), 1 },
    // Oriya
    { FT_MAKE_TAG('o', 'r', 'y', 'a'), 1 },
    // Tamil
    { FT_MAKE_TAG('t', 'a', 'm', 'l'), 1 },
    // Telugu
    { FT_MAKE_TAG('t', 'e', 'l', 'u'), 1 },
    // Kannada
    { FT_MAKE_TAG('k', 'n', 'd', 'a'), 1 },
    // Malayalam
    { FT_MAKE_TAG('m', 'l', 'y', 'm'), 1 },
    // Sinhala
    // ### could not find any OT specs on this
    { FT_MAKE_TAG('s', 'i', 'n', 'h'), 1 },
    // Thai
    { FT_MAKE_TAG('t', 'h', 'a', 'i'), 1 },
    // Lao
    { FT_MAKE_TAG('l', 'a', 'o', ' '), 1 },
    // Tibetan
    { FT_MAKE_TAG('t', 'i', 'b', 't'), 1 },
    // Myanmar
    { FT_MAKE_TAG('m', 'y', 'm', 'r'), 1 },
    // Hangul
    { FT_MAKE_TAG('h', 'a', 'n', 'g'), 1 },
    // Khmer
    { FT_MAKE_TAG('k', 'h', 'm', 'r'), 1 },
};

QOpenType::QOpenType(QFontEngine *fe, FT_Face _face)
    : fontEngine(fe), face(_face), gdef(0), gsub(0), gpos(0), current_script(0)
{
    otl_buffer_new(face->memory, &otl_buffer);
    tmpAttributes = 0;
    tmpLogClusters = 0;

    FT_Error error;
    if ((error = TT_Load_GDEF_Table(face, &gdef))) {
#ifdef OT_DEBUG
        qDebug("error loading gdef table: %d", error);
#endif
        gdef = 0;
    }

    if ((error = TT_Load_GSUB_Table(face, &gsub, gdef))) {
        gsub = 0;
#ifdef OT_DEBUG
        if (error != FT_Err_Table_Missing) {
            qDebug("error loading gsub table: %d", error);
        } else {
            qDebug("face doesn't have a gsub table");
        }
#endif
    }

    if ((error = TT_Load_GPOS_Table(face, &gpos, gdef))) {
        gpos = 0;
#ifdef OT_DEBUG
        qDebug("error loading gpos table: %d", error);
#endif
    }
    
    for (uint i = 0; i < QUnicodeTables::ScriptCount; ++i)
        supported_scripts[i] = checkScript(i);
}

QOpenType::~QOpenType()
{
    if (gpos)
        TT_Done_GPOS_Table(gpos);
    if (gsub)
        TT_Done_GSUB_Table(gsub);
    if (gdef)
        TT_Done_GDEF_Table(gdef);
    if (otl_buffer)
        otl_buffer_free(otl_buffer);
    if (tmpAttributes)
        free(tmpAttributes);
    if (tmpLogClusters)
        free(tmpLogClusters);
}

bool QOpenType::checkScript(unsigned int script)
{
    assert(script < QUnicodeTables::ScriptCount);

    uint tag = ot_scripts[script].tag;
    int requirements = ot_scripts[script].flags;

    if (requirements & RequiresGsub) {
        if (!gsub)
            return false;
        
        FT_UShort script_index;
        FT_Error error = TT_GSUB_Select_Script(gsub, tag, &script_index);
        if (error) {
#ifdef OT_DEBUG
            qDebug("could not select script %d in GSub table: %d", (int)script, error);
#endif
            return false;
        }
    }
    
    if (requirements & RequiresGpos) {
        if (!gpos)
            return false;
        
        FT_UShort script_index;
        FT_Error error = TT_GPOS_Select_Script(gpos, script, &script_index);
        if (error) {
#ifdef OT_DEBUG
            qDebug("could not select script in gpos table: %d", error);
#endif
            return false;
        }

    }
    return true;
}


void QOpenType::selectScript(unsigned int script, const Features *features)
{
    if (current_script == script)
        return;
    
    assert(script < QUnicodeTables::ScriptCount);
    // find script in our list of supported scripts.
    uint tag = ot_scripts[script].tag;

    if (gsub && features) {
#ifdef OT_DEBUG
        {
            TTO_FeatureList featurelist = gsub->FeatureList;
            int numfeatures = featurelist.FeatureCount;
            qDebug("gsub table has %d features", numfeatures);
            for(int i = 0; i < numfeatures; i++) {
                TTO_FeatureRecord *r = featurelist.FeatureRecord + i;
                qDebug("   feature '%s'", tag_to_string(r->FeatureTag));
            }
        }
#endif
        TT_GSUB_Clear_Features(gsub);
        FT_UShort script_index;
        FT_Error error = TT_GSUB_Select_Script(gsub, tag, &script_index);
        if (!error) {
#ifdef OT_DEBUG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -