/** \file lvfnt.h
    \brief Grayscale Bitmap Font engine

    CoolReader Engine

    (c) Vadim Lopatin, 2000-2006

    This source code is distributed under the terms of
    GNU General Public License.

    See LICENSE file for details.

   \section Unicode greyscale bitmap font file structure

   (pointers are byte offsets from file beginning)

   - <font file>::
      - <file header>      -- lvfont_header_t
      - <decode table>     -- huffman decode table
      - <glyph chunk 1>    -- lvfont_glyph_t * [64]
      - ...
      - <glyph chunk N>    -- lvfont_glyph_t * [64]
   - <file header>::
      - <signature>        -- 4 bytes
      - <version>          -- 4 bytes
      - <fontName>         -- 64 bytes
      - <copyright>        -- 64 bytes
      - <fileSize>         -- 4 bytes
      - <fontAttributes>   -- 8 bytes
      - <font ranges>      -- lvfont_glyph_t * * [1024], 0 if no chunk
   - <glyph chunk>::
      - <glyph table>      -- lvfont_glyph_t * [64], 0 if no glyph
      - <glyph 1>          -- lvfont_glyph_t [arbitrary size]
      - ...
      - <glyph M>          -- lvfont_glyph_t [arbitrary size]

*/

#ifndef __LVFNT_H_INCLUDED__
#define __LVFNT_H_INCLUDED__

#include "lvtypes.h"

/// maximum font name length
#define FONT_NAME_LENGTH       64
/// maximum copyright notice length
#define FONT_COPYRIGHT_LENGTH  64

#ifdef __cplusplus

#include "hyphman.h"

extern "C" {
#endif

/**
    \brief Bitmap font header structure

    This structure starts from the beginning of file.

*/
#pragma pack(push,1)
typedef struct 
tag_lvfont_header 
{
    char magic[4];   ///< {'L', 'F', 'N', 'T'}
    char version[4]; ///< {'1', '.', '0', '0'  } */
    char fontName[FONT_NAME_LENGTH];  ///< font typeface name
    char fontCopyright[FONT_COPYRIGHT_LENGTH]; ///< copyright notice
    lUInt32 fileSize;         ///< full font file size, bytes
    lUInt8  fontHeight;       ///< font height, pixels
    lUInt8  fontAvgWidth;     ///< avg char width, pixels
    lUInt8  fontMaxWidth;     ///< max char width
    lUInt8  fontBaseline;     ///< font baseline offset, from top, pixels
    lUInt8  fontBitsPerPixel; ///< usually 1, 2 or 4
    lUInt8  flgBold;          ///< 1 for bold, 0 for normal
    lUInt8  flgItalic;        ///< 1 for italic, 0 for normal
    lUInt8  fontFamily;       ///< font family
    lUInt16 minCode;          ///< min font character code
    lUInt16 maxCode;          ///< max font character code
    lUInt32 decodeTableOffset;///< huffman decode table offset
    lUInt32 rangesOffset[1024]; /**< \brief byte offset from beginning of file to 64 chars unicode ranges

                                   - 0 if no chars in range 
                                   - rangesOffset[0] - 0..63
                                   - rangesOffset[1] - 64..127
                                   - rangesOffset[2] - 128..191
                                   - ...
                                   - rangesOffset[maxCode/64] -- ..maxCode
                                   The real length of whis array is
                                   (maxCode/64+1), the rest is overlapped
                                   with first range data.
                                */
    /* decode table follows */
} lvfont_header_t;
#pragma pack(pop)

/**
    \brief Glyph range offset table.

    Contains pointers to individual glyphs for 64-character glyph range.
*/
#pragma pack(push,1)
typedef struct 
tag_lvfont_range 
{
    lUInt16 glyphsOffset[64]; /** \brief offset table for 64 glyphs in range
                                   - 0 if no glyph for char 
                                   - byte offset from beginning of range to glyph if exists

                                   followed by lvfont_glyph_t for each non-zero offset
                              */
} lvfont_range_t;
#pragma pack(pop)

/**
    \brief Glyph data structure.

    Describes properties of single glyph followed by compressed glyph image.

*/
#pragma pack(push,1)
typedef struct 
tag_lvfont_glyph 
{
    lUInt32  glyphSize;   ///< 4: bytes in glyph array
    lUInt16  blackBoxX;   ///< 0: width of glyph
    lUInt16  blackBoxY;   ///< 1: height of glyph black box
    lInt16   originX;     ///< 2: X origin for glyph
    lInt16   originY;     ///< 3: Y origin for glyph
    lUInt16  width;       ///< 6: full width of glyph
    lUInt8   glyph[2];    ///< 7: glyph data, arbitrary size
} lvfont_glyph_t;
#pragma pack(pop)

/** \brief RLE/Huffman table entry used for glyph image encoding.

    Describes huffman code of single symbol.

*/
#pragma pack(push,1)
typedef struct {
    lUInt8  value;    ///< color value
    lUInt8  count;    ///< number of times value is repeated
    lUInt8  codelen;  ///< number of bits in huffman code
    lUInt8  code;     ///< huffman code (left aligned)
} hrle_decode_table_t;
#pragma pack(pop)

/**
    \brief RLE/Huffman table used for glyph image encoding.

    Contains table used to encode glyph images.

*/
#pragma pack(push,1)
typedef struct {
    lUInt8  itemcount; ///< number of items in table
    lUInt8  bitcount;  ///< bit count per color value
    lUInt8  rightmask; ///< left aligned mask
    lUInt8  leftmask;  ///< right aligned mask
    hrle_decode_table_t table[1]; ///< table items [itemcount]
} hrle_decode_info_t;
#pragma pack(pop)

/// Font handle typedef to refer the font
typedef void * lvfont_handle;

/**********************************************************************
    font object API
**********************************************************************/

/** 
   \brief loads font from file, allocates memory 
   \return 1 if successful, 0 for error
*/
int lvfontOpen( const char * fname, lvfont_handle * hfont );

/// frees memory allocated for font 
void lvfontClose( lvfont_handle pfont );

/** \brief retrieves font header pointer by handle 
    \param hfont is font handle
    \return pointer to font header structure
*/
const lvfont_header_t * lvfontGetHeader( const lvfont_handle hfont );

/** \brief retrieves pointer to huffman decode table by font handle
    \param hfont is font handle
    \return pointer to huffman decode table
*/
const hrle_decode_info_t * lvfontGetDecodeTable( const lvfont_handle hfont );

/** \brief retrieves pointer to glyph structure for specified char by font handle
    \param hfont is font handle
    \param code is unicode character
    \return pointer to glyph structure
*/
const lvfont_glyph_t * lvfontGetGlyph( const lvfont_handle hfont, lUInt16 code );

/** \brief measures test line width

    \param pfont is font handle
    \param text is pointer to text string
    \param len is number of characters in text to measure
    \param max_width is a width limit -- measuring stops when total width exceeds this value
    \param widths returns running total widths of string [0..i] including text[i]
    \return number of items written to widths[]
*/
lUInt16 lvfontMeasureText( const lvfont_handle pfont, 
                    const lChar32 * text, int len, 
                    lUInt16 * widths,
                    lUInt8 * flags,
                    int max_width,
                    lChar32 def_char
                 );

// These lower than 0x0100 (that fit in a lUint8) may be set by lvfntman's measureText()
// (to possibly get some informative flags back from harfbuzz) and hyphman's hyphenate().
// (These should be changed or dropped with care, as they may be used by some other parts of CoolReader)
#define LCHAR_IS_SPACE               0x0001 ///< flag: this char is one of the unicode space chars.
                                            //         It is set only on the normal space and the normal non-breakable
                                            //         space (spaces that can have their widths expanded or shrunk).
                                            //         It is not set on the unicode fixed width spaces.
#define LCHAR_ALLOW_WRAP_AFTER       0x0002 ///< flag: line break after this char is allowed.
                                            //         It is set on all spaces, except non-breakable ones.
                                            //         It is set on soft-hyphen.
                                            //         It is not set on CJK chars.
#define LCHAR_DEPRECATED_WRAP_AFTER  0x0004 ///< flag: line break after this char is possible but deprecated
                                            //         When not using libunibreak: it is set on '-' and other unicode hyphens.
                                            //         When using libunibreak: set on all text inside "white-space: nowrap"
#define LCHAR_ALLOW_HYPH_WRAP_AFTER  0x0008 ///< flag: line break after this char is allowed with addition of hyphen
                                            //         It is set by Hyphman when finding hyphenation points in a word.
#define LCHAR_MANDATORY_NEWLINE      0x0010 ///< flag: this char must start with new line
#define LCHAR_IS_CLUSTER_TAIL        0x0020 ///< flag: this char is a tail of a cluster (eg. ligature,
                                            //         whose glyph is carried by first char)
                                            //         It is set by harfbuzz when used.

// (This one is actually not set by lvfntman)
#define LCHAR_LOCKED_SPACING         0x0040 ///< flag: forbid any letter spacing tweak on this char
                                            //         (for cursive scripts like arabic, and special cases)
#define LCHAR__AVAILABLE_BIT_08__    0x0080

/// The next ones, not fitting in a lUInt8, should only be set and used by lvtextfm
#define LCHAR_IS_OBJECT              0x0100 ///< flag: this char is object (image, float)
#define LCHAR_IS_COLLAPSED_SPACE     0x0200 ///< flag: this char is a space that should not be rendered
#define LCHAR_IS_TO_IGNORE           0x0400 ///< flag: this char is to be ignored/skipped in text measurement and drawing
#define LCHAR_IS_RTL                 0x0800 ///< flag: this char is part of a RTL segment

#define LCHAR__AVAILABLE_BIT_13__    0x1000
#define LCHAR__AVAILABLE_BIT_14__    0x2000
#define LCHAR__AVAILABLE_BIT_15__    0x4000
#define LCHAR__AVAILABLE_BIT_16__    0x8000

// Some idea, if needed:
// #define LCHAR_IS_CJK_NOT_PUNCT       0x1000 ///< flag: this char is part a CJK char but not a punctuation
// #define LCHAR_IS_CJK_LEFT_PUNCT      0x2000 ///< flag: this char is part a CJK left punctuation
// #define LCHAR_IS_CJK_RIGHT_PUNCT     0x4000 ///< flag: this char is part a CJK right punctuation
// #define LCHAR_IS_CJK_PUNCT           0x6000 ///< flag: (for checking) this char is a CJK punctuation (neutral if set)
// #define LCHAR_IS_CJK                 0x7000 ///< flag: (for checking) this char is a CJK char

// LCHAR_IS_EOL was not used by any code, and has been replaced by LCHAR_IS_CLUSTER_TAIL
// #define LCHAR_IS_EOL              0x0010 ///< flag: this char is CR or LF


/** \brief returns true if character is unicode space 
    \param code is character
    \return 1 if character is space, 0 otherwise 
*/
inline int lvfontIsUnicodeSpace( lChar32 code ) { return code==0x0020; }

/** \brief returns unpacked glyph image 
    \param packed is RLE/Huffman encoded glyph data
    \param table is RLE/Huffman table
    \param unpacked is buffer to place unpacked image (1 byte per pixel)
    \param unp_size is size of \a unpacked
*/
void lvfontUnpackGlyph( const lUInt8 * packed, 
                       const hrle_decode_info_t * table, 
                       lUInt8 * unpacked, 
                       int unp_size );

#ifdef __cplusplus
}



#endif

#endif
