OKF File Format Specification v1.0


Structure of an .OKF File
-------------------------

Byte         Block            Size           Description/Comments

  0          Header            76            See next chapter.
 76          CharSet           NbChars       Code of each character. It's up to the designer of the font
                                             to decide the table to use ASCII, ANSI, whatever... but it
                                             has to be known by the user of the font. The prefered table
                                             is ANSI.
  ?          CharWidths        NbChars       Width of each character in the bitmap.
  ?        * CharLeftIndents   0 or NbChars  Left indents of each character in CharSet. Present only if
                                             Flags:5 is ON.
  ?        * CharRightIndents  0 or NbChars  Right indents of each character in CharSet. Present only if
                                             Flags:5 is ON.
  ?          ColorPalette      0 or 256*2    GP32 palette. Present only if Flags:0 is OFF.
BitmapOffset FontBitmapData    ?             Data of the bitmap font. Size depends on bitmap depth, font
                                             size, charset, encoding, etc...
MaskOffset   AlphaMaskData     ?             Data of the alpha mask bitmap. Size depends on font size,
                                             charset, encoding, etc...



.OKF File Header Format
-----------------------

Byte         Item              Size          Description/Comments

  0          Signature         4             Signature of the file. String[4] = "OKF\0".
  4          Version           1             Version, actually 1.
  5          Flags             2             Bit  0: Color depth.        OFF: 8 bits       ON: 16 bits
                                             Bit  1: Bitmap encoding.    OFF: Not encoded  ON: RLE encoded
                                             Bit  2: Alpha mask.         OFF: Not present  ON: Present
                                             Bit  3: Mask encoding.      OFF: Not encoded  ON: RLE encoded
                                             Bit  4: Mask type           OFF: Multipurpose ON: Shadow
                                             Bit  5: Left/right indents. OFF: Not present  ON: Present
                                             Bit  6: Postprocessed font.
                                             Bit  7: Font pitch.         OFF: Monospaced   ON: Proportional
                                             Bit  8: Font with serif  (like Times New Roman).
                                             Bit  9: Script font.
                                             Bit 10: Bold.
                                             Bit 11: Italic.
                                             Bit 12: Underline.
                                             Bit 13: Strikethrough.
                                             Bits 14-15: Reserved for future usage (always OFF).
  7          Size              1             Size of the font (Windows like).
  8          Name              32            Font name (Windows like when possible).
 40          FileSize          4             Total file size.
 44          BitmapOffset      4             Address of the first byte of the bitmap data.
 48          MaskOffset        4             Address of the first byte of the alpha mask data.
 52          TransColor        2             Color of the font bitmap to use as transparent color.
                                             If Flags:0 is OFF, TransColor = index in color palette.
                                             If Flags:0 is ON,  TransColor = GP32 16 bits color.
 54          ShadowColor       2             Default color of the font shadow. Used only for shadow masks.
                                             If Flags:0 is OFF, ShadowColor = index in color palette.
                                             If Flags:0 is ON,  ShadowColor = GP32 16 bits color.
 56          Reserved          2             Reserved for future usage (filled with 0).
 58          BitmapWidth       2             Real width of the font bitmap.
 60          BitmapHeight      1             Real heigth of the font bitmap.
 61          DefaultWidth      1             Default width of a character.
 62          DefaultHeight     1             Default height of a character. Height of the font.
 63          MaxWidth          1             Width of the widest character.
 64          MaxHeight         1             Height of the tallest character.
 65        * MaskWidthInc      1             Increment to add to char widths to get char mask widths.
                                             Used only for shadow masks.
 66        * MaskHeightInc     1             Increment to add to char heights to get char mask heights.
                                             Used only for shadow masks.
 67        * ShadowOX          1             X coordinate of the shadow mask bitmap in reference to the
                                             char bitmap origin, when the shadow is located just
                                             underneath the character. Used only for shadow masks.
 68        * ShadowOY          1             Y coordinate of the shadow mask bitmap in reference to the
                                             char bitmap origin, when the shadow is located just
                                             underneath the character. Used only for shadow masks.
 69        * ShadowPosX        1             Default X position of the shadow mask bitmap.
 70        * ShadowPosY        1             Default Y position of the shadow mask bitmap.
 71        * LineSeparation    1             Pixels to add to the height of the font when moving cursor
                                             position to next line.
 72        * CharSeparation    1             Pixels to add to the width of the character when moving 
                                             cursor position to next character.
 73          NbChars           1             Number of chars in the font (0-254)
 74          Reserved          2             Reserved for future usage (filled with 0).


NOTES:

All sizes are measured in BYTES.

All variables of SIZE 4 are unsigned long.

All variables of SIZE 2 are unsigned short.

All variables of SIZE 1 without a '*' are unsigned char.
All variables of SIZE 1 with a '*' are signed char.



Decoding .OKF Files
-------------------

If Flags:1 is OFF, the bitmap data is not encoded and contains the bitmap in GP32 RAW format.
If Flags:1 is ON, the bitmap data is run length encoded. Two encoding methods are used depending on the
depth of the bitmap (8 bits or 16 bits fonts).
If Flags:3 is OFF, the alpha mask data is not encoded and contains the mask in GP32 RAW format.
If Flags:3 is ON, the alpha mask data is run length encoded.

For 8 bits bitmaps, the encoding method is the same as for PCX files.
For 16 bits bitmaps, the encoding method is new and take advantage of the color scheme in the GP32, and,
depending on the bitmap, should be a lot more efficient than 24 bits PCX compression.
For alpha masks, the encoding method is the same as for 16 bits bitmaps.


* Decoding a 8 bits bitmap:

    FOR each byte, X, read from the file
        IF the top 2 bits of X are  1's then
            count = 6 lowest bits of X
            data = next byte following X
        ELSE
            count = 1
            data = X

Calculate how many bytes are required to hold one complete uncompressed scan line:

TotalBytes = BitmapWidth   // for font bitmap

TotalBytes shows how much storage must be available to decode each scan line.
You can now begin decoding the first scan line:
Read the first byte of data from the file.
If the top 2 bits are set, the remaining 6 bits in the byte show how many times to duplicate the next
byte in the file.
If the top 2 bits are not set, the first byte is the data itself, with a count of 1.
Continue decoding the rest of the line. Keep a running subtotal of how many bytes are moved and duplicated
into the output buffer.
When the subtotal equals TotalBytes, the scan line is complete. There always will be a decoding break at
the end of each scan line.
Continue decoding the remainder of the scan lines (BitmapHeight) (do not just read to end-of-file).


* Decoding a 16 bits font or the alpha mask:

    FOR each byte, X, read from the file
        data = 5 lowest bits of X
        IF the top 3 bits of X are 0's then
            count = next byte following X
        ELSE
            count = 3 top bits of X

Calculate how many bytes are required to hold one complete uncompressed scan line:

TotalBytes = BitmapWidth * NPlanes                             // for font bitmap
TotalBytes = (BitmapWidth + MaskWidthInc * NbChars) * NPlanes  // for mask bitmap

For 16 bits fonts, NPlanes = 3 and comes in the order Red, Green, Blue for each scan line.
For alpha masks, NPlanes = 1.

TotalBytes shows how much storage must be available to decode each scan line.
You can now begin decoding the first scan line:
Read the first byte of data from the file.
The lowest 5 bits is the data itself.
If the remaining top 3 bits are not set (all 0's), the next byte in the file show how many times to
duplicate the data.
If at least one of the remaining top 3 bits is set, these 3 top bits show how many times to duplicate
the data.
Continue decoding the rest of the line. Keep a running subtotal of how many bytes are moved and duplicated
into the output buffer.
When the subtotal equals TotalBytes, the scan line is complete. There always will be a decoding break at
the end of each plane and at the end of each scan line.
Continue decoding the remainder of the scan lines (BitmapHeight or MaskBitmapHeight) (do not just read
to end-of-file).



Important notes
---------------

Bitmaps in .OKF files are not GP32 rotated and are not bound to GP32 sizes.
If your purpose is to use the fonts with GP32 SDK, you'll have to resize the bitmap to GP32 boundaries
(8 bytes), and rotate it yourself even if the bitmap is in RAW format.

If the alpha mask is present, it is represented by an 8 bit bitmap. Alpha masks can have up to 32 levels
of opacities (5 bits).

Depending on Flags:4, the mask has to be managed in two different ways:

- If Flags:4 is OFF, the mask is a multipurpose alpha mask and the bitmap has exactly the same size as the
  font bitmap.
  To get the color of a pixel in the screen, you will have to combine the existing color in the screen,
  the color in the font bitmap and the opacity value in the mask bitmap.

- If Flags:4 is ON, the mask is a shadow alpha mask and to save space, the font bitmap and the alpha mask
  bitmap can be of different size. Usually the font bitmap will be smaller.
  To get the color of a pixel in the screen, first you will have to check if the pixel in the font is of
  TransColor color or not. If it is, it means that the pixel is outside the character and the shadow has
  to be rendered. You will have to combine the existing color in the screen, the ShadowColor color and
  the opacity value in the mask bitmap.
  If the pixel of the font is not of TransColor color, it means that the pixel is part of the character.
  You will just have to peek the pixel color in the font bitmap.

  To get the exact size of the shadow mask bitmap:

  MaskBitmapWidth  = BitmapWidth + MaskWidthInc * NbChars
  MaskBitmapHeight = BitmapHeight + MaskHeightInc

  To get the exact size of a character in the shadow mask:

  MaskCharWidth  = CharWidth + MaskWidthInc
  MaskCharHeight = CharHeight + MaskHeightInc

  To get the exact position of a character shadow mask in reference to the character itself:

  CharMaskX = CharX + ShadowOX + ShadowXPos
  CharMaskY = CharY + ShadowOY + ShadowYPos


--------------------------------------------------------------------------------------------------------

Copyright (c) 2004, Guillem Reinoso
aka Oankali
oankali@andorra.ad

Please, read the license in OKF_LIC.TXT for conditions on using OKF Fonts.
