mirror of
https://github.com/NoelFB/blah.git
synced 2024-11-25 16:18:57 +08:00
various memory cleanup, move/copy simplifications
This commit is contained in:
parent
b1e33f2627
commit
9c7d8a4418
|
@ -81,61 +81,46 @@ namespace Blah
|
|||
#else
|
||||
namespace Blah
|
||||
{
|
||||
struct RefDel { virtual ~RefDel() = default; virtual void delete_it(void* it) = 0; };
|
||||
template<class Y> struct RefDelOf : public RefDel { void delete_it(void* it) { delete (Y*)it; } };
|
||||
|
||||
template<typename T>
|
||||
class Ref
|
||||
{
|
||||
template<class Y> friend class Ref;
|
||||
private:
|
||||
T* m_instance;
|
||||
i32* m_counter;
|
||||
Ref(T* instance, i32* counter) : m_instance(instance), m_counter(counter) {}
|
||||
inline static RefDelOf<T> del;
|
||||
|
||||
T* m_obj = nullptr;
|
||||
u32* m_num = nullptr;
|
||||
RefDel* m_del = nullptr;
|
||||
|
||||
Ref(T* o, u32* n, RefDel* d) : m_obj(o), m_num(n), m_del(d) {}
|
||||
|
||||
void copy(const Ref& rhs) { m_obj = rhs.m_obj; m_num = rhs.m_num; m_del = rhs.m_del; }
|
||||
void zero() { m_obj = nullptr; m_num = nullptr; m_del = nullptr; }
|
||||
void steal(Ref& rhs) { copy(rhs); rhs.zero(); }
|
||||
void increment() { if (m_num) (*m_num)++; }
|
||||
|
||||
public:
|
||||
Ref() : m_instance(nullptr), m_counter(nullptr) {}
|
||||
|
||||
Ref() = default;
|
||||
template<class Y>
|
||||
Ref(Y* instance) : Ref(static_cast<T*>(instance), new i32(1)) {}
|
||||
Ref(const Ref& rhs) : Ref(rhs.m_instance, rhs.m_counter) { if (m_counter) (*m_counter)++; }
|
||||
Ref(Ref&& rhs) : Ref(rhs.m_instance, rhs.m_counter) { rhs.m_instance = nullptr; rhs.m_counter = nullptr; }
|
||||
|
||||
Ref& operator=(const Ref& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
reset();
|
||||
m_instance = rhs.m_instance; m_counter = rhs.m_counter;
|
||||
if (m_counter) (*m_counter)++;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ref& operator=(Ref&& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
reset();
|
||||
m_instance = rhs.m_instance; m_counter = rhs.m_counter;
|
||||
rhs.m_instance = nullptr; rhs.m_counter = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Ref(Y* instance) : Ref(static_cast<T*>(instance), new u32(1), &Ref<Y>::del) {}
|
||||
Ref(const Ref& rhs) { copy(rhs); increment(); }
|
||||
Ref(Ref&& rhs) { steal(rhs); }
|
||||
~Ref() { reset(); }
|
||||
|
||||
void reset()
|
||||
{
|
||||
if (m_counter) (*m_counter)--;
|
||||
if (m_counter && (*m_counter) <= 0) { delete m_instance; delete m_counter; }
|
||||
m_instance = nullptr; m_counter = nullptr;
|
||||
}
|
||||
Ref& operator=(const Ref& rhs) { if (this != &rhs) { reset(); copy(rhs); increment(); } return *this; }
|
||||
Ref& operator=(Ref&& rhs) { if (this != &rhs) { reset(); steal(rhs); } return *this; }
|
||||
|
||||
int use_count() const { return (m_counter ? (*m_counter) : 0); }
|
||||
T* get() const { return m_instance; }
|
||||
T* operator->() const { return m_instance; }
|
||||
operator bool() const { return m_counter && (*m_counter) > 0; }
|
||||
template<class Y> bool operator==(const Ref<Y>& rhs) const { return m_counter == rhs.m_counter; }
|
||||
template<class Y> bool operator!=(const Ref<Y>& rhs) const { return m_counter != rhs.m_counter; }
|
||||
template<class Y> operator Ref<Y>() { if (m_counter) (*m_counter)++; return Ref<Y>(static_cast<Y*>(m_instance), m_counter); }
|
||||
void reset() { if (m_num && --(*m_num) <= 0) { m_del->delete_it(m_obj); delete m_num; } zero(); }
|
||||
int use_count() const { return (m_num ? (*m_num) : 0); }
|
||||
T* get() const { return m_obj; }
|
||||
T* operator->() const { return m_obj; }
|
||||
operator bool() const { return m_num && (*m_num) > 0; }
|
||||
template<class Y> bool operator==(const Ref<Y>& rhs) const { return m_num == rhs.m_num; }
|
||||
template<class Y> bool operator!=(const Ref<Y>& rhs) const { return m_num != rhs.m_num; }
|
||||
template<class Y> operator Ref<Y>() { increment(); return Ref<Y>(static_cast<Y*>(m_obj), m_num, m_del); }
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -3,13 +3,12 @@
|
|||
#include <blah/containers/str.h>
|
||||
#include <blah/containers/vector.h>
|
||||
#include <blah/graphics/subtexture.h>
|
||||
#include <blah/images/font.h>
|
||||
#include <blah/math/spatial.h>
|
||||
#include <blah/filesystem.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
class Font;
|
||||
|
||||
// Sprite Font is a bitmap font implementation for font rendering.
|
||||
// It can be constructed from a Font (ttf) and will automatically create
|
||||
// texture atlases for rendering. You can add your own characters
|
||||
|
@ -59,30 +58,25 @@ namespace Blah
|
|||
String name;
|
||||
|
||||
// Height, in pixels
|
||||
float size;
|
||||
float size = 0;
|
||||
|
||||
// Ascent, in pixels
|
||||
float ascent;
|
||||
float ascent = 0;
|
||||
|
||||
// Descent, in pixels
|
||||
float descent;
|
||||
float descent = 0;
|
||||
|
||||
// Line Gap, in pixels
|
||||
float line_gap;
|
||||
float line_gap = 0;
|
||||
|
||||
SpriteFont();
|
||||
SpriteFont() = default;
|
||||
SpriteFont(const FilePath& file, float size);
|
||||
SpriteFont(const FilePath& file, float size, const CharSet& charset);
|
||||
SpriteFont(const Font& font, float size);
|
||||
SpriteFont(const Font& font, float size, const CharSet& charset);
|
||||
SpriteFont(const SpriteFont&) = delete;
|
||||
SpriteFont& operator=(const SpriteFont&) = delete;
|
||||
SpriteFont(SpriteFont&& src) noexcept;
|
||||
SpriteFont& operator=(SpriteFont&& src) noexcept;
|
||||
~SpriteFont();
|
||||
SpriteFont(const FontRef& font, float size);
|
||||
SpriteFont(const FontRef& font, float size, const CharSet& charset);
|
||||
|
||||
// releases all assets used by the spritefont
|
||||
void dispose();
|
||||
void clear();
|
||||
|
||||
// gets the height of the sprite font
|
||||
float height() const { return ascent - descent; }
|
||||
|
@ -106,7 +100,7 @@ namespace Blah
|
|||
void rebuild(const FilePath& file, float size, const CharSet& charset);
|
||||
|
||||
// disposes the existing spritefont data and rebuilds from the given font
|
||||
void rebuild(const Font& font, float size, const CharSet& charset);
|
||||
void rebuild(const FontRef& font, float size, const CharSet& charset);
|
||||
|
||||
// gets the kerning between two characters
|
||||
float get_kerning(Codepoint codepoint0, Codepoint codepoint1) const;
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
#pragma once
|
||||
#include <blah/common.h>
|
||||
#include <blah/streams/stream.h>
|
||||
#include <blah/images/image.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/containers/vector.h>
|
||||
#include <blah/filesystem.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
// Loads fonts from file and can blit individual characters to images
|
||||
class Font;
|
||||
using FontRef = Ref<Font>;
|
||||
|
||||
// Loads fonts from file and can blit individual characters to images.
|
||||
// Use Font::create() to instantiate a FontRef.
|
||||
class Font
|
||||
{
|
||||
private:
|
||||
Font() = default;
|
||||
|
||||
public:
|
||||
|
||||
// Font uses u32 Codepoints
|
||||
|
@ -42,18 +51,11 @@ namespace Blah
|
|||
bool has_glyph = false;
|
||||
};
|
||||
|
||||
Font();
|
||||
Font(Stream& stream);
|
||||
Font(const FilePath& path);
|
||||
Font(const Font&) = delete;
|
||||
Font& operator=(const Font&) = delete;
|
||||
Font(Font&& src) noexcept;
|
||||
Font& operator=(Font&& src) noexcept;
|
||||
~Font();
|
||||
// creates a new font from the given file path
|
||||
static FontRef create(const FilePath& path);
|
||||
|
||||
// Releases all Font resources
|
||||
// Note that after doing this various properties may become invalid (ex. font name)
|
||||
void dispose();
|
||||
// creates a new font from the Stream
|
||||
static FontRef create(Stream& stream);
|
||||
|
||||
// returns the font family name
|
||||
const String& family_name() const;
|
||||
|
@ -97,18 +99,13 @@ namespace Blah
|
|||
// If the character doesn't exist, this will return an empty image.
|
||||
Image get_image(const Character& ch) const;
|
||||
|
||||
// checks if the Font is valid
|
||||
bool is_valid() const;
|
||||
|
||||
private:
|
||||
void load(Stream& stream);
|
||||
void* m_font;
|
||||
unsigned char* m_data;
|
||||
Ref<void> m_font;
|
||||
Vector<u8> m_buffer;
|
||||
String m_family_name;
|
||||
String m_style_name;
|
||||
int m_ascent;
|
||||
int m_descent;
|
||||
int m_line_gap;
|
||||
bool m_valid;
|
||||
int m_ascent = 0;
|
||||
int m_descent = 0;
|
||||
int m_line_gap = 0;
|
||||
};
|
||||
}
|
|
@ -69,11 +69,6 @@ namespace Blah
|
|||
|
||||
Packer();
|
||||
Packer(int max_size, int spacing, bool power_of_two);
|
||||
Packer(const Packer&) = delete;
|
||||
Packer& operator=(const Packer&) = delete;
|
||||
Packer(Packer&& src) noexcept;
|
||||
Packer& operator=(Packer&& src) noexcept;
|
||||
~Packer();
|
||||
|
||||
// add a new entry
|
||||
void add(u64 id, int width, int height, const Color* pixels);
|
||||
|
@ -96,9 +91,6 @@ namespace Blah
|
|||
// clear the current packer data
|
||||
void clear();
|
||||
|
||||
// dispose all resources used by the packer
|
||||
void dispose();
|
||||
|
||||
private:
|
||||
struct Node
|
||||
{
|
||||
|
|
|
@ -8,34 +8,28 @@ namespace Blah
|
|||
class BufferStream : public Stream
|
||||
{
|
||||
public:
|
||||
BufferStream();
|
||||
BufferStream() = default;
|
||||
BufferStream(int capacity);
|
||||
BufferStream(BufferStream&& bs) noexcept;
|
||||
BufferStream& operator=(BufferStream&& bs) noexcept;
|
||||
~BufferStream();
|
||||
|
||||
size_t length() const override;
|
||||
size_t position() const override;
|
||||
size_t seek(size_t seekTo) override;
|
||||
size_t seek(size_t seek_to) override;
|
||||
bool is_open() const override;
|
||||
bool is_readable() const override;
|
||||
bool is_writable() const override;
|
||||
void close() override;
|
||||
|
||||
void resize(size_t length);
|
||||
void clear();
|
||||
|
||||
char* data();
|
||||
const char* data() const;
|
||||
u8* data();
|
||||
const u8* data() const;
|
||||
|
||||
protected:
|
||||
size_t read_data(void* ptr, size_t length) override;
|
||||
size_t write_data(const void* ptr, size_t length) override;
|
||||
|
||||
private:
|
||||
char* m_buffer;
|
||||
size_t m_capacity;
|
||||
size_t m_length;
|
||||
size_t m_position;
|
||||
Vector<u8> m_buffer;
|
||||
size_t m_position = 0;
|
||||
};
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Blah
|
|||
class FileStream : public Stream
|
||||
{
|
||||
public:
|
||||
FileStream();
|
||||
FileStream() = default;
|
||||
FileStream(const FilePath& path, FileMode mode);
|
||||
FileStream(FileStream&& fs) noexcept;
|
||||
FileStream& operator=(FileStream&& fs) noexcept;
|
||||
|
@ -18,14 +18,13 @@ namespace Blah
|
|||
bool is_open() const override;
|
||||
bool is_readable() const override;
|
||||
bool is_writable() const override;
|
||||
void close() override;
|
||||
|
||||
protected:
|
||||
size_t read_data(void* ptr, size_t length) override;
|
||||
size_t write_data(const void* ptr, size_t length) override;
|
||||
|
||||
private:
|
||||
FileMode m_mode;
|
||||
FileMode m_mode = FileMode::OpenRead;
|
||||
FileRef m_file;
|
||||
};
|
||||
}
|
|
@ -8,30 +8,28 @@ namespace Blah
|
|||
class MemoryStream : public Stream
|
||||
{
|
||||
public:
|
||||
MemoryStream();
|
||||
MemoryStream(unsigned char* data, size_t length);
|
||||
MemoryStream(MemoryStream&& ms) noexcept;
|
||||
MemoryStream& operator=(MemoryStream&& ms) noexcept;
|
||||
~MemoryStream() override { m_data = nullptr; m_length = m_position = 0; }
|
||||
MemoryStream() = default;
|
||||
MemoryStream(u8* data, size_t length);
|
||||
MemoryStream(const u8* data, size_t length);
|
||||
|
||||
size_t length() const override;
|
||||
size_t position() const override;
|
||||
size_t seek(size_t seekTo) override;
|
||||
size_t seek(size_t seek_to) override;
|
||||
bool is_open() const override;
|
||||
bool is_readable() const override;
|
||||
bool is_writable() const override;
|
||||
void close() override;
|
||||
|
||||
unsigned char* data();
|
||||
const unsigned char* data() const;
|
||||
u8* data();
|
||||
const u8* data() const;
|
||||
|
||||
protected:
|
||||
size_t read_data(void* ptr, size_t length) override;
|
||||
size_t write_data(const void* ptr, size_t length) override;
|
||||
|
||||
private:
|
||||
unsigned char* m_data;
|
||||
size_t m_length;
|
||||
size_t m_position;
|
||||
u8* m_data = nullptr;
|
||||
const u8* m_const_data = nullptr;
|
||||
size_t m_length = 0;
|
||||
size_t m_position = 0;
|
||||
};
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
#include <blah/common.h>
|
||||
#include <blah/containers/str.h>
|
||||
#include <blah/math/calc.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Blah
|
||||
{
|
||||
|
@ -33,9 +32,6 @@ namespace Blah
|
|||
// returns true of the stream is writable
|
||||
virtual bool is_writable() const = 0;
|
||||
|
||||
// closes the stream
|
||||
virtual void close() = 0;
|
||||
|
||||
// pipes the contents of this stream to another stream
|
||||
size_t pipe(Stream& to, size_t length);
|
||||
|
||||
|
|
|
@ -14,14 +14,6 @@ SpriteFont::CharRange::CharRange(Codepoint from, Codepoint to)
|
|||
|
||||
const SpriteFont::CharSet SpriteFont::CharRange::ASCII = SpriteFont::CharSet({ CharRange(32, 128) });
|
||||
|
||||
SpriteFont::SpriteFont()
|
||||
{
|
||||
size = 0;
|
||||
ascent = 0;
|
||||
descent = 0;
|
||||
line_gap = 0;
|
||||
}
|
||||
|
||||
SpriteFont::SpriteFont(const FilePath& file, float size)
|
||||
{
|
||||
rebuild(file, size, CharRange::ASCII);
|
||||
|
@ -32,52 +24,22 @@ SpriteFont::SpriteFont(const FilePath& file, float size, const CharSet& charset)
|
|||
rebuild(file, size, charset);
|
||||
}
|
||||
|
||||
SpriteFont::SpriteFont(const Font& font, float size)
|
||||
SpriteFont::SpriteFont(const FontRef& font, float size)
|
||||
{
|
||||
rebuild(font, size, CharRange::ASCII);
|
||||
}
|
||||
|
||||
SpriteFont::SpriteFont(const Font& font, float size, const CharSet& charset)
|
||||
SpriteFont::SpriteFont(const FontRef& font, float size, const CharSet& charset)
|
||||
{
|
||||
rebuild(font, size, charset);
|
||||
}
|
||||
|
||||
SpriteFont::SpriteFont(SpriteFont&& src) noexcept
|
||||
{
|
||||
name = src.name;
|
||||
size = src.size;
|
||||
ascent = src.ascent;
|
||||
descent = src.descent;
|
||||
line_gap = src.line_gap;
|
||||
m_characters = std::move(src.m_characters);
|
||||
m_kerning = std::move(src.m_kerning);
|
||||
m_atlas = std::move(src.m_atlas);
|
||||
}
|
||||
|
||||
SpriteFont::~SpriteFont()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void SpriteFont::dispose()
|
||||
void SpriteFont::clear()
|
||||
{
|
||||
m_atlas.clear();
|
||||
m_characters.clear();
|
||||
m_kerning.clear();
|
||||
name.dispose();
|
||||
}
|
||||
|
||||
SpriteFont& SpriteFont::operator=(SpriteFont && src) noexcept
|
||||
{
|
||||
name = src.name;
|
||||
size = src.size;
|
||||
ascent = src.ascent;
|
||||
descent = src.descent;
|
||||
line_gap = src.line_gap;
|
||||
m_characters = std::move(src.m_characters);
|
||||
m_kerning = std::move(src.m_kerning);
|
||||
m_atlas = std::move(src.m_atlas);
|
||||
return *this;
|
||||
name.clear();
|
||||
}
|
||||
|
||||
float SpriteFont::width_of(const String& text) const
|
||||
|
@ -86,7 +48,7 @@ float SpriteFont::width_of(const String& text) const
|
|||
float line_width = 0;
|
||||
|
||||
Codepoint last = 0;
|
||||
for (int i = 0; i < text.length(); i ++)
|
||||
for (int i = 0; i < text.length(); i += text.utf8_length(i))
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
{
|
||||
|
@ -94,21 +56,12 @@ float SpriteFont::width_of(const String& text) const
|
|||
continue;
|
||||
}
|
||||
|
||||
// get codepoint
|
||||
auto next = text.utf8_at(i);
|
||||
|
||||
// increment length
|
||||
line_width += this->operator[](next).advance;
|
||||
|
||||
// add kerning
|
||||
line_width += get_character(next).advance;
|
||||
if (i > 0)
|
||||
line_width += get_kerning(last, next);
|
||||
|
||||
if (line_width > width)
|
||||
width = line_width;
|
||||
|
||||
// move to thext utf8 character
|
||||
i += text.utf8_length(i) - 1;
|
||||
last = next;
|
||||
}
|
||||
|
||||
|
@ -123,26 +76,15 @@ float SpriteFont::width_of_line(const String& text, int start) const
|
|||
float width = 0;
|
||||
|
||||
Codepoint last = 0;
|
||||
for (auto i = start; i < text.length(); i ++)
|
||||
for (auto i = start; i < text.length(); i += text.utf8_length(i))
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
return width;
|
||||
|
||||
// get codepoint
|
||||
auto next = text.utf8_at(i);
|
||||
|
||||
// increment length
|
||||
width += this->operator[](next).advance;
|
||||
|
||||
// add kerning
|
||||
width += get_character(next).advance;
|
||||
if (i > 0)
|
||||
width += get_kerning(last, next);
|
||||
|
||||
// move to thext utf8 character
|
||||
auto len = text.utf8_length(i);
|
||||
if (len > 0)
|
||||
i += len - 1;
|
||||
|
||||
last = next;
|
||||
}
|
||||
|
||||
|
@ -155,11 +97,10 @@ float SpriteFont::height_of(const String& text) const
|
|||
return 0;
|
||||
|
||||
float height = line_height();
|
||||
for (auto i = 0; i < text.length(); i ++)
|
||||
for (auto i = 0; i < text.length(); i += text.utf8_length(i))
|
||||
{
|
||||
if (text[i] == '\n')
|
||||
height += line_height();
|
||||
i += text.utf8_length(i) - 1;
|
||||
}
|
||||
|
||||
return height - line_gap;
|
||||
|
@ -167,23 +108,24 @@ float SpriteFont::height_of(const String& text) const
|
|||
|
||||
void SpriteFont::rebuild(const FilePath& file, float sz, const CharSet& charset)
|
||||
{
|
||||
dispose();
|
||||
clear();
|
||||
|
||||
Font font(file);
|
||||
if (font.is_valid())
|
||||
if (auto font = Font::create(file))
|
||||
rebuild(font, sz, charset);
|
||||
}
|
||||
|
||||
void SpriteFont::rebuild(const Font& font, float size, const CharSet& charset)
|
||||
void SpriteFont::rebuild(const FontRef& font, float size, const CharSet& charset)
|
||||
{
|
||||
dispose();
|
||||
clear();
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
float scale = font.get_scale(size);
|
||||
float scale = font->get_scale(size);
|
||||
|
||||
name = font.family_name();
|
||||
ascent = font.ascent() * scale;
|
||||
descent = font.descent() * scale;
|
||||
line_gap = font.line_gap() * scale;
|
||||
name = font->family_name();
|
||||
ascent = font->ascent() * scale;
|
||||
descent = font->descent() * scale;
|
||||
line_gap = font->line_gap() * scale;
|
||||
this->size = size;
|
||||
|
||||
Packer packer;
|
||||
|
@ -203,12 +145,12 @@ void SpriteFont::rebuild(const Font& font, float size, const CharSet& charset)
|
|||
|
||||
for (auto i = from; i < to; i++)
|
||||
{
|
||||
auto glyph = font.get_glyph(i);
|
||||
auto glyph = font->get_glyph(i);
|
||||
if (glyph <= 0)
|
||||
continue;
|
||||
|
||||
// add character
|
||||
auto ch = font.get_character(glyph, scale);
|
||||
auto ch = font->get_character(glyph, scale);
|
||||
auto& sfch = get_character(i);
|
||||
sfch.codepoint = i;
|
||||
sfch.advance = ch.advance;
|
||||
|
@ -220,7 +162,7 @@ void SpriteFont::rebuild(const Font& font, float size, const CharSet& charset)
|
|||
if (buffer.size() < ch.width * ch.height)
|
||||
buffer.resize(ch.width * ch.height);
|
||||
|
||||
if (font.get_image(ch, buffer.data()))
|
||||
if (font->get_image(ch, buffer.data()))
|
||||
packer.add(i, ch.width, ch.height, buffer.data());
|
||||
}
|
||||
}
|
||||
|
@ -242,7 +184,7 @@ void SpriteFont::rebuild(const Font& font, float size, const CharSet& charset)
|
|||
{
|
||||
for (auto& b : m_characters)
|
||||
{
|
||||
auto kerning_value = font.get_kerning(a.glyph, b.glyph, scale);
|
||||
auto kerning_value = font->get_kerning(a.glyph, b.glyph, scale);
|
||||
if (kerning_value != 0)
|
||||
set_kerning(a.codepoint, b.codepoint, kerning_value);
|
||||
}
|
||||
|
|
|
@ -32,105 +32,44 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
Font::Font()
|
||||
FontRef Font::create(Stream& stream)
|
||||
{
|
||||
m_font = nullptr;
|
||||
m_data = nullptr;
|
||||
m_ascent = 0;
|
||||
m_descent = 0;
|
||||
m_line_gap = 0;
|
||||
m_valid = false;
|
||||
if (!stream.is_readable())
|
||||
{
|
||||
Log::error("Unable to load a font as the Stream was not readable");
|
||||
return FontRef();
|
||||
}
|
||||
|
||||
// read into buffer
|
||||
Vector<u8> buffer;
|
||||
buffer.reserve(stream.length());
|
||||
stream.read(buffer.data(), stream.length());
|
||||
|
||||
// init font
|
||||
auto stbtt = Ref<stbtt_fontinfo>(new stbtt_fontinfo());
|
||||
auto fn = (stbtt_fontinfo*)stbtt.get();
|
||||
if (stbtt_InitFont(fn, buffer.data(), 0) == 0)
|
||||
{
|
||||
Log::error("Unable to parse Font file");
|
||||
return false;
|
||||
}
|
||||
|
||||
// setup
|
||||
auto font = FontRef(new Font());
|
||||
font->m_font = stbtt;
|
||||
font->m_buffer = std::move(buffer);
|
||||
font->m_family_name = get_font_name(fn, 1);
|
||||
font->m_style_name = get_font_name(fn, 2);
|
||||
stbtt_GetFontVMetrics(fn, &font->m_ascent, &font->m_descent, &font->m_line_gap);
|
||||
return font;
|
||||
}
|
||||
|
||||
Font::Font(Stream& stream) : Font()
|
||||
{
|
||||
load(stream);
|
||||
}
|
||||
|
||||
Font::Font(const FilePath& path) : Font()
|
||||
FontRef Font::create(const FilePath& path)
|
||||
{
|
||||
FileStream fs(path, FileMode::OpenRead);
|
||||
if (fs.is_readable())
|
||||
load(fs);
|
||||
}
|
||||
|
||||
Font::Font(Font&& src) noexcept
|
||||
{
|
||||
m_font = src.m_font;
|
||||
m_data = src.m_data;
|
||||
m_family_name = src.m_family_name;
|
||||
m_style_name = src.m_style_name;
|
||||
m_ascent = src.m_ascent;
|
||||
m_descent = src.m_descent;
|
||||
m_line_gap = src.m_line_gap;
|
||||
m_valid = src.m_valid;
|
||||
|
||||
src.m_family_name.clear();
|
||||
src.m_style_name.clear();
|
||||
src.m_valid = false;
|
||||
src.m_font = nullptr;
|
||||
src.m_data = nullptr;
|
||||
}
|
||||
|
||||
Font& Font::operator=(Font&& src) noexcept
|
||||
{
|
||||
m_font = src.m_font;
|
||||
m_data = src.m_data;
|
||||
m_family_name = src.m_family_name;
|
||||
m_style_name = src.m_style_name;
|
||||
m_ascent = src.m_ascent;
|
||||
m_descent = src.m_descent;
|
||||
m_line_gap = src.m_line_gap;
|
||||
m_valid = src.m_valid;
|
||||
|
||||
src.m_family_name.clear();
|
||||
src.m_style_name.clear();
|
||||
src.m_valid = false;
|
||||
src.m_font = nullptr;
|
||||
src.m_data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Font::~Font()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void Font::load(Stream& stream)
|
||||
{
|
||||
dispose();
|
||||
|
||||
if (!stream.is_readable())
|
||||
{
|
||||
BLAH_ASSERT(false, "Unable to load a font as the Stream was not readable");
|
||||
return;
|
||||
}
|
||||
|
||||
// create data buffer
|
||||
auto size = stream.length();
|
||||
m_data = new unsigned char[size];
|
||||
stream.read(m_data, size);
|
||||
|
||||
// init font
|
||||
m_font = new stbtt_fontinfo();
|
||||
auto fn = (stbtt_fontinfo*)m_font;
|
||||
stbtt_InitFont(fn, m_data, 0);
|
||||
m_family_name = get_font_name(fn, 1);
|
||||
m_style_name = get_font_name(fn, 2);
|
||||
|
||||
// properties
|
||||
stbtt_GetFontVMetrics(fn, &m_ascent, &m_descent, &m_line_gap);
|
||||
m_valid = true;
|
||||
}
|
||||
|
||||
void Font::dispose()
|
||||
{
|
||||
delete (stbtt_fontinfo*)m_font;
|
||||
delete[] m_data;
|
||||
m_font = nullptr;
|
||||
m_data = nullptr;
|
||||
m_family_name.dispose();
|
||||
m_style_name.dispose();
|
||||
return create(fs);
|
||||
return FontRef();
|
||||
}
|
||||
|
||||
const String& Font::family_name() const
|
||||
|
@ -172,7 +111,7 @@ int Font::get_glyph(Codepoint codepoint) const
|
|||
{
|
||||
if (!m_font)
|
||||
return 0;
|
||||
return stbtt_FindGlyphIndex((stbtt_fontinfo*)m_font, codepoint);
|
||||
return stbtt_FindGlyphIndex((stbtt_fontinfo*)m_font.get(), codepoint);
|
||||
}
|
||||
|
||||
float Font::get_scale(float size) const
|
||||
|
@ -180,14 +119,14 @@ float Font::get_scale(float size) const
|
|||
if (!m_font)
|
||||
return 0;
|
||||
|
||||
return stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_font, size);
|
||||
return stbtt_ScaleForMappingEmToPixels((stbtt_fontinfo*)m_font.get(), size);
|
||||
}
|
||||
|
||||
float Font::get_kerning(int glyph1, int glyph2, float scale) const
|
||||
{
|
||||
if (!m_font)
|
||||
return 0;
|
||||
return stbtt_GetGlyphKernAdvance((stbtt_fontinfo*)m_font, glyph1, glyph2) * scale;
|
||||
return stbtt_GetGlyphKernAdvance((stbtt_fontinfo*)m_font.get(), glyph1, glyph2) * scale;
|
||||
}
|
||||
|
||||
Font::Character Font::get_character(int glyph, float scale) const
|
||||
|
@ -199,8 +138,8 @@ Font::Character Font::get_character(int glyph, float scale) const
|
|||
|
||||
int advance, offsetX, x0, y0, x1, y1;
|
||||
|
||||
stbtt_GetGlyphHMetrics((stbtt_fontinfo*)m_font, glyph, &advance, &offsetX);
|
||||
stbtt_GetGlyphBitmapBox((stbtt_fontinfo*)m_font, glyph, scale, scale, &x0, &y0, &x1, &y1);
|
||||
stbtt_GetGlyphHMetrics((stbtt_fontinfo*)m_font.get(), glyph, &advance, &offsetX);
|
||||
stbtt_GetGlyphBitmapBox((stbtt_fontinfo*)m_font.get(), glyph, scale, scale, &x0, &y0, &x1, &y1);
|
||||
|
||||
int w = (x1 - x0);
|
||||
int h = (y1 - y0);
|
||||
|
@ -213,7 +152,7 @@ Font::Character Font::get_character(int glyph, float scale) const
|
|||
ch.offset_x = offsetX * scale;
|
||||
ch.offset_y = (float)y0;
|
||||
ch.scale = scale;
|
||||
ch.has_glyph = (w > 0 && h > 0 && stbtt_IsGlyphEmpty((stbtt_fontinfo*)m_font, glyph) == 0);
|
||||
ch.has_glyph = (w > 0 && h > 0 && stbtt_IsGlyphEmpty((stbtt_fontinfo*)m_font.get(), glyph) == 0);
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
@ -225,7 +164,7 @@ bool Font::get_image(const Font::Character& ch, Color* pixels) const
|
|||
// we actually use the image buffer as our temporary buffer, and fill the pixels out backwards after
|
||||
// kinda weird but it works & saves creating more memory
|
||||
auto* src = (unsigned char*)pixels;
|
||||
stbtt_MakeGlyphBitmap((stbtt_fontinfo*)m_font, src, ch.width, ch.height, ch.width, ch.scale, ch.scale, ch.glyph);
|
||||
stbtt_MakeGlyphBitmap((stbtt_fontinfo*)m_font.get(), src, ch.width, ch.height, ch.width, ch.scale, ch.scale, ch.glyph);
|
||||
|
||||
int len = ch.width * ch.height;
|
||||
for (int a = (len - 1) * 4, b = (len - 1); b >= 0; a -= 4, b -= 1)
|
||||
|
@ -250,9 +189,4 @@ Image Font::get_image(const Font::Character& ch) const
|
|||
return img;
|
||||
|
||||
return Image();
|
||||
}
|
||||
|
||||
bool Font::is_valid() const
|
||||
{
|
||||
return m_valid;
|
||||
}
|
|
@ -11,36 +11,6 @@ Packer::Packer()
|
|||
Packer::Packer(int max_size, int spacing, bool power_of_two)
|
||||
: max_size(max_size), power_of_two(power_of_two), spacing(spacing), padding(1), m_dirty(false) { }
|
||||
|
||||
Packer::Packer(Packer&& src) noexcept
|
||||
{
|
||||
max_size = src.max_size;
|
||||
power_of_two = src.power_of_two;
|
||||
spacing = src.spacing;
|
||||
padding = src.padding;
|
||||
m_dirty = src.m_dirty;
|
||||
pages = std::move(src.pages);
|
||||
m_entries = std::move(src.m_entries);
|
||||
m_buffer = std::move(src.m_buffer);
|
||||
}
|
||||
|
||||
Packer& Packer::operator=(Packer&& src) noexcept
|
||||
{
|
||||
max_size = src.max_size;
|
||||
power_of_two = src.power_of_two;
|
||||
spacing = src.spacing;
|
||||
padding = src.padding;
|
||||
m_dirty = src.m_dirty;
|
||||
pages = std::move(src.pages);
|
||||
m_entries = std::move(src.m_entries);
|
||||
m_buffer = std::move(src.m_buffer);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packer::~Packer()
|
||||
{
|
||||
dispose();
|
||||
}
|
||||
|
||||
void Packer::add(u64 id, int width, int height, const Color* pixels)
|
||||
{
|
||||
add_entry(id, width, height, pixels, Recti(0, 0, width, height));
|
||||
|
@ -308,17 +278,7 @@ void Packer::clear()
|
|||
{
|
||||
pages.clear();
|
||||
m_entries.clear();
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
void Packer::dispose()
|
||||
{
|
||||
pages.clear();
|
||||
m_entries.clear();
|
||||
m_buffer.close();
|
||||
max_size = 0;
|
||||
power_of_two = 0;
|
||||
spacing = 0;
|
||||
m_buffer.clear();
|
||||
m_dirty = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,51 +3,14 @@
|
|||
|
||||
using namespace Blah;
|
||||
|
||||
BufferStream::BufferStream()
|
||||
: m_buffer(nullptr), m_capacity(0), m_length(0), m_position(0) {}
|
||||
|
||||
BufferStream::BufferStream(int capacity)
|
||||
: m_buffer(nullptr), m_capacity(0), m_length(0), m_position(0)
|
||||
{
|
||||
if (capacity > 0)
|
||||
{
|
||||
m_buffer = new char[capacity];
|
||||
m_capacity = capacity;
|
||||
}
|
||||
}
|
||||
|
||||
BufferStream::BufferStream(BufferStream&& src) noexcept
|
||||
{
|
||||
m_buffer = src.m_buffer;
|
||||
m_length = src.m_length;
|
||||
m_capacity = src.m_capacity;
|
||||
m_position = src.m_position;
|
||||
src.m_buffer = nullptr;
|
||||
src.m_position = src.m_length = src.m_capacity = 0;
|
||||
}
|
||||
|
||||
BufferStream& BufferStream::operator=(BufferStream&& src) noexcept
|
||||
{
|
||||
close();
|
||||
|
||||
m_buffer = src.m_buffer;
|
||||
m_length = src.m_length;
|
||||
m_capacity = src.m_capacity;
|
||||
m_position = src.m_position;
|
||||
src.m_buffer = nullptr;
|
||||
src.m_position = src.m_length = src.m_capacity = 0;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BufferStream::~BufferStream()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
m_buffer.resize(capacity);
|
||||
}
|
||||
|
||||
size_t BufferStream::length() const
|
||||
{
|
||||
return m_length;
|
||||
return m_buffer.size();
|
||||
}
|
||||
|
||||
size_t BufferStream::position() const
|
||||
|
@ -55,23 +18,20 @@ size_t BufferStream::position() const
|
|||
return m_position;
|
||||
}
|
||||
|
||||
size_t BufferStream::seek(size_t seekTo)
|
||||
size_t BufferStream::seek(size_t seek_to)
|
||||
{
|
||||
return m_position = (seekTo < 0 ? 0 : (seekTo > m_length ? m_length : seekTo));
|
||||
return m_position = (seek_to < 0 ? 0 : (seek_to > m_buffer.size() ? m_buffer.size() : seek_to));
|
||||
}
|
||||
|
||||
size_t BufferStream::read_data(void* ptr, size_t len)
|
||||
{
|
||||
if (m_buffer == nullptr || ptr == nullptr)
|
||||
if (ptr == nullptr || len <= 0)
|
||||
return 0;
|
||||
|
||||
if (len < 0)
|
||||
return 0;
|
||||
if (len > m_buffer.size() - m_position)
|
||||
len = m_buffer.size() - m_position;
|
||||
|
||||
if (len > m_length - m_position)
|
||||
len = m_length - m_position;
|
||||
|
||||
memcpy(ptr, m_buffer + m_position, (size_t)len);
|
||||
memcpy(ptr, m_buffer.data() + m_position, (size_t)len);
|
||||
m_position += len;
|
||||
return len;
|
||||
}
|
||||
|
@ -82,12 +42,12 @@ size_t BufferStream::write_data(const void* ptr, size_t len)
|
|||
return 0;
|
||||
|
||||
// resize
|
||||
if (m_position + len > m_length)
|
||||
if (m_position + len > m_buffer.size())
|
||||
resize(m_position + len);
|
||||
|
||||
// copy data
|
||||
if (ptr != nullptr)
|
||||
memcpy(m_buffer + m_position, ptr, (size_t)len);
|
||||
memcpy(m_buffer.data() + m_position, ptr, (size_t)len);
|
||||
|
||||
// increment position
|
||||
m_position += len;
|
||||
|
@ -96,70 +56,27 @@ size_t BufferStream::write_data(const void* ptr, size_t len)
|
|||
return len;
|
||||
}
|
||||
|
||||
bool BufferStream::is_open() const
|
||||
{
|
||||
return m_buffer != nullptr;
|
||||
}
|
||||
|
||||
bool BufferStream::is_readable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BufferStream::is_writable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool BufferStream::is_open() const { return true; }
|
||||
bool BufferStream::is_readable() const { return true; }
|
||||
bool BufferStream::is_writable() const { return true; }
|
||||
|
||||
void BufferStream::resize(size_t length)
|
||||
{
|
||||
if (m_capacity > length)
|
||||
{
|
||||
m_length = length;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto last_capacity = m_capacity;
|
||||
|
||||
if (m_capacity <= 0)
|
||||
m_capacity = 16;
|
||||
while (length >= m_capacity)
|
||||
m_capacity *= 2;
|
||||
|
||||
char* new_buffer = new char[m_capacity];
|
||||
|
||||
if (m_buffer != nullptr)
|
||||
{
|
||||
memcpy(new_buffer, m_buffer, last_capacity);
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
m_buffer = new_buffer;
|
||||
}
|
||||
|
||||
m_length = length;
|
||||
}
|
||||
|
||||
void BufferStream::close()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
m_buffer = nullptr;
|
||||
m_position = 0;
|
||||
m_length = 0;
|
||||
m_capacity = 0;
|
||||
m_buffer.resize(length);
|
||||
}
|
||||
|
||||
void BufferStream::clear()
|
||||
{
|
||||
m_length = m_position = 0;
|
||||
m_buffer.clear();
|
||||
m_position = 0;
|
||||
}
|
||||
|
||||
char* BufferStream::data()
|
||||
u8* BufferStream::data()
|
||||
{
|
||||
return m_buffer;
|
||||
return m_buffer.data();
|
||||
}
|
||||
|
||||
const char* BufferStream::data() const
|
||||
const u8* BufferStream::data() const
|
||||
{
|
||||
return m_buffer;
|
||||
return m_buffer.data();
|
||||
}
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
|
||||
using namespace Blah;
|
||||
|
||||
FileStream::FileStream()
|
||||
{
|
||||
m_mode = FileMode::OpenRead;
|
||||
}
|
||||
|
||||
FileStream::FileStream(const FilePath& path, FileMode mode)
|
||||
: m_mode(mode)
|
||||
, m_file(File::open(path, mode))
|
||||
|
@ -58,8 +53,6 @@ size_t FileStream::read_data(void* ptr, size_t length)
|
|||
|
||||
if (m_file)
|
||||
return m_file->read((unsigned char*)ptr, length);
|
||||
|
||||
BLAH_ASSERT(false, "Unable to read from Stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -70,8 +63,6 @@ size_t FileStream::write_data(const void* ptr, size_t length)
|
|||
|
||||
if (m_file)
|
||||
return m_file->write((const unsigned char*)ptr, length);
|
||||
|
||||
BLAH_ASSERT(false, "Unable to write to Stream");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -88,9 +79,4 @@ bool FileStream::is_readable() const
|
|||
bool FileStream::is_writable() const
|
||||
{
|
||||
return m_file.get() && (m_mode != FileMode::OpenRead);
|
||||
}
|
||||
|
||||
void FileStream::close()
|
||||
{
|
||||
m_file.reset();
|
||||
}
|
|
@ -3,30 +3,11 @@
|
|||
|
||||
using namespace Blah;
|
||||
|
||||
MemoryStream::MemoryStream()
|
||||
: m_data(nullptr), m_length(0), m_position(0) {}
|
||||
MemoryStream::MemoryStream(u8* data, size_t length)
|
||||
: m_data(data), m_const_data(nullptr), m_length(length), m_position(0) {}
|
||||
|
||||
MemoryStream::MemoryStream(unsigned char* data, size_t length)
|
||||
: m_data(data), m_length(length), m_position(0) {}
|
||||
|
||||
MemoryStream::MemoryStream(MemoryStream&& src) noexcept
|
||||
{
|
||||
m_data = src.m_data;
|
||||
m_position = src.m_position;
|
||||
m_length = src.m_length;
|
||||
src.m_data = nullptr;
|
||||
src.m_length = src.m_position = 0;
|
||||
}
|
||||
|
||||
MemoryStream& MemoryStream::operator=(MemoryStream&& src) noexcept
|
||||
{
|
||||
m_data = src.m_data;
|
||||
m_position = src.m_position;
|
||||
m_length = src.m_length;
|
||||
src.m_data = nullptr;
|
||||
src.m_length = src.m_position = 0;
|
||||
return *this;
|
||||
}
|
||||
MemoryStream::MemoryStream(const u8* data, size_t length)
|
||||
: m_data(nullptr), m_const_data(data), m_length(length), m_position(0) {}
|
||||
|
||||
size_t MemoryStream::length() const
|
||||
{
|
||||
|
@ -38,63 +19,60 @@ size_t MemoryStream::position() const
|
|||
return m_position;
|
||||
}
|
||||
|
||||
size_t MemoryStream::seek(size_t seekTo)
|
||||
size_t MemoryStream::seek(size_t seek_to)
|
||||
{
|
||||
return m_position = (seekTo < 0 ? 0 : (seekTo > m_length ? m_length : seekTo));
|
||||
return m_position = (seek_to < 0 ? 0 : (seek_to > m_length ? m_length : seek_to));
|
||||
}
|
||||
|
||||
size_t MemoryStream::read_data(void* ptr, size_t len)
|
||||
{
|
||||
if (len < 0 || ptr == nullptr)
|
||||
const u8* src = (m_data ? m_data : m_const_data);
|
||||
|
||||
if (src == nullptr || ptr == nullptr || len <= 0 || m_length <= 0 || m_position >= m_length)
|
||||
return 0;
|
||||
|
||||
if (len > m_length - m_position)
|
||||
len = m_length - m_position;
|
||||
|
||||
memcpy(ptr, m_data + m_position, (size_t)len);
|
||||
memcpy(ptr, src + m_position, len);
|
||||
m_position += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t MemoryStream::write_data(const void* ptr, size_t len)
|
||||
{
|
||||
if (len < 0 || ptr == nullptr)
|
||||
if (m_data == nullptr || ptr == nullptr || len <= 0 || m_length <= 0 || m_position >= m_length)
|
||||
return 0;
|
||||
|
||||
if (len > m_length - m_position)
|
||||
len = m_length - m_position;
|
||||
|
||||
memcpy(m_data + m_position, ptr, (size_t)len);
|
||||
memcpy(m_data + m_position, ptr, len);
|
||||
m_position += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
bool MemoryStream::is_open() const
|
||||
{
|
||||
return m_data != nullptr;
|
||||
return (m_data || m_const_data) && m_length > 0;
|
||||
}
|
||||
|
||||
bool MemoryStream::is_readable() const
|
||||
{
|
||||
return true;
|
||||
return (m_data || m_const_data) && m_length > 0;
|
||||
}
|
||||
|
||||
bool MemoryStream::is_writable() const
|
||||
{
|
||||
return true;
|
||||
return m_data != nullptr && m_length > 0;
|
||||
}
|
||||
|
||||
void MemoryStream::close()
|
||||
{
|
||||
m_data = nullptr; m_length = m_position = 0;
|
||||
}
|
||||
|
||||
unsigned char* MemoryStream::data()
|
||||
u8* MemoryStream::data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const unsigned char* MemoryStream::data() const
|
||||
const u8* MemoryStream::data() const
|
||||
{
|
||||
return m_data;
|
||||
return (m_data ? m_data : m_const_data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user