Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement BMFont and Image Rasterizers #209

Merged
merged 6 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,4 @@ test
*.wuhb

*.zip
debug.py
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ if(NINTENDO_3DS)
ROMFS ${PROJECT_NAME}_ctr_romfs
)

set(APP_LIBS citro2d citro3d)
set(APP_LIBS citro3d)

add_custom_target(dist COMMAND
${CMAKE_COMMAND} -E tar "cfv" "${PROJECT_NAME}-3ds-${COMMIT_HASH}.zip" --format=zip
Expand Down Expand Up @@ -393,6 +393,8 @@ target_sources(${PROJECT_NAME} PRIVATE
source/modules/window/wrap_window.cpp
source/objects/beziercurve/beziercurve.cpp
source/objects/beziercurve/wrap_beziercurve.cpp
source/objects/bmfontrasterizer/bmfontrasterizer.cpp
source/objects/imagerasterizer/imagerasterizer.cpp
source/objects/channel/channel.cpp
source/objects/channel/wrap_channel.cpp
source/objects/compressedimagedata/compressedimagedata.cpp
Expand Down
17 changes: 17 additions & 0 deletions include/common/color.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,20 @@ struct Color
return (uint8_t)(255.0f * std::clamp(in, 0.0f, 1.0f) + 0.5f);
}
};

struct Color32
{
public:
Color32() : r(0), g(0), b(0), a(0)
{}

Color32(uint8_t r, uint8_t g, uint8_t b, uint8_t a) : r(r), g(g), b(b), a(a)
{}

constexpr std::strong_ordering operator<=>(const Color32&) const noexcept = default;

uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
};
14 changes: 14 additions & 0 deletions include/modules/font/fontmodule.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

#include <objects/truetyperasterizer/truetyperasterizer.tcc>

#include <objects/imagedata/imagedata.tcc>

#include <objects/data/filedata/filedata.hpp>

#include <memory>
Expand All @@ -34,6 +36,18 @@ namespace love
return "love.font";
}

Rasterizer* NewBMFontRasterizer(FileData* data,
const std::vector<ImageData<Console::Which>*>& images,
float dpiScale) const;

virtual Rasterizer* NewImageRasterizer(ImageData<Console::Which>* data,
const std::string& text, int extraSpacing,
float dpiScale) const = 0;

virtual Rasterizer* NewImageRasterizer(ImageData<Console::Which>* data, uint32_t* glyphs,
int glyphCount, int extraSpacing,
float dpiScale) const = 0;

Rasterizer* NewTrueTypeRasterizer(int size, TrueTypeRasterizer<>::Hinting hinting) const;

Rasterizer* NewTrueTypeRasterizer(int size, float dpiScale,
Expand Down
4 changes: 4 additions & 0 deletions include/modules/font/wrap_fontmodule.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ namespace Wrap_FontModule

int NewTrueTypeRasterizer(lua_State* L);

int NewBMFontRasterizer(lua_State* L);

int NewImageRasterizer(lua_State* L);

int Register(lua_State* L);

extern std::span<const luaL_Reg> extensions;
Expand Down
65 changes: 65 additions & 0 deletions include/objects/bmfontrasterizer/bmfontrasterizer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#pragma once

#include <objects/imagedata/imagedata.tcc>

#include <objects/rasterizer/rasterizer.hpp>

#include <unordered_map>
#include <vector>

namespace love
{
class BMFontRasterizer : public Rasterizer
{
public:
BMFontRasterizer(FileData* fontDefinition,
const std::vector<ImageData<Console::Which>*>& imageList, float dpiScale);

virtual ~BMFontRasterizer()
{}

int GetLineHeight() const override;

int GetGlyphSpacing(uint32_t glyph) const override;

int GetGlyphIndex(uint32_t glyph) const override;

GlyphData* GetGlyphDataForIndex(int index) const override;

int GetGlyphCount() const override;

bool HasGlyph(uint32_t glyph) const override;

float GetKerning(uint32_t left, uint32_t right) const override;

DataType GetDataType() const override;

TextShaper* NewTextShaper() override;

static bool Accepts(FileData* fontDefinition);

private:
struct BMFontCharacter
{
int x;
int y;
int page;
GlyphData::GlyphMetrics metrics;
uint32_t glyph;
};

void ParseConfig(const std::string& config);

std::string fontFolder;
std::unordered_map<int, StrongReference<ImageData<Console::Which>>> images;

std::vector<BMFontCharacter> characters;

std::unordered_map<uint64_t, int> characterIndices;
std::unordered_map<uint64_t, int> kernings;

int fontSize;
bool unicode;
int lineHeight;
};
} // namespace love
2 changes: 1 addition & 1 deletion include/objects/imagedata/imagedata.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ namespace love
}
}

love::mutex& GetMutex()
love::mutex& GetMutex() const
{
return this->mutex;
}
Expand Down
57 changes: 57 additions & 0 deletions include/objects/imagerasterizer/imagerasterizer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include <common/color.hpp>

#include <objects/imagedata/imagedata.tcc>
#include <objects/rasterizer/rasterizer.hpp>

#include <map>

namespace love
{
class ImageRasterizer : public Rasterizer
{
public:
ImageRasterizer(ImageData<Console::Which>* data, const uint32_t* glyphs, int glyphCount,
int extraSpacing, float dpiScale);

virtual ~ImageRasterizer()
{}

int GetLineHeight() const override;

int GetGlyphSpacing(uint32_t glyph) const override;

int GetGlyphIndex(uint32_t glyph) const override;

GlyphData* GetGlyphDataForIndex(int index) const override;

int GetGlyphCount() const override;

bool HasGlyph(uint32_t glyph) const override;

DataType GetDataType() const override;

TextShaper* NewTextShaper() override;

private:
struct ImageGlyphData
{
int x;
int width;
uint32_t glyph;
};

void Load(const uint32_t* glyphs, int glyphCount);

StrongReference<ImageData<Console::Which>> imageData;

int glyphCount;
int extraSpacing;

std::vector<ImageGlyphData> imageGlyphs;
std::map<uint32_t, int> glyphIndicies;

Color32 spacer;
};
} // namespace love
8 changes: 6 additions & 2 deletions platform/cafe/include/modules/fontmodule_ext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ namespace love

using FontModule<Console::ALL>::NewTrueTypeRasterizer;

Rasterizer* NewTrueTypeRasterizer(int size, TrueTypeRasterizer<>::Hinting hinting,
OSSharedDataType type) const;
Rasterizer* NewImageRasterizer(ImageData<Console::Which>* data, const std::string& text,
int extraSpacing, float dpiScale) const override;

Rasterizer* NewImageRasterizer(ImageData<Console::Which>* data, uint32_t* glyphs,
int glyphCount, int extraSpacing,
float dpiScale) const override;

Rasterizer* NewTrueTypeRasterizer(Data* data, int size,
TrueTypeRasterizer<>::Hinting hinting) const override;
Expand Down
43 changes: 35 additions & 8 deletions platform/cafe/source/modules/fontmodule_ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,57 @@

#include <modules/fontmodule_ext.hpp>

#include <objects/bmfontrasterizer/bmfontrasterizer.hpp>
#include <objects/imagerasterizer/imagerasterizer.hpp>

using namespace love;

FontModule<Console::CAFE>::FontModule() : FontModule<Console::ALL>()
{
this->defaultFontData.Set(new SystemFont(), Acquire::NORETAIN);
}

Rasterizer* FontModule<Console::CAFE>::NewImageRasterizer(ImageData<Console::Which>* data,
const std::string& text, int extraSpacing,
float dpiScale) const
{
std::vector<uint32_t> glyphs {};
glyphs.reserve(text.size());

try
{
utf8::iterator<std::string::const_iterator> it(text.begin(), text.begin(), text.end());
utf8::iterator<std::string::const_iterator> end(text.end(), text.begin(), text.end());

while (it != end)
glyphs.push_back(*it++);
}
catch (utf8::exception& e)
{
throw love::Exception("UTF-8 decoding error: %s", e.what());
}

return this->NewImageRasterizer(data, &glyphs[0], (int)glyphs.size(), extraSpacing, dpiScale);
}

Rasterizer* FontModule<Console::CAFE>::NewImageRasterizer(ImageData<Console::Which>* data,
uint32_t* glyphs, int glyphCount,
int extraSpacing, float dpiScale) const
{
return new ImageRasterizer(data, glyphs, glyphCount, extraSpacing, dpiScale);
}

Rasterizer* FontModule<Console::CAFE>::NewRasterizer(FileData* data) const
{
if (TrueTypeRasterizer<Console::CAFE>::Accepts(this->library, data))
return this->NewTrueTypeRasterizer(data, 12, TrueTypeRasterizer<>::HINTING_NORMAL);
else if (BMFontRasterizer::Accepts(data))
return this->NewBMFontRasterizer(data, {}, 1.0f);

throw love::Exception("Invalid font file: %s", data->GetFilename().c_str());
return nullptr;
}

Rasterizer* FontModule<Console::CAFE>::NewTrueTypeRasterizer(int size,
TrueTypeRasterizer<>::Hinting hinting,
OSSharedDataType type) const
{
StrongReference<SystemFont> data(new SystemFont(type), Acquire::NORETAIN);
return this->NewTrueTypeRasterizer(data.Get(), size, hinting);
}

Rasterizer* FontModule<Console::CAFE>::NewTrueTypeRasterizer(
Data* data, int size, TrueTypeRasterizer<>::Hinting hinting) const
{
Expand Down
Loading