add msdf-atlas-gen libs linux64 & emscripten
This commit is contained in:
parent
0bb0e87a33
commit
6fb3f95348
143 changed files with 13729 additions and 0 deletions
|
@ -0,0 +1,10 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "enums.h"
|
||||
#include "structures.h"
|
||||
#include "serialization.h"
|
||||
|
||||
// ARTERY ENGINE ATLAS FONT FORMAT LIBRARY v1.0.1
|
||||
// Author: Viktor Chlumsky (c) 2020 - 2022
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
uint32 crc32Init();
|
||||
uint32 crc32Update(uint32 crc, byte x);
|
||||
|
||||
}
|
||||
|
||||
#include "crc32.hpp"
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
#include "crc32.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
inline uint32 crc32Init() {
|
||||
return ~0u;
|
||||
}
|
||||
|
||||
inline uint32 crc32Update(uint32 crc, byte x) {
|
||||
static const uint32 crc32Table[256] = {
|
||||
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u, 0x706af48fu, 0xe963a535u, 0x9e6495a3u,
|
||||
0x0edb8832u, 0x79dcb8a4u, 0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u, 0x90bf1d91u,
|
||||
0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu, 0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u,
|
||||
0x136c9856u, 0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u, 0xfa0f3d63u, 0x8d080df5u,
|
||||
0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u, 0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
|
||||
0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u, 0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u,
|
||||
0x26d930acu, 0x51de003au, 0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u, 0xb8bda50fu,
|
||||
0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u, 0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du,
|
||||
0x76dc4190u, 0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu, 0x9fbfe4a5u, 0xe8b8d433u,
|
||||
0x7807c9a2u, 0x0f00f934u, 0x9609a88eu, 0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
|
||||
0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu, 0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u,
|
||||
0x65b0d9c6u, 0x12b7e950u, 0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u, 0xfbd44c65u,
|
||||
0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u, 0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu,
|
||||
0x4369e96au, 0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u, 0xaa0a4c5fu, 0xdd0d7cc9u,
|
||||
0x5005713cu, 0x270241aau, 0xbe0b1010u, 0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
|
||||
0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u, 0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu,
|
||||
0xedb88320u, 0x9abfb3b6u, 0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u, 0x73dc1683u,
|
||||
0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u, 0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u,
|
||||
0xf00f9344u, 0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu, 0x196c3671u, 0x6e6b06e7u,
|
||||
0xfed41b76u, 0x89d32be0u, 0x10da7a5au, 0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
|
||||
0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u, 0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu,
|
||||
0xd80d2bdau, 0xaf0a1b4cu, 0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu, 0x4669be79u,
|
||||
0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u, 0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu,
|
||||
0xc5ba3bbeu, 0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u, 0x2cd99e8bu, 0x5bdeae1du,
|
||||
0x9b64c2b0u, 0xec63f226u, 0x756aa39cu, 0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
|
||||
0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu, 0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u,
|
||||
0x86d3d2d4u, 0xf1d4e242u, 0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u, 0x18b74777u,
|
||||
0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu, 0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u,
|
||||
0xa00ae278u, 0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u, 0x4969474du, 0x3e6e77dbu,
|
||||
0xaed16a4au, 0xd9d65adcu, 0x40df0b66u, 0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
|
||||
0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u, 0xcdd70693u, 0x54de5729u, 0x23d967bfu,
|
||||
0xb3667a2eu, 0xc4614ab8u, 0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu, 0x2d02ef8du,
|
||||
};
|
||||
return crc32Table[byte(x^crc)]^crc>>8;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
enum FontFlags {
|
||||
FONT_BOLD = 0x01,
|
||||
FONT_LIGHT = 0x02,
|
||||
FONT_EXTRA_BOLD = 0x04,
|
||||
FONT_CONDENSED = 0x08,
|
||||
FONT_ITALIC = 0x10,
|
||||
FONT_SMALL_CAPS = 0x20,
|
||||
FONT_ICONOGRAPHIC = 0x0100,
|
||||
FONT_SANS_SERIF = 0x0200,
|
||||
FONT_SERIF = 0x0400,
|
||||
FONT_MONOSPACE = 0x1000,
|
||||
FONT_CURSIVE = 0x2000
|
||||
};
|
||||
|
||||
enum CodepointType {
|
||||
CP_UNSPECIFIED = 0,
|
||||
CP_UNICODE = 1,
|
||||
CP_INDEXED = 2,
|
||||
CP_ICONOGRAPHIC = 14
|
||||
};
|
||||
|
||||
enum MetadataFormat {
|
||||
METADATA_NONE = 0,
|
||||
METADATA_PLAINTEXT = 1,
|
||||
METADATA_JSON = 2
|
||||
};
|
||||
|
||||
enum ImageType {
|
||||
IMAGE_NONE = 0,
|
||||
IMAGE_SRGB_IMAGE = 1,
|
||||
IMAGE_LINEAR_MASK = 2,
|
||||
IMAGE_MASKED_SRGB_IMAGE = 3,
|
||||
IMAGE_SDF = 4,
|
||||
IMAGE_PSDF = 5,
|
||||
IMAGE_MSDF = 6,
|
||||
IMAGE_MTSDF = 7,
|
||||
IMAGE_MIXED_CONTENT = 255
|
||||
};
|
||||
|
||||
enum PixelFormat {
|
||||
PIXEL_UNKNOWN = 0,
|
||||
PIXEL_BOOLEAN1 = 1,
|
||||
PIXEL_UNSIGNED8 = 8,
|
||||
PIXEL_FLOAT32 = 32
|
||||
};
|
||||
|
||||
enum ImageEncoding {
|
||||
IMAGE_UNKNOWN_ENCODING = 0,
|
||||
IMAGE_RAW_BINARY = 1,
|
||||
IMAGE_BMP = 4,
|
||||
IMAGE_TIFF = 5,
|
||||
IMAGE_PNG = 8,
|
||||
IMAGE_TGA = 9
|
||||
};
|
||||
|
||||
enum ImageOrientation {
|
||||
ORIENTATION_TOP_DOWN = 1,
|
||||
ORIENTATION_BOTTOM_UP = -1
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "enums.h"
|
||||
#include "structures.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
typedef int ReadFunction(void *dst, int limit, void *userData);
|
||||
typedef int WriteFunction(const void *src, int length, void *userData);
|
||||
|
||||
template <ReadFunction READ, typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData);
|
||||
|
||||
template <WriteFunction WRITE, typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData);
|
||||
|
||||
}
|
||||
|
||||
#include "serialization.hpp"
|
|
@ -0,0 +1,394 @@
|
|||
|
||||
#include "serialization.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "crc32.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
namespace internal {
|
||||
|
||||
#define ARTERY_FONT_HEADER_TAG "ARTERY/FONT\0\0\0\0\0"
|
||||
#define ARTERY_FONT_HEADER_VERSION 1u
|
||||
#define ARTERY_FONT_HEADER_MAGIC_NO 0x4d276a5cu
|
||||
#define ARTERY_FONT_FOOTER_MAGIC_NO 0x55ccb363u
|
||||
|
||||
struct ArteryFontHeader {
|
||||
char tag[16];
|
||||
uint32 magicNo;
|
||||
uint32 version;
|
||||
uint32 flags;
|
||||
uint32 realType;
|
||||
uint32 reserved[4];
|
||||
|
||||
uint32 metadataFormat;
|
||||
uint32 metadataLength;
|
||||
uint32 variantCount;
|
||||
uint32 variantsLength;
|
||||
uint32 imageCount;
|
||||
uint32 imagesLength;
|
||||
uint32 appendixCount;
|
||||
uint32 appendicesLength;
|
||||
uint32 reserved2[8];
|
||||
};
|
||||
|
||||
struct ArteryFontFooter {
|
||||
uint32 salt;
|
||||
uint32 magicNo;
|
||||
uint32 reserved[4];
|
||||
uint32 totalLength;
|
||||
uint32 checksum;
|
||||
};
|
||||
|
||||
template <typename REAL>
|
||||
struct FontVariantHeader {
|
||||
uint32 flags;
|
||||
uint32 weight;
|
||||
uint32 codepointType;
|
||||
uint32 imageType;
|
||||
uint32 fallbackVariant;
|
||||
uint32 fallbackGlyph;
|
||||
uint32 reserved[6];
|
||||
REAL metrics[32];
|
||||
uint32 nameLength;
|
||||
uint32 metadataLength;
|
||||
uint32 glyphCount;
|
||||
uint32 kernPairCount;
|
||||
};
|
||||
|
||||
struct ImageHeader {
|
||||
uint32 flags;
|
||||
uint32 encoding;
|
||||
uint32 width, height;
|
||||
uint32 channels;
|
||||
uint32 pixelFormat;
|
||||
uint32 imageType;
|
||||
uint32 rowLength;
|
||||
sint32 orientation;
|
||||
uint32 childImages;
|
||||
uint32 textureFlags;
|
||||
uint32 reserved[3];
|
||||
uint32 metadataLength;
|
||||
uint32 dataLength;
|
||||
};
|
||||
|
||||
struct AppendixHeader {
|
||||
uint32 metadataLength;
|
||||
uint32 dataLength;
|
||||
};
|
||||
|
||||
template <typename REAL>
|
||||
uint32 realTypeCode();
|
||||
|
||||
template <>
|
||||
inline uint32 realTypeCode<float>() {
|
||||
return 0x14u;
|
||||
}
|
||||
template <>
|
||||
inline uint32 realTypeCode<double>() {
|
||||
return 0x18u;
|
||||
}
|
||||
|
||||
inline uint32 paddedLength(uint32 len) {
|
||||
if (len&0x03u)
|
||||
len += 0x04u-(len&0x03u);
|
||||
return len;
|
||||
}
|
||||
|
||||
template <class STRING>
|
||||
uint32 paddedStringLength(const STRING &str) {
|
||||
uint32 len = str.length();
|
||||
return paddedLength(len+(len > 0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifndef __BIG_ENDIAN__
|
||||
|
||||
template <ReadFunction READ, typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
|
||||
uint32 totalLength = 0;
|
||||
uint32 prevLength = 0;
|
||||
uint32 checksum = crc32Init();
|
||||
byte dump[4];
|
||||
#define ARTERY_FONT_DECODE_READ(target, len) { \
|
||||
if (READ((target), (len), userData) != int(len)) \
|
||||
return false; \
|
||||
totalLength += (len); \
|
||||
for (int i = 0; i < int(len); ++i) \
|
||||
checksum = crc32Update(checksum, reinterpret_cast<const byte *>(target)[i]); \
|
||||
}
|
||||
#define ARTERY_FONT_DECODE_REALIGN() { \
|
||||
if (totalLength&0x03u) { \
|
||||
uint32 len = 0x04u-(totalLength&0x03u); \
|
||||
ARTERY_FONT_DECODE_READ(dump, len); \
|
||||
} \
|
||||
}
|
||||
#define ARTERY_FONT_DECODE_READ_STRING(str, len) { \
|
||||
if ((len) > 0) { \
|
||||
LIST<char> characters((len)+1); \
|
||||
ARTERY_FONT_DECODE_READ((char *) characters, (len)+1); \
|
||||
((char *) characters)[len] = '\0'; \
|
||||
(str) = STRING((const char *) characters, int(len)); \
|
||||
ARTERY_FONT_DECODE_REALIGN(); \
|
||||
} else \
|
||||
(str) = STRING(); \
|
||||
}
|
||||
int variantCount = 0;
|
||||
int imageCount = 0;
|
||||
int appendixCount = 0;
|
||||
uint32 variantsLength = 0;
|
||||
uint32 imagesLength = 0;
|
||||
uint32 appendicesLength = 0;
|
||||
// Read header
|
||||
{
|
||||
internal::ArteryFontHeader header;
|
||||
ARTERY_FONT_DECODE_READ(&header, sizeof(header));
|
||||
if (memcmp(header.tag, ARTERY_FONT_HEADER_TAG, sizeof(header.tag)))
|
||||
return false;
|
||||
if (header.magicNo != ARTERY_FONT_HEADER_MAGIC_NO)
|
||||
return false;
|
||||
if (header.realType != internal::realTypeCode<REAL>())
|
||||
return false;
|
||||
font.metadataFormat = (MetadataFormat) header.metadataFormat;
|
||||
ARTERY_FONT_DECODE_READ_STRING(font.metadata, header.metadataLength);
|
||||
variantCount = header.variantCount;
|
||||
imageCount = header.imageCount;
|
||||
appendixCount = header.appendixCount;
|
||||
font.variants = LIST<FontVariant<REAL, LIST, STRING> >(header.variantCount);
|
||||
font.images = LIST<FontImage<BYTE_ARRAY, STRING> >(header.imageCount);
|
||||
font.appendices = LIST<FontAppendix<BYTE_ARRAY, STRING> >(header.appendixCount);
|
||||
variantsLength = header.variantsLength;
|
||||
imagesLength = header.imagesLength;
|
||||
appendicesLength = header.appendicesLength;
|
||||
}
|
||||
prevLength = totalLength;
|
||||
// Read variants
|
||||
for (int i = 0; i < variantCount; ++i) {
|
||||
FontVariant<REAL, LIST, STRING> &variant = font.variants[i];
|
||||
internal::FontVariantHeader<REAL> header;
|
||||
ARTERY_FONT_DECODE_READ(&header, sizeof(header));
|
||||
variant.flags = header.flags;
|
||||
variant.weight = header.weight;
|
||||
variant.codepointType = (CodepointType) header.codepointType;
|
||||
variant.imageType = (ImageType) header.imageType;
|
||||
variant.fallbackVariant = header.fallbackVariant;
|
||||
variant.fallbackGlyph = header.fallbackGlyph;
|
||||
memcpy(&variant.metrics, header.metrics, sizeof(header.metrics));
|
||||
ARTERY_FONT_DECODE_READ_STRING(variant.name, header.nameLength);
|
||||
ARTERY_FONT_DECODE_READ_STRING(variant.metadata, header.metadataLength);
|
||||
variant.glyphs = LIST<Glyph<REAL> >(header.glyphCount);
|
||||
variant.kernPairs = LIST<KernPair<REAL> >(header.kernPairCount);
|
||||
ARTERY_FONT_DECODE_READ((Glyph<REAL> *) variant.glyphs, header.glyphCount*sizeof(Glyph<REAL>));
|
||||
ARTERY_FONT_DECODE_READ((KernPair<REAL> *) variant.kernPairs, header.kernPairCount*sizeof(KernPair<REAL>));
|
||||
}
|
||||
if (totalLength-prevLength != variantsLength)
|
||||
return false;
|
||||
prevLength = totalLength;
|
||||
// Read images
|
||||
for (int i = 0; i < imageCount; ++i) {
|
||||
FontImage<BYTE_ARRAY, STRING> &image = font.images[i];
|
||||
internal::ImageHeader header;
|
||||
ARTERY_FONT_DECODE_READ(&header, sizeof(header));
|
||||
image.flags = header.flags;
|
||||
image.encoding = (ImageEncoding) header.encoding;
|
||||
image.width = header.width;
|
||||
image.height = header.height;
|
||||
image.channels = header.channels;
|
||||
image.pixelFormat = (PixelFormat) header.pixelFormat;
|
||||
image.imageType = (ImageType) header.imageType;
|
||||
image.rawBinaryFormat.rowLength = header.rowLength;
|
||||
image.rawBinaryFormat.orientation = (ImageOrientation) header.orientation;
|
||||
image.childImages = header.childImages;
|
||||
image.textureFlags = header.textureFlags;
|
||||
ARTERY_FONT_DECODE_READ_STRING(image.metadata, header.metadataLength);
|
||||
image.data = BYTE_ARRAY(header.dataLength);
|
||||
ARTERY_FONT_DECODE_READ((unsigned char *) image.data, header.dataLength);
|
||||
ARTERY_FONT_DECODE_REALIGN();
|
||||
}
|
||||
if (totalLength-prevLength != imagesLength)
|
||||
return false;
|
||||
prevLength = totalLength;
|
||||
// Read appendices
|
||||
for (int i = 0; i < appendixCount; ++i) {
|
||||
FontAppendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i];
|
||||
internal::AppendixHeader header;
|
||||
ARTERY_FONT_DECODE_READ(&header, sizeof(header));
|
||||
ARTERY_FONT_DECODE_READ_STRING(appendix.metadata, header.metadataLength);
|
||||
appendix.data = BYTE_ARRAY(header.dataLength);
|
||||
ARTERY_FONT_DECODE_READ((unsigned char *) appendix.data, header.dataLength);
|
||||
ARTERY_FONT_DECODE_REALIGN();
|
||||
}
|
||||
if (totalLength-prevLength != appendicesLength)
|
||||
return false;
|
||||
prevLength = totalLength;
|
||||
// Read footer
|
||||
{
|
||||
internal::ArteryFontFooter footer;
|
||||
ARTERY_FONT_DECODE_READ(&footer, sizeof(footer)-sizeof(footer.checksum));
|
||||
if (footer.magicNo != ARTERY_FONT_FOOTER_MAGIC_NO)
|
||||
return false;
|
||||
uint32 finalChecksum = checksum;
|
||||
ARTERY_FONT_DECODE_READ(&footer.checksum, sizeof(footer.checksum));
|
||||
if (footer.checksum != finalChecksum)
|
||||
return false;
|
||||
if (totalLength != footer.totalLength)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#undef ARTERY_FONT_DECODE_READ
|
||||
#undef ARTERY_FONT_DECODE_REALIGN
|
||||
#undef ARTERY_FONT_DECODE_READ_STRING
|
||||
}
|
||||
|
||||
template <WriteFunction WRITE, typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
|
||||
uint32 totalLength = 0;
|
||||
uint32 checksum = crc32Init();
|
||||
const byte padding[4] = { };
|
||||
#define ARTERY_FONT_ENCODE_WRITE(data, len) { \
|
||||
if (WRITE((data), (len), userData) != int(len)) \
|
||||
return false; \
|
||||
totalLength += (len); \
|
||||
for (int i = 0; i < int(len); ++i) \
|
||||
checksum = crc32Update(checksum, reinterpret_cast<const byte *>(data)[i]); \
|
||||
}
|
||||
#define ARTERY_FONT_ENCODE_REALIGN() { \
|
||||
if (totalLength&0x03u) { \
|
||||
uint32 len = 0x04u-(totalLength&0x03u); \
|
||||
ARTERY_FONT_ENCODE_WRITE(padding, len); \
|
||||
} \
|
||||
}
|
||||
#define ARTERY_FONT_ENCODE_WRITE_STRING(str) { \
|
||||
uint32 len = (str).length(); \
|
||||
if ((len) > 0) { \
|
||||
ARTERY_FONT_ENCODE_WRITE((const char *) (str), (len)); \
|
||||
ARTERY_FONT_ENCODE_WRITE(padding, 1) \
|
||||
ARTERY_FONT_ENCODE_REALIGN(); \
|
||||
} \
|
||||
}
|
||||
int variantCount = 0;
|
||||
int imageCount = 0;
|
||||
int appendixCount = 0;
|
||||
// Write header
|
||||
{
|
||||
internal::ArteryFontHeader header;
|
||||
memcpy(header.tag, ARTERY_FONT_HEADER_TAG, sizeof(header.tag));
|
||||
header.magicNo = ARTERY_FONT_HEADER_MAGIC_NO;
|
||||
header.version = ARTERY_FONT_HEADER_VERSION;
|
||||
header.flags = 0;
|
||||
header.realType = internal::realTypeCode<REAL>();
|
||||
memset(header.reserved, 0, sizeof(header.reserved));
|
||||
header.metadataFormat = (uint32) font.metadataFormat;
|
||||
header.metadataLength = font.metadata.length();
|
||||
header.variantCount = variantCount = font.variants.length();
|
||||
header.variantsLength = 0;
|
||||
header.imageCount = imageCount = font.images.length();
|
||||
header.imagesLength = 0;
|
||||
header.appendixCount = appendixCount = font.appendices.length();
|
||||
header.appendicesLength = 0;
|
||||
memset(header.reserved2, 0, sizeof(header.reserved2));
|
||||
for (int i = 0; i < variantCount; ++i) {
|
||||
const FontVariant<REAL, LIST, STRING> &variant = font.variants[i];
|
||||
header.variantsLength += sizeof(internal::FontVariantHeader<REAL>);
|
||||
header.variantsLength += internal::paddedStringLength(variant.name);
|
||||
header.variantsLength += internal::paddedStringLength(variant.metadata);
|
||||
header.variantsLength += variant.glyphs.length()*sizeof(Glyph<REAL>);
|
||||
header.variantsLength += variant.kernPairs.length()*sizeof(KernPair<REAL>);
|
||||
}
|
||||
for (int i = 0; i < imageCount; ++i) {
|
||||
const FontImage<BYTE_ARRAY, STRING> &image = font.images[i];
|
||||
header.imagesLength += sizeof(internal::ImageHeader);
|
||||
header.imagesLength += internal::paddedStringLength(image.metadata);
|
||||
header.imagesLength += internal::paddedLength(image.data.length());
|
||||
}
|
||||
for (int i = 0; i < appendixCount; ++i) {
|
||||
const FontAppendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i];
|
||||
header.appendicesLength += sizeof(internal::AppendixHeader);
|
||||
header.appendicesLength += internal::paddedStringLength(appendix.metadata);
|
||||
header.appendicesLength += internal::paddedLength(appendix.data.length());
|
||||
}
|
||||
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
|
||||
ARTERY_FONT_ENCODE_WRITE_STRING(font.metadata);
|
||||
}
|
||||
// Write variants
|
||||
for (int i = 0; i < variantCount; ++i) {
|
||||
const FontVariant<REAL, LIST, STRING> &variant = font.variants[i];
|
||||
internal::FontVariantHeader<REAL> header;
|
||||
header.flags = variant.flags;
|
||||
header.weight = variant.weight;
|
||||
header.codepointType = (uint32) variant.codepointType;
|
||||
header.imageType = (uint32) variant.imageType;
|
||||
header.fallbackVariant = variant.fallbackVariant;
|
||||
header.fallbackGlyph = variant.fallbackGlyph;
|
||||
memset(header.reserved, 0, sizeof(header.reserved));
|
||||
memcpy(header.metrics, &variant.metrics, sizeof(header.metrics));
|
||||
header.nameLength = variant.name.length();
|
||||
header.metadataLength = variant.metadata.length();
|
||||
header.glyphCount = variant.glyphs.length();
|
||||
header.kernPairCount = variant.kernPairs.length();
|
||||
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
|
||||
ARTERY_FONT_ENCODE_WRITE_STRING(variant.name);
|
||||
ARTERY_FONT_ENCODE_WRITE_STRING(variant.metadata);
|
||||
ARTERY_FONT_ENCODE_WRITE((const Glyph<REAL> *) variant.glyphs, header.glyphCount*sizeof(Glyph<REAL>));
|
||||
ARTERY_FONT_ENCODE_WRITE((const KernPair<REAL> *) variant.kernPairs, header.kernPairCount*sizeof(KernPair<REAL>));
|
||||
}
|
||||
// Write images
|
||||
for (int i = 0; i < imageCount; ++i) {
|
||||
const FontImage<BYTE_ARRAY, STRING> &image = font.images[i];
|
||||
internal::ImageHeader header;
|
||||
header.flags = image.flags;
|
||||
header.encoding = (uint32) image.encoding;
|
||||
header.width = image.width;
|
||||
header.height = image.height;
|
||||
header.channels = image.channels;
|
||||
header.pixelFormat = (uint32) image.pixelFormat;
|
||||
header.imageType = (uint32) image.imageType;
|
||||
header.rowLength = image.rawBinaryFormat.rowLength;
|
||||
header.orientation = (sint32) image.rawBinaryFormat.orientation;
|
||||
header.childImages = image.childImages;
|
||||
header.textureFlags = image.textureFlags;
|
||||
memset(header.reserved, 0, sizeof(header.reserved));
|
||||
header.metadataLength = image.metadata.length();
|
||||
header.dataLength = image.data.length();
|
||||
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
|
||||
ARTERY_FONT_ENCODE_WRITE_STRING(image.metadata);
|
||||
ARTERY_FONT_ENCODE_WRITE((const unsigned char *) image.data, header.dataLength);
|
||||
ARTERY_FONT_ENCODE_REALIGN();
|
||||
}
|
||||
// Write appendices
|
||||
for (int i = 0; i < appendixCount; ++i) {
|
||||
const FontAppendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i];
|
||||
internal::AppendixHeader header;
|
||||
header.metadataLength = appendix.metadata.length();
|
||||
header.dataLength = appendix.data.length();
|
||||
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
|
||||
ARTERY_FONT_ENCODE_WRITE_STRING(appendix.metadata);
|
||||
ARTERY_FONT_ENCODE_WRITE((const unsigned char *) appendix.data, header.dataLength);
|
||||
ARTERY_FONT_ENCODE_REALIGN();
|
||||
}
|
||||
// Write footer
|
||||
{
|
||||
internal::ArteryFontFooter footer;
|
||||
footer.salt = 0;
|
||||
footer.magicNo = ARTERY_FONT_FOOTER_MAGIC_NO;
|
||||
memset(footer.reserved, 0, sizeof(footer.reserved));
|
||||
footer.totalLength = totalLength+sizeof(footer);
|
||||
ARTERY_FONT_ENCODE_WRITE(&footer, sizeof(footer)-sizeof(footer.checksum));
|
||||
footer.checksum = checksum;
|
||||
ARTERY_FONT_ENCODE_WRITE(&footer.checksum, sizeof(footer.checksum));
|
||||
}
|
||||
return true;
|
||||
#undef ARTERY_FONT_ENCODE_WRITE
|
||||
#undef ARTERY_FONT_ENCODE_REALIGN
|
||||
#undef ARTERY_FONT_ENCODE_WRITE_STRING
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#undef ARTERY_FONT_HEADER_TAG
|
||||
#undef ARTERY_FONT_HEADER_VERSION
|
||||
#undef ARTERY_FONT_HEADER_MAGIC_NO
|
||||
#undef ARTERY_FONT_FOOTER_MAGIC_NO
|
||||
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "artery-font.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
template <typename T>
|
||||
class StdList : private std::vector<T> {
|
||||
|
||||
public:
|
||||
inline StdList() { }
|
||||
inline explicit StdList(int length) : std::vector<T>((size_t) length) { }
|
||||
inline int length() const { return (int) std::vector<T>::size(); }
|
||||
inline explicit operator T *() { return std::vector<T>::data(); }
|
||||
inline explicit operator const T *() const { return std::vector<T>::data(); }
|
||||
inline T &operator[](int index) { return std::vector<T>::operator[](index); }
|
||||
inline const T &operator[](int index) const { return std::vector<T>::operator[](index); }
|
||||
|
||||
};
|
||||
|
||||
class StdString : private std::string {
|
||||
|
||||
public:
|
||||
inline StdString() { }
|
||||
inline StdString(const char *characters, int length) : std::string(characters, (size_t) length) { }
|
||||
inline int length() const { return (int) std::string::size(); }
|
||||
inline explicit operator const char *() const { return std::string::c_str(); }
|
||||
|
||||
};
|
||||
|
||||
typedef StdList<unsigned char> StdByteArray;
|
||||
|
||||
template <typename REAL>
|
||||
using StdArteryFont = ArteryFont<REAL, StdList, StdByteArray, StdString>;
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include "serialization.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool read(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, FILE *file);
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool write(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, FILE *file);
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool readFile(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, const char *filename);
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool writeFile(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, const char *filename);
|
||||
|
||||
}
|
||||
|
||||
#include "stdio-serialization.hpp"
|
|
@ -0,0 +1,48 @@
|
|||
|
||||
#include "stdio-serialization.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
namespace internal {
|
||||
|
||||
inline int fileRead(void *buffer, int length, void *file) {
|
||||
return fread(buffer, 1, length, reinterpret_cast<FILE *>(file));
|
||||
}
|
||||
|
||||
inline int fileWrite(const void *buffer, int length, void *file) {
|
||||
return fwrite(buffer, 1, length, reinterpret_cast<FILE *>(file));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool read(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, FILE *file) {
|
||||
return decode<internal::fileRead>(font, file);
|
||||
}
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool write(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, FILE *file) {
|
||||
return encode<internal::fileWrite>(font, file);
|
||||
}
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool readFile(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, const char *filename) {
|
||||
FILE *file = fopen(filename, "rb");
|
||||
if (!file)
|
||||
return false;
|
||||
bool result = read(font, file);
|
||||
fclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
bool writeFile(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, const char *filename) {
|
||||
FILE *file = fopen(filename, "wb");
|
||||
if (!file)
|
||||
return false;
|
||||
bool result = write(font, file);
|
||||
fclose(file);
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "enums.h"
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
template <typename REAL>
|
||||
struct Glyph {
|
||||
uint32 codepoint;
|
||||
uint32 image;
|
||||
struct {
|
||||
REAL l, b, r, t;
|
||||
} planeBounds, imageBounds;
|
||||
struct {
|
||||
REAL h, v;
|
||||
} advance;
|
||||
};
|
||||
|
||||
template <typename REAL>
|
||||
struct KernPair {
|
||||
uint32 codepoint1, codepoint2;
|
||||
struct {
|
||||
REAL h, v;
|
||||
} advance;
|
||||
};
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class STRING>
|
||||
struct FontVariant {
|
||||
uint32 flags;
|
||||
uint32 weight;
|
||||
CodepointType codepointType;
|
||||
ImageType imageType;
|
||||
uint32 fallbackVariant;
|
||||
uint32 fallbackGlyph;
|
||||
struct Metrics {
|
||||
// In pixels:
|
||||
REAL fontSize;
|
||||
REAL distanceRange;
|
||||
// Proportional to font size:
|
||||
REAL emSize;
|
||||
REAL ascender, descender;
|
||||
REAL lineHeight;
|
||||
REAL underlineY, underlineThickness;
|
||||
REAL reserved[24];
|
||||
} metrics;
|
||||
STRING name;
|
||||
STRING metadata;
|
||||
LIST<Glyph<REAL> > glyphs;
|
||||
LIST<KernPair<REAL> > kernPairs;
|
||||
};
|
||||
|
||||
template <class BYTE_ARRAY, class STRING>
|
||||
struct FontImage {
|
||||
uint32 flags;
|
||||
ImageEncoding encoding;
|
||||
uint32 width, height;
|
||||
uint32 channels;
|
||||
PixelFormat pixelFormat;
|
||||
ImageType imageType;
|
||||
struct {
|
||||
uint32 rowLength;
|
||||
ImageOrientation orientation;
|
||||
} rawBinaryFormat;
|
||||
uint32 childImages;
|
||||
uint32 textureFlags;
|
||||
STRING metadata;
|
||||
BYTE_ARRAY data;
|
||||
};
|
||||
|
||||
template <class BYTE_ARRAY, class STRING>
|
||||
struct FontAppendix {
|
||||
STRING metadata;
|
||||
BYTE_ARRAY data;
|
||||
};
|
||||
|
||||
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
|
||||
struct ArteryFont {
|
||||
typedef FontVariant<REAL, LIST, STRING> Variant;
|
||||
typedef FontImage<BYTE_ARRAY, STRING> Image;
|
||||
typedef FontAppendix<BYTE_ARRAY, STRING> Appendix;
|
||||
MetadataFormat metadataFormat;
|
||||
STRING metadata;
|
||||
LIST<Variant> variants;
|
||||
LIST<Image> images;
|
||||
LIST<Appendix> appendices;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace artery_font {
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef int32_t sint32;
|
||||
typedef uint32_t uint32;
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue