/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */

/**
 * @file ttcr.hxx
 * @brief TrueType font creator
 */

#pragma once

#include <sft.hxx>
#include <vector>

namespace vcl
{
class TrueTypeTable;
struct tdata_loca;
struct table_cmap;
struct TableEntry;


/* TrueType data types */
    typedef struct {
        sal_uInt16 aw;
        sal_Int16  lsb;
    } longHorMetrics;

/** Error codes for most functions */
    enum TTCRErrCodes {
        TTCR_OK,                        /**< no error                                               */
        TTCR_ZEROGLYPHS,                /**< At least one glyph should be defined                   */
        TTCR_UNKNOWN,                   /**< Unknown TrueType table                                 */
        TTCR_NONAMES,                   /**< 'name' table does not contain any names                */
        TTCR_NAMETOOLONG,               /**< 'name' table is too long (string data > 64K)           */
        TTCR_POSTFORMAT                 /**< unsupported format of a 'post' table                   */
    };

    class TrueTypeCreator {
    public:
        /**
         * TrueTypeCreator constructor.
         * Allocates all internal structures.
         */
        TrueTypeCreator(sal_uInt32 tag);
        ~TrueTypeCreator();
        /**
         * Adds a TrueType table to the TrueType creator.
         */
        void AddTable(std::unique_ptr<TrueTypeTable> table);
        /**
         * Removes a TrueType table from the TrueType creator if it is stored there.
         * It also calls a TrueTypeTable destructor.
         * Note: all generic tables (with tag 0) will be removed if this function is
         * called with the second argument of 0.
         * @return value of SFErrCodes type
         */
        void RemoveTable(sal_uInt32 tag);
        /**
         * Writes a TrueType font generated by the TrueTypeCreator to a segment of
         * memory that this method allocates. When it is not needed anymore the caller
         * is supposed to call free() on it.
         * @return value of SFErrCodes type
         */
        SFErrCodes StreamToMemory(std::vector<sal_uInt8>& rOutBuffer);

    private:
        TrueTypeTable *FindTable(sal_uInt32 tag);
        void ProcessTables();

        sal_uInt32 m_tag;                                     /**< TrueType file tag */
        std::vector<std::unique_ptr<TrueTypeTable>> m_tables; /**< List of table tags and pointers */
    };

    /* A generic base class for all TrueType tables */
    class TrueTypeTable {
    protected:
        TrueTypeTable(sal_uInt32 tag_) : m_tag(tag_) {}

    public:
        virtual ~TrueTypeTable();

        /**
         * This function converts the data of a TrueType table to a raw array of bytes.
         * It may allocates the memory for it and returns the size of the raw data in bytes.
         * If memory is allocated it does not need to be freed by the caller of this function,
         * since the pointer to it is stored in the TrueTypeTable and it is freed by the destructor
         * @return TTCRErrCode
         *
         */
        virtual int GetRawData(TableEntry*) = 0;

        sal_uInt32  m_tag = 0;                       /* table tag                                                */
        std::unique_ptr<sal_uInt8[]> m_rawdata;      /* raw data allocated by GetRawData_*()                     */
    };

    class TrueTypeTableGeneric : public TrueTypeTable
    {
    public:
        /**
         *
         * Creates a new raw TrueType table. The difference between this constructor and
         * TrueTypeTableNew_tag constructors is that the latter create structured tables
         * while this constructor just copies memory pointed to by ptr to its buffer
         * and stores its length. This constructor is suitable for data that is not
         * supposed to be processed in any way, just written to the resulting TTF file.
         */
        TrueTypeTableGeneric(sal_uInt32 tag,
                        sal_uInt32 nbytes,
                        const sal_uInt8* ptr);
        TrueTypeTableGeneric(sal_uInt32 tag,
                        sal_uInt32 nbytes,
                        std::unique_ptr<sal_uInt8[]> ptr);
        virtual ~TrueTypeTableGeneric() override;
        virtual int GetRawData(TableEntry*) override;
    private:
        sal_uInt32 m_nbytes;
        std::unique_ptr<sal_uInt8[]> m_ptr;
    };

/**
 * Creates a new 'head' table for a TrueType font.
 * Allocates memory for it. Since a lot of values in the 'head' table depend on the
 * rest of the tables in the TrueType font this table should be the last one added
 * to the font.
 */
    class TrueTypeTableHead : public TrueTypeTable
    {
    public:
        TrueTypeTableHead(sal_uInt32 fontRevision,
                         sal_uInt16 flags,
                         sal_uInt16 unitsPerEm,
                         const sal_uInt8  *created,
                         sal_uInt16 macStyle,
                         sal_uInt16 lowestRecPPEM,
                         sal_Int16  fontDirectionHint);
        virtual ~TrueTypeTableHead() override;
        virtual int GetRawData(TableEntry*) override;

