/***************************************************************************
 *   crengine-ng                                                           *
 *   Copyright (C) 2009-2011 Vadim Lopatin <coolreader.org@gmail.com>      *
 *   Copyright (C) 2015 Yifei(Frank) ZHU <fredyifei@gmail.com>             *
 *   Copyright (C) 2020 Konstantin Potapov <pkbo@users.sourceforge.net>    *
 *   Copyright (C) 2018-2021 Aleksey Chernov <valexlin@gmail.com>          *
 *   Copyright (C) 2018-2021 poire-z <poire-z@users.noreply.github.com>    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU General Public License           *
 *   as published by the Free Software Foundation; either version 2        *
 *   of the License, or (at your option) any later version.                *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,            *
 *   MA 02110-1301, USA.                                                   *
 ***************************************************************************/

#ifndef __LV_FONTBOLDTRANSFORM_H_INCLUDED__
#define __LV_FONTBOLDTRANSFORM_H_INCLUDED__

#include <lvfont.h>
#include <lvtextfm.h>

#include "lvfontglyphcache.h"

class LVFontBoldTransform: public LVFont
{
    LVFontRef _baseFontRef;
    LVFont* _baseFont;
    int _hyphWidth;
    int _hShift;
    int _vShift;
    int _size;   // glyph height in pixels
    int _height; // line height in pixels
    //int           _hyphen_width;
    int _baseline;
    LVFontLocalGlyphCache _glyph_cache;
public:
    virtual lUInt32 getFallbackMask() const {
        return _baseFont->getFallbackMask();
    }

    virtual void setFallbackMask(lUInt32 mask) {
        _baseFont->setFallbackMask(mask);
    }

    /// set fallback font for this font
    virtual void setFallbackFont(LVFontRef font) {
        _baseFont->setFallbackFont(font);
    }

    /// get fallback font for this font
    virtual LVFont* getFallbackFont(lUInt32 fallbackPassMask) {
        return _baseFont->getFallbackFont(fallbackPassMask);
    }

    /// returns font weight
    virtual int getWeight() const;

    /// returns italic flag
    virtual int getItalic() const {
        return _baseFont->getItalic();
    }

    LVFontBoldTransform(LVFontRef baseFont, LVFontGlobalGlyphCache* globalCache);

    /// hyphenation character
    virtual lChar32 getHyphChar() {
        return UNICODE_SOFT_HYPHEN_CODE;
    }

    /// hyphen width
    virtual int getHyphenWidth();

    /** \brief get glyph info
        \param glyph is pointer to glyph_info_t struct to place retrieved info
        \return true if glyh was found
    */
    virtual bool getGlyphInfo(lUInt32 code, glyph_info_t* glyph, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0);

    /** \brief get extra glyph metric
    */
    virtual bool getGlyphExtraMetric(glyph_extra_metric_t metric, lUInt32 code, int& value, bool scaled_to_px = true, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0);

    /** \brief measure text
        \param text is text string pointer
        \param len is number of characters to measure
        \param max_width is maximum width to measure line
        \param def_char is character to replace absent glyphs in font
        \param letter_spacing is number of pixels to add between letters
        \return number of characters before max_width reached
    */
    virtual lUInt16 measureText(
            const lChar32* text, int len,
            lUInt16* widths,
            lUInt8* flags,
            int max_width,
            lChar32 def_char,
            TextLangCfg* lang_cfg = NULL,
            int letter_spacing = 0,
            bool allow_hyphenation = true,
            lUInt32 hints = 0,
            lUInt32 fallbackPassMask = 0);

    /** \brief measure text
        \param text is text string pointer
        \param len is number of characters to measure
        \return width of specified string
    */
    virtual lUInt32 getTextWidth(
            const lChar32* text, int len, TextLangCfg* lang_cfg = NULL);

    /** \brief get glyph item
        \param code is unicode character
        \return glyph pointer if glyph was found, NULL otherwise
    */
    virtual LVFontGlyphCacheItem* getGlyph(lUInt32 ch, lChar32 def_char = 0, lUInt32 fallbackPassMask = 0);

    /** \brief get glyph image in 1 byte per pixel format
        \param code is unicode character
        \param buf is buffer [width*height] to place glyph data
        \return true if glyph was found
    */
    //virtual bool getGlyphImage(lUInt16 code, lUInt8 * buf, lChar32 def_char=0 );

    /// returns font baseline offset
    virtual int getBaseline() {
        return _baseline;
    }

    /// returns font height
    virtual int getHeight() const {
        return _height;
    }

    /// returns font character size
    virtual int getSize() const {
        return _size;
    }

    /// returns char width
    virtual int getCharWidth(lChar32 ch, lChar32 def_char = 0) {
        int w = _baseFont->getCharWidth(ch, def_char) + _hShift;
        return w;
    }

    /// returns char glyph left side bearing
    virtual int getLeftSideBearing(lChar32 ch, bool negative_only = false, bool italic_only = false) {
        return _baseFont->getLeftSideBearing(ch, negative_only, italic_only);
    }

    /// returns char glyph right side bearing
    virtual int getRightSideBearing(lChar32 ch, bool negative_only = false, bool italic_only = false) {
        return _baseFont->getRightSideBearing(ch, negative_only, italic_only);
    }

    /// returns extra metric
    virtual int getExtraMetric(font_extra_metric_t metric, bool scaled_to_px = true);

    /// returns if font has OpenType Math tables
    virtual bool hasOTMathSupport() const;

    /// retrieves font handle
    virtual void* GetHandle() {
        return NULL;
    }

    /// returns font typeface name
    virtual lString8 getTypeFace() const {
        return _baseFont->getTypeFace();
    }

    /// returns font family id
    virtual css_font_family_t getFontFamily() const {
        return _baseFont->getFontFamily();
    }

    /// draws text string
    virtual int DrawTextString(LVDrawBuf* buf, int x, int y,
                               const lChar32* text, int len,
                               lChar32 def_char, lUInt32* palette = NULL,
                               bool addHyphen = false, TextLangCfg* lang_cfg = NULL,
                               lUInt32 flags = 0, int letter_spacing = 0,
                               int width = -1, int text_decoration_back_gap = 0,
                               int target_w = -1, int target_h = -1,
                               lUInt32 fallbackPassMask = 0);

    /// get bitmap mode (true=monochrome bitmap, false=antialiased)
    virtual bool getBitmapMode() {
        return _baseFont->getBitmapMode();
    }

    /// set bitmap mode (true=monochrome bitmap, false=antialiased)
    virtual void setBitmapMode(bool m) {
        _baseFont->setBitmapMode(m);
    }

    /// sets current hinting mode
    virtual void setHintingMode(hinting_mode_t mode) {
        _baseFont->setHintingMode(mode);
    }

    /// returns current hinting mode
    virtual hinting_mode_t getHintingMode() const {
        return _baseFont->getHintingMode();
    }

    /// get kerning mode: true==ON, false=OFF
    virtual bool getKerning() const {
        return _baseFont->getKerning();
    }

    /// get kerning mode: true==ON, false=OFF
    virtual void setKerning(bool b) {
        _baseFont->setKerning(b);
    }

    /// get shaping mode
    virtual shaping_mode_t getShapingMode() const {
        return _baseFont->getShapingMode();
    }

    /// get shaping mode
    virtual void setShapingMode(shaping_mode_t mode) {
        _baseFont->setShapingMode(mode);
    }

    /// clear cache
    virtual void clearCache() {
        _baseFont->clearCache();
    }

    /// returns true if font is empty
    virtual bool IsNull() const {
        return _baseFont->IsNull();
    }

    virtual bool operator!() const {
        return !(*_baseFont);
    }

    virtual void Clear() {
        _baseFont->Clear();
    }

    virtual ~LVFontBoldTransform() {
    }
};

#endif // __LV_FONTBOLDTRANSFORM_H_INCLUDED__
