Subversion Repositories Scribus

Rev

Rev 24464 | Blame | Compare with Previous | Last modification | View Log | RSS feed

//
//  cff.h
//  Scribus
//
//  Created by Andreas Vox on 04.05.15.
//
//

#ifndef Scribus__cff_h
#define Scribus__cff_h


#include "scribusapi.h"

#include <QByteArray>
#include <QDataStream>
#include <QHash>
#include <QList>
#include <QMap>
#include <QString>

#include <ft2build.h>
#include FT_FREETYPE_H

namespace cff {
       
        typedef quint16 sid_type;
        typedef uint operator_type;
       
        enum sid_range {
                sid_min = 0,
                sid_last_std = 390,
                sid_max = 64999,
                sid_max1 = 65000
        };
       
        enum CFF_Header_Format {
                cff_major   = 0,
                cff_minor   = 1,
                cff_hdrSize = 2,
                cff_offSize = 3
        };
       
       
        enum CFF_INDEX_Format {
                cff_idx_count   = 0,
                cff_idx_offsize = 2,
                cff_idx_offsets = 3
        };
       
       
        enum cff_Real_Format {
                cff_nibble_maxDigit = 9,
                cff_nibble_Point    = 10,
                cff_nibble_PosExp   = 11,
                cff_nibble_NegExp   = 12,
                cff_nibble_Reserved = 13,
                cff_nibble_Minus    = 14,
                cff_nibble_End      = 15
        };
       
       
        enum CFF_DICT_Format {
                cff_dict_version            = 0x00,
                cff_dict_Notice             = 0x01,
                cff_dict_FullName           = 0x02,
                cff_dict_FamilyName         = 0x03,
                cff_dict_Weight             = 0x04,
                cff_dict_FontBBox           = 0x05,
                cff_dict_BlueValues         = 0x06,
                cff_dict_OtherBlues         = 0x07,
                cff_dict_FamilyBlues        = 0x08,
                cff_dict_FamilyOtherBlues   = 0x09,
                cff_dict_StdHW              = 0x0a,
                cff_dict_StdVW              = 0x0b,
                cff_dict_TwoBytes           = 12,
                cff_dict_UniqueID           = 0x0d,
                cff_dict_XUID               = 0x0e,
                cff_dict_charset            = 0x0f,
                cff_dict_Encoding           = 0x10,
                cff_dict_CharStrings        = 0x11,
                cff_dict_Private            = 0x12,
                cff_dict_Subrs              = 0x13,
                cff_dict_defaultWidthX      = 0x14,
                cff_dict_nominalWidthX      = 0x15,
                // 0x16+ reserved
                cff_dict_Card16             = 28,
                cff_dict_Card32             = 29,
                cff_dict_Real               = 30,
                cff_dict_minOperand         = 32,
                cff_dict_maxSmallCard       = 246,
                cff_dict_biasSmallCard      = -139,
                cff_dict_minPosCard         = 247,
                cff_dict_maxPosCard         = 250,
                cff_dict_biasPosCard        = 108,
                cff_dict_minNegCard         = 251,
                cff_dict_maxNegCard         = 254,
                cff_dict_biasNegCard        = -108,
                cff_dict_Copyright          = 0x0c00,
                cff_dict_isFixedPitch       = 0x0c01,
                cff_dict_ItalicAngle        = 0x0c02,
                cff_dict_UnderlinePosition  = 0x0c03,
                cff_dict_UnderlineThickness = 0x0c04,
                cff_dict_CharstringType     = 0x0c06,
                cff_dict_FontMatrix         = 0x0c07,
                cff_dict_StrokeWidth        = 0x0c08,
                cff_dict_BlueScale          = 0x0c09,
                cff_dict_BlueShift          = 0x0c0a,
                cff_dict_BlueFuzz           = 0x0c0b,
                cff_dict_StemSnapH          = 0x0c0c,
                cff_dict_StemSnapV          = 0x0c0d,
                cff_dict_ForceBold          = 0x0c0e,
                // 0c 0f -Reserved-
                // 0c 10 -Reserved-
                cff_dict_LanguageGroup      = 0x0c11,
                cff_dict_ExpansionFactor    = 0x0c12,
                cff_dict_initialRandomSeed  = 0x0c13,
                cff_dict_SyntheticBase      = 0x0c14,
                cff_dict_PostScript         = 0x0c15,
                cff_dict_BaseFontName       = 0x0c16,
                cff_dict_BaseFontBlend      = 0x0c17,
                // 0c 18 -Reserved-
                // 0c 19 -Reserved-
                // 0c 1a -Reserved-
                // 0c 1b -Reserved-
                // 0c 1c -Reserved-
                // 0c 1d -Reserved-
                cff_dict_ROS                = 0x0c1e,
                cff_dict_CIDFontVersion     = 0x0c1f,
                cff_dict_CIDFontRevision    = 0x0c20,
                cff_dict_CIDFontType        = 0x0c21,
                cff_dict_CIDCount           = 0x0c22,
                cff_dict_UIDBase            = 0x0c23,
                cff_dict_FDArray            = 0x0c24,
                cff_dict_FDSelect           = 0x0c25,
                cff_dict_FontName           = 0x0c26
        };
       
       
        enum CFF_Variant_Type
        {
                cff_varnt_Error    = 0,
                cff_varnt_Bool     = 1,
                cff_varnt_Card     = 2,
                cff_varnt_SID      = 3,
                cff_varnt_Real     = 4,
                cff_varnt_Array    = 5,
                cff_varnt_Delta    = 6,
                cff_varnt_Operator = 7
        };

       
        struct CFF_Number
        {
                long long   card {0};
                int         exponent {0};
                uchar       type {0};
                bool        isCardinal() const;
                double      toDouble() const;
                int         toCardinal() const;
                CFF_Number() {};
        };
       

        struct CFF_Variant
        {
                uchar type;
                QList<CFF_Number> array;
                CFF_Variant()                      : type(cff_varnt_Error) {}
                CFF_Variant(CFF_Number val)        : type(val.type) { array.append(val); }
                CFF_Variant(const QList<CFF_Number>& arr) : type(cff_varnt_Array), array(arr) {}
        };
       
       
        class CFF {
        public:
                /// For creating new CFF fonts
                CFF();
                CFF(const QByteArray& cff);

                uint readCard(uint pos) const;
                QByteArray readSegment(uint pos, uint size) const;
                QMap<operator_type,CFF_Variant> getDict(const QByteArray& dict) const;
                QList<QByteArray> readIndex(uint& pos) const;
                CFF extractSubset(uint faceIndex, QList<uint> cids) const;
               
                void dump();
                QByteArray dump(const CFF_Variant& var) const;
               
                const QByteArray& data() const {
                        return m_bytes;
                }
               
                QList<QByteArray> fontNames() const {
                        return m_fontTopDicts.keys();
                }
               
                uint offset(uint unscaled)
                {
                        return unscaled * m_offsetSize;
                }
               
                QByteArray string(sid_type sid) const {
                        return sid < m_strings.length()? m_strings[sid] : QByteArray();
                }
               
                sid_type sid(const QByteArray str) const {
                        return m_sids.contains(str)? m_sids[str] : sid_max1;
                }
               
                void dump(QDataStream& out) const;
               
        private:
                QByteArray m_bytes;
                uint m_offsetSize;
               
                QList<QByteArray> m_names;
                QMap<QByteArray, QMap<uint,CFF_Variant> > m_fontTopDicts;
                QList<QByteArray> m_strings;
                QHash<QByteArray,uint> m_sids;
                QList<QByteArray> m_globalSubr;
               
                sid_type createSid(const QByteArray& str);
               
                CFF_Number parseDictElement(const QByteArray& dict, uint& pos) const;
                CFF_Number parseReal(const QByteArray& dict, uint& pos) const;
                CFF_Number parseCard(const QByteArray& dict, uint& pos) const;
                QList<sid_type> readCharset(uint nGlyphs, uint& pos) const;
                QList<uint> readEncoding(uint& pos) const;
               
                /// This write the header, name index and TopDict index for exactly one font.
                /// All unknown offset are preset as 4 byte cardinal and corresponding operator positions returned
                uint writeTopDict(const QByteArray& name, const QMap<operator_type, CFF_Variant>& dict, const QList<QByteArray>& oldStrings, QHash<operator_type, uint>& patchAddresses);
                /// this will write another segment and return the start offset
                uint writeSegment(const QByteArray& data);
                void patch(QHash<operator_type, uint> patchPositions, uint patchOffset, operator_type op, uint offset, uint length = 0);
               
                QByteArray makeCharset(QList<sid_type>) const;
                QByteArray makeEncoding(QList<uint>) const;
                QByteArray makeIndex(QList<QByteArray> data) const;
                QByteArray makeDict(QMap<operator_type, CFF_Variant> dict, const QList<QByteArray>& oldStrings, QHash<operator_type, uint>& patchAddresses);
        };
       
        QByteArray extractFace(const QByteArray& cff, int faceIndex);
        QByteArray subsetFace(const QByteArray& cff, QList<uint> cids, QMap<uint, uint>& glyphMap);
}


#endif /* defined(Scribus__cff_h) */