        std::unique_ptr<sal_uInt8[]> m_head;
    };

/**
 * Creates a new 'hhea' table for a TrueType font.
 * Allocates memory for it and stores it in the hhea pointer.
 */
    class TrueTypeTableHhea : public TrueTypeTable
    {
    public:
        TrueTypeTableHhea(sal_Int16  ascender,
                                         sal_Int16  descender,
                                         sal_Int16  linegap,
                                         sal_Int16  caretSlopeRise,
                                         sal_Int16  caretSlopeRun);
        virtual ~TrueTypeTableHhea() override;
        virtual int GetRawData(TableEntry*) override;

        std::unique_ptr<sal_uInt8[]> m_hhea;
    };

/**
 * Creates a new empty 'loca' table for a TrueType font.
 *
 * INTERNAL: gets called only from ProcessTables();
 */
    class TrueTypeTableLoca : public TrueTypeTable
    {
    public:
        TrueTypeTableLoca();
        virtual ~TrueTypeTableLoca() override;
        virtual int GetRawData(TableEntry*) override;

        std::unique_ptr<tdata_loca> m_loca;
    };

/**
 * Creates a new 'maxp' table based on an existing maxp table.
 * If maxp is 0, a new empty maxp table is created
 * size specifies the size of existing maxp table for
 * error-checking purposes
 */
    class TrueTypeTableMaxp : public TrueTypeTable
    {
    public:
        TrueTypeTableMaxp(const sal_uInt8* maxp, int size);
        virtual ~TrueTypeTableMaxp() override;
        virtual int GetRawData(TableEntry*) override;

        std::unique_ptr<sal_uInt8[]> m_maxp;
    };

/**
 * Creates a new empty 'glyf' table.
 */
    class TrueTypeTableGlyf : public TrueTypeTable
    {
    public:
        TrueTypeTableGlyf();
        virtual ~TrueTypeTableGlyf() override;
        virtual int GetRawData(TableEntry*) override;

        /**
         * Add a glyph to a glyf table.
         *
         * @return glyphID of the glyph in the new font
         *
         * NOTE: This function does not duplicate GlyphData, so memory will be
         * deallocated in the table destructor
         */
        sal_uInt32 glyfAdd(std::unique_ptr<GlyphData> glyphdata, AbstractTrueTypeFont *fnt);

        std::vector<std::unique_ptr<GlyphData>> m_list;
    };

/**
 * Creates a new empty 'cmap' table.
 */
    class TrueTypeTableCmap : public TrueTypeTable
    {
    public:
        TrueTypeTableCmap();
        virtual ~TrueTypeTableCmap() override;
        virtual int GetRawData(TableEntry*) override;

        /**
         * Add a character/glyph pair to a cmap table
         */
        void cmapAdd(sal_uInt32 id, sal_uInt32 c, sal_uInt32 g);

    private:
        std::unique_ptr<table_cmap> m_cmap;
    };

/**
 * Creates a new 'name' table. If n != 0 the table gets populated by
 * the Name Records stored in the nr array. This function allocates
 * memory for its own copy of NameRecords, so nr array has to
 * be explicitly deallocated when it is not needed.
 */
    class TrueTypeTableName : public TrueTypeTable
    {
    public:
        TrueTypeTableName(std::vector<NameRecord> nr);
        virtual ~TrueTypeTableName() override;
        virtual int GetRawData(TableEntry*) override;
    private:
        std::vector<NameRecord> m_list;
    };

/**
 * Creates a new 'post' table of one of the supported formats
 */
    class TrueTypeTablePost : public TrueTypeTable
    {
    public:
        TrueTypeTablePost(sal_Int32 format,
                     sal_Int32 italicAngle,
                     sal_Int16 underlinePosition,
                     sal_Int16 underlineThickness,
                     sal_uInt32 isFixedPitch);
        virtual ~TrueTypeTablePost() override;
        virtual int GetRawData(TableEntry*) override;
    private:
        sal_uInt32 m_format;
        sal_uInt32 m_italicAngle;
        sal_Int16  m_underlinePosition;
        sal_Int16  m_underlineThickness;
        sal_uInt32 m_isFixedPitch;
    };

} // namespace

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */