Compare commits

..

No commits in common. "master" and "v1.0" have entirely different histories.
master ... v1.0

6 changed files with 75 additions and 75 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2020 - 2024 Viktor Chlumsky Copyright (c) 2020 Viktor Chlumsky
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@ -6,5 +6,5 @@
#include "structures.h" #include "structures.h"
#include "serialization.h" #include "serialization.h"
// ARTERY ENGINE ATLAS FONT FORMAT LIBRARY v1.1 // ARTERY ENGINE ATLAS FONT FORMAT LIBRARY v1.0
// Author: Viktor Chlumsky (c) 2020 - 2024 // Author: Viktor Chlumsky (c) 2020

View File

@ -7,13 +7,10 @@
namespace artery_font { namespace artery_font {
typedef int ReadFunction(void *dst, int limit, void *userData); template <int (*READ)(void *, int, void *), typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
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); 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> template <int (*WRITE)(const void *, int, void *), typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData); bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData);
} }

View File

@ -81,11 +81,11 @@ template <typename REAL>
uint32 realTypeCode(); uint32 realTypeCode();
template <> template <>
inline uint32 realTypeCode<float>() { uint32 realTypeCode<float>() {
return 0x14u; return 0x14u;
} }
template <> template <>
inline uint32 realTypeCode<double>() { uint32 realTypeCode<double>() {
return 0x18u; return 0x18u;
} }
@ -97,7 +97,7 @@ inline uint32 paddedLength(uint32 len) {
template <class STRING> template <class STRING>
uint32 paddedStringLength(const STRING &str) { uint32 paddedStringLength(const STRING &str) {
uint32 len = (uint32) str.length(); uint32 len = str.length();
return paddedLength(len+(len > 0)); return paddedLength(len+(len > 0));
} }
@ -105,18 +105,18 @@ uint32 paddedStringLength(const STRING &str) {
#ifndef __BIG_ENDIAN__ #ifndef __BIG_ENDIAN__
template <ReadFunction READ, typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING> template <int (*READ)(void *, int, void *), typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) { bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
uint32 totalLength = 0; uint32 totalLength = 0;
uint32 prevLength = 0; uint32 prevLength = 0;
uint32 checksum = crc32Init(); uint32 checksum = crc32Init();
byte dump[4]; byte dump[4];
#define ARTERY_FONT_DECODE_READ(target, len) { \ #define ARTERY_FONT_DECODE_READ(target, len) { \
if (READ((target), (len), userData) != int(len)) \ if (READ((void *) (target), (len), userData) != (len)) \
return false; \ return false; \
totalLength += (len); \ totalLength += (len); \
for (int _i = 0; _i < int(len); ++_i) \ for (int i = 0; i < int(len); ++i) \
checksum = crc32Update(checksum, reinterpret_cast<const byte *>(target)[_i]); \ checksum = crc32Update(checksum, ((const byte *) (const void *) (target))[i]); \
} }
#define ARTERY_FONT_DECODE_REALIGN() { \ #define ARTERY_FONT_DECODE_REALIGN() { \
if (totalLength&0x03u) { \ if (totalLength&0x03u) { \
@ -129,7 +129,7 @@ bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
LIST<char> characters((len)+1); \ LIST<char> characters((len)+1); \
ARTERY_FONT_DECODE_READ((char *) characters, (len)+1); \ ARTERY_FONT_DECODE_READ((char *) characters, (len)+1); \
((char *) characters)[len] = '\0'; \ ((char *) characters)[len] = '\0'; \
(str) = STRING((const char *) characters, int(len)); \ (str) = STRING((const char *) characters, uint32(len)); \
ARTERY_FONT_DECODE_REALIGN(); \ ARTERY_FONT_DECODE_REALIGN(); \
} else \ } else \
(str) = STRING(); \ (str) = STRING(); \
@ -156,8 +156,8 @@ bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
imageCount = header.imageCount; imageCount = header.imageCount;
appendixCount = header.appendixCount; appendixCount = header.appendixCount;
font.variants = LIST<FontVariant<REAL, LIST, STRING> >(header.variantCount); font.variants = LIST<FontVariant<REAL, LIST, STRING> >(header.variantCount);
font.images = LIST<FontImage<BYTE_ARRAY, STRING> >(header.imageCount); font.images = LIST<Image<BYTE_ARRAY, STRING> >(header.imageCount);
font.appendices = LIST<FontAppendix<BYTE_ARRAY, STRING> >(header.appendixCount); font.appendices = LIST<Appendix<BYTE_ARRAY, STRING> >(header.appendixCount);
variantsLength = header.variantsLength; variantsLength = header.variantsLength;
imagesLength = header.imagesLength; imagesLength = header.imagesLength;
appendicesLength = header.appendicesLength; appendicesLength = header.appendicesLength;
@ -187,7 +187,7 @@ bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
prevLength = totalLength; prevLength = totalLength;
// Read images // Read images
for (int i = 0; i < imageCount; ++i) { for (int i = 0; i < imageCount; ++i) {
FontImage<BYTE_ARRAY, STRING> &image = font.images[i]; Image<BYTE_ARRAY, STRING> &image = font.images[i];
internal::ImageHeader header; internal::ImageHeader header;
ARTERY_FONT_DECODE_READ(&header, sizeof(header)); ARTERY_FONT_DECODE_READ(&header, sizeof(header));
image.flags = header.flags; image.flags = header.flags;
@ -211,7 +211,7 @@ bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
prevLength = totalLength; prevLength = totalLength;
// Read appendices // Read appendices
for (int i = 0; i < appendixCount; ++i) { for (int i = 0; i < appendixCount; ++i) {
FontAppendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i]; Appendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i];
internal::AppendixHeader header; internal::AppendixHeader header;
ARTERY_FONT_DECODE_READ(&header, sizeof(header)); ARTERY_FONT_DECODE_READ(&header, sizeof(header));
ARTERY_FONT_DECODE_READ_STRING(appendix.metadata, header.metadataLength); ARTERY_FONT_DECODE_READ_STRING(appendix.metadata, header.metadataLength);
@ -228,9 +228,9 @@ bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
ARTERY_FONT_DECODE_READ(&footer, sizeof(footer)-sizeof(footer.checksum)); ARTERY_FONT_DECODE_READ(&footer, sizeof(footer)-sizeof(footer.checksum));
if (footer.magicNo != ARTERY_FONT_FOOTER_MAGIC_NO) if (footer.magicNo != ARTERY_FONT_FOOTER_MAGIC_NO)
return false; return false;
uint32 finalChecksum = checksum; uint32 prevChecksum = checksum;
ARTERY_FONT_DECODE_READ(&footer.checksum, sizeof(footer.checksum)); ARTERY_FONT_DECODE_READ(&footer.checksum, sizeof(footer.checksum));
if (footer.checksum != finalChecksum) if (footer.checksum != prevChecksum)
return false; return false;
if (totalLength != footer.totalLength) if (totalLength != footer.totalLength)
return false; return false;
@ -241,28 +241,28 @@ bool decode(ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
#undef ARTERY_FONT_DECODE_READ_STRING #undef ARTERY_FONT_DECODE_READ_STRING
} }
template <WriteFunction WRITE, typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING> template <int (*WRITE)(const void *, int, void *), typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) { bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userData) {
uint32 totalLength = 0; uint32 totalLength = 0;
uint32 checksum = crc32Init(); uint32 checksum = crc32Init();
const byte padding[4] = { }; const byte padding[4] = { };
#define ARTERY_FONT_ENCODE_WRITE(data, len) { \ #define ARTERY_FONT_ENCODE_WRITE(data, len) { \
if (WRITE((data), (len), userData) != int(len)) \ if (WRITE((const void *) (data), (len), userData) != (len)) \
return false; \ return false; \
totalLength += (len); \ totalLength += (len); \
for (int _i = 0; _i < int(len); ++_i) \ for (int i = 0; i < int(len); ++i) \
checksum = crc32Update(checksum, reinterpret_cast<const byte *>(data)[_i]); \ checksum = crc32Update(checksum, ((const byte *) (const void *) (data))[i]); \
} }
#define ARTERY_FONT_ENCODE_REALIGN() { \ #define ARTERY_FONT_ENCODE_REALIGN() { \
if (totalLength&0x03u) { \ if (totalLength&0x03u) { \
uint32 _len = 0x04u-(totalLength&0x03u); \ uint32 len = 0x04u-(totalLength&0x03u); \
ARTERY_FONT_ENCODE_WRITE(padding, _len); \ ARTERY_FONT_ENCODE_WRITE(padding, len); \
} \ } \
} }
#define ARTERY_FONT_ENCODE_WRITE_STRING(str) { \ #define ARTERY_FONT_ENCODE_WRITE_STRING(str) { \
uint32 len = (uint32) (str).length(); \ uint32 len = (str).length(); \
if (len > 0) { \ if ((len) > 0) { \
ARTERY_FONT_ENCODE_WRITE((const char *) (str), len); \ ARTERY_FONT_ENCODE_WRITE((const char *) (str), (len)); \
ARTERY_FONT_ENCODE_WRITE(padding, 1) \ ARTERY_FONT_ENCODE_WRITE(padding, 1) \
ARTERY_FONT_ENCODE_REALIGN(); \ ARTERY_FONT_ENCODE_REALIGN(); \
} \ } \
@ -280,12 +280,12 @@ bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userDa
header.realType = internal::realTypeCode<REAL>(); header.realType = internal::realTypeCode<REAL>();
memset(header.reserved, 0, sizeof(header.reserved)); memset(header.reserved, 0, sizeof(header.reserved));
header.metadataFormat = (uint32) font.metadataFormat; header.metadataFormat = (uint32) font.metadataFormat;
header.metadataLength = (uint32) font.metadata.length(); header.metadataLength = font.metadata.length();
header.variantCount = variantCount = (int) font.variants.length(); header.variantCount = variantCount = font.variants.length();
header.variantsLength = 0; header.variantsLength = 0;
header.imageCount = imageCount = (int) font.images.length(); header.imageCount = imageCount = font.images.length();
header.imagesLength = 0; header.imagesLength = 0;
header.appendixCount = appendixCount = (int) font.appendices.length(); header.appendixCount = appendixCount = font.appendices.length();
header.appendicesLength = 0; header.appendicesLength = 0;
memset(header.reserved2, 0, sizeof(header.reserved2)); memset(header.reserved2, 0, sizeof(header.reserved2));
for (int i = 0; i < variantCount; ++i) { for (int i = 0; i < variantCount; ++i) {
@ -293,20 +293,20 @@ bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userDa
header.variantsLength += sizeof(internal::FontVariantHeader<REAL>); header.variantsLength += sizeof(internal::FontVariantHeader<REAL>);
header.variantsLength += internal::paddedStringLength(variant.name); header.variantsLength += internal::paddedStringLength(variant.name);
header.variantsLength += internal::paddedStringLength(variant.metadata); header.variantsLength += internal::paddedStringLength(variant.metadata);
header.variantsLength += (uint32) (variant.glyphs.length()*sizeof(Glyph<REAL>)); header.variantsLength += variant.glyphs.length()*sizeof(Glyph<REAL>);
header.variantsLength += (uint32) (variant.kernPairs.length()*sizeof(KernPair<REAL>)); header.variantsLength += variant.kernPairs.length()*sizeof(KernPair<REAL>);
} }
for (int i = 0; i < imageCount; ++i) { for (int i = 0; i < imageCount; ++i) {
const FontImage<BYTE_ARRAY, STRING> &image = font.images[i]; const Image<BYTE_ARRAY, STRING> &image = font.images[i];
header.imagesLength += sizeof(internal::ImageHeader); header.imagesLength += sizeof(internal::ImageHeader);
header.imagesLength += internal::paddedStringLength(image.metadata); header.imagesLength += internal::paddedStringLength(image.metadata);
header.imagesLength += internal::paddedLength((uint32) image.data.length()); header.imagesLength += internal::paddedLength(image.data.length());
} }
for (int i = 0; i < appendixCount; ++i) { for (int i = 0; i < appendixCount; ++i) {
const FontAppendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i]; const Appendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i];
header.appendicesLength += sizeof(internal::AppendixHeader); header.appendicesLength += sizeof(internal::AppendixHeader);
header.appendicesLength += internal::paddedStringLength(appendix.metadata); header.appendicesLength += internal::paddedStringLength(appendix.metadata);
header.appendicesLength += internal::paddedLength((uint32) appendix.data.length()); header.appendicesLength += internal::paddedLength(appendix.data.length());
} }
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header)); ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
ARTERY_FONT_ENCODE_WRITE_STRING(font.metadata); ARTERY_FONT_ENCODE_WRITE_STRING(font.metadata);
@ -323,10 +323,10 @@ bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userDa
header.fallbackGlyph = variant.fallbackGlyph; header.fallbackGlyph = variant.fallbackGlyph;
memset(header.reserved, 0, sizeof(header.reserved)); memset(header.reserved, 0, sizeof(header.reserved));
memcpy(header.metrics, &variant.metrics, sizeof(header.metrics)); memcpy(header.metrics, &variant.metrics, sizeof(header.metrics));
header.nameLength = (uint32) variant.name.length(); header.nameLength = variant.name.length();
header.metadataLength = (uint32) variant.metadata.length(); header.metadataLength = variant.metadata.length();
header.glyphCount = (uint32) variant.glyphs.length(); header.glyphCount = variant.glyphs.length();
header.kernPairCount = (uint32) variant.kernPairs.length(); header.kernPairCount = variant.kernPairs.length();
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header)); ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
ARTERY_FONT_ENCODE_WRITE_STRING(variant.name); ARTERY_FONT_ENCODE_WRITE_STRING(variant.name);
ARTERY_FONT_ENCODE_WRITE_STRING(variant.metadata); ARTERY_FONT_ENCODE_WRITE_STRING(variant.metadata);
@ -335,7 +335,7 @@ bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userDa
} }
// Write images // Write images
for (int i = 0; i < imageCount; ++i) { for (int i = 0; i < imageCount; ++i) {
const FontImage<BYTE_ARRAY, STRING> &image = font.images[i]; const Image<BYTE_ARRAY, STRING> &image = font.images[i];
internal::ImageHeader header; internal::ImageHeader header;
header.flags = image.flags; header.flags = image.flags;
header.encoding = (uint32) image.encoding; header.encoding = (uint32) image.encoding;
@ -349,8 +349,8 @@ bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userDa
header.childImages = image.childImages; header.childImages = image.childImages;
header.textureFlags = image.textureFlags; header.textureFlags = image.textureFlags;
memset(header.reserved, 0, sizeof(header.reserved)); memset(header.reserved, 0, sizeof(header.reserved));
header.metadataLength = (uint32) image.metadata.length(); header.metadataLength = image.metadata.length();
header.dataLength = (uint32) image.data.length(); header.dataLength = image.data.length();
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header)); ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
ARTERY_FONT_ENCODE_WRITE_STRING(image.metadata); ARTERY_FONT_ENCODE_WRITE_STRING(image.metadata);
ARTERY_FONT_ENCODE_WRITE((const unsigned char *) image.data, header.dataLength); ARTERY_FONT_ENCODE_WRITE((const unsigned char *) image.data, header.dataLength);
@ -358,10 +358,10 @@ bool encode(const ArteryFont<REAL, LIST, BYTE_ARRAY, STRING> &font, void *userDa
} }
// Write appendices // Write appendices
for (int i = 0; i < appendixCount; ++i) { for (int i = 0; i < appendixCount; ++i) {
const FontAppendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i]; const Appendix<BYTE_ARRAY, STRING> &appendix = font.appendices[i];
internal::AppendixHeader header; internal::AppendixHeader header;
header.metadataLength = (uint32) appendix.metadata.length(); header.metadataLength = appendix.metadata.length();
header.dataLength = (uint32) appendix.data.length(); header.dataLength = appendix.data.length();
ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header)); ARTERY_FONT_ENCODE_WRITE(&header, sizeof(header));
ARTERY_FONT_ENCODE_WRITE_STRING(appendix.metadata); ARTERY_FONT_ENCODE_WRITE_STRING(appendix.metadata);
ARTERY_FONT_ENCODE_WRITE((const unsigned char *) appendix.data, header.dataLength); ARTERY_FONT_ENCODE_WRITE((const unsigned char *) appendix.data, header.dataLength);

View File

@ -8,26 +8,30 @@
namespace artery_font { namespace artery_font {
template <typename T> template <typename T>
class StdList : private std::vector<T> { class StdList {
public: public:
inline StdList() { } std::vector<T> vector;
inline explicit StdList(int length) : std::vector<T>((size_t) length) { }
inline int length() const { return (int) std::vector<T>::size(); } StdList() { }
inline explicit operator T *() { return std::vector<T>::data(); } explicit StdList(int length) : vector((size_t) length) { }
inline explicit operator const T *() const { return std::vector<T>::data(); } int length() const { return (int) vector.size(); }
inline T &operator[](int index) { return std::vector<T>::operator[](index); } explicit operator T *() { return vector.data(); }
inline const T &operator[](int index) const { return std::vector<T>::operator[](index); } explicit operator const T *() const { return vector.data(); }
T & operator[](int index) { return vector[index]; }
const T & operator[](int index) const { return vector[index]; }
}; };
class StdString : private std::string { class StdString {
public: public:
inline StdString() { } std::string string;
inline StdString(const char *characters, int length) : std::string(characters, (size_t) length) { }
inline int length() const { return (int) std::string::size(); } StdString() { }
inline explicit operator const char *() const { return std::string::c_str(); } StdString(const char *characters, int length) : string(characters, (size_t) length) { }
int length() const { return (int) string.size(); }
explicit operator const char *() const { return string.c_str(); }
}; };
@ -35,5 +39,9 @@ typedef StdList<unsigned char> StdByteArray;
template <typename REAL> template <typename REAL>
using StdArteryFont = ArteryFont<REAL, StdList, StdByteArray, StdString>; using StdArteryFont = ArteryFont<REAL, StdList, StdByteArray, StdString>;
template <typename REAL>
using StdFontVariant = FontVariant<REAL, StdList, StdString>;
using StdImage = Image<StdByteArray, StdString>;
using StdAppendix = Appendix<StdByteArray, StdString>;
} }

View File

@ -43,9 +43,7 @@ struct FontVariant {
REAL ascender, descender; REAL ascender, descender;
REAL lineHeight; REAL lineHeight;
REAL underlineY, underlineThickness; REAL underlineY, underlineThickness;
// In pixels: REAL reserved[24];
REAL distanceRangeMiddle;
REAL reserved[23];
} metrics; } metrics;
STRING name; STRING name;
STRING metadata; STRING metadata;
@ -54,7 +52,7 @@ struct FontVariant {
}; };
template <class BYTE_ARRAY, class STRING> template <class BYTE_ARRAY, class STRING>
struct FontImage { struct Image {
uint32 flags; uint32 flags;
ImageEncoding encoding; ImageEncoding encoding;
uint32 width, height; uint32 width, height;
@ -72,21 +70,18 @@ struct FontImage {
}; };
template <class BYTE_ARRAY, class STRING> template <class BYTE_ARRAY, class STRING>
struct FontAppendix { struct Appendix {
STRING metadata; STRING metadata;
BYTE_ARRAY data; BYTE_ARRAY data;
}; };
template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING> template <typename REAL, template <typename> class LIST, class BYTE_ARRAY, class STRING>
struct ArteryFont { struct ArteryFont {
typedef FontVariant<REAL, LIST, STRING> Variant;
typedef FontImage<BYTE_ARRAY, STRING> Image;
typedef FontAppendix<BYTE_ARRAY, STRING> Appendix;
MetadataFormat metadataFormat; MetadataFormat metadataFormat;
STRING metadata; STRING metadata;
LIST<Variant> variants; LIST<FontVariant<REAL, LIST, STRING> > variants;
LIST<Image> images; LIST<Image<BYTE_ARRAY, STRING> > images;
LIST<Appendix> appendices; LIST<Appendix<BYTE_ARRAY, STRING> > appendices;
}; };
} }