This commit is contained in:
2023-06-05 11:49:38 -07:00
parent bbd442b191
commit 3ca30721b6
12 changed files with 405 additions and 210 deletions

View File

@ -53,16 +53,17 @@ namespace Dawn {
};
#pragma pack(pop)
#define COLOR_WHITE { 1.0f, 1.0f, 1.0f, 1.0f }
#define COLOR_RED { 1.0f, 0, 0, 1.0f }
#define COLOR_GREEN { 0, 1.0f, 0, 1.0f }
#define COLOR_BLUE { 0, 0, 1.0f, 1.0f }
#define COLOR_BLACK { 0, 0, 0, 1.0f }
#define COLOR_MAGENTA { 1.0f, 0, 1.0f, 1.0f }
#define COLOR_DARK_GREY { 0.19607843137254901961f, 0.19607843137254901961f, 0.19607843137254901961f, 1.0f }
#define COLOR_LIGHT_GREY { 0.8f, 0.8f, 0.8f, 1.0f }
#define COLOR_CORNFLOWER_BLUE { 0.39215686274509803922f, 0.58431372549019607843f, 0.92941176470588235294f, 1.0f }
#define COLOR_WHITE_TRANSPARENT { 1.0f, 1.0f, 1.0f, 0 }
#define COLOR_BLACK_TRANSPARENT { 0, 0, 0, 0 }
#define COLOR_TRANSPARENT COLOR_BLACK_TRANSPARENT
#define COLOR_DEF(r,g,b,a) { r, g, b, a }
#define COLOR_WHITE COLOR_DEF(1.0f, 1.0f, 1.0f, 1.0f)
#define COLOR_RED COLOR_DEF(1.0f, 0, 0, 1.0f)
#define COLOR_GREEN COLOR_DEF(0, 1.0f, 0, 1.0f)
#define COLOR_BLUE COLOR_DEF(0, 0, 1.0f, 1.0f)
#define COLOR_BLACK COLOR_DEF(0, 0, 0, 1.0f)
#define COLOR_MAGENTA COLOR_DEF(1.0f, 0, 1.0f, 1.0f)
#define COLOR_DARK_GREY COLOR_DEF(0.2f, 0.2f, 0.2f, 1.0f)
#define COLOR_LIGHT_GREY COLOR_DEF(0.8f, 0.8f, 0.8f, 1.0f)
#define COLOR_CORNFLOWER_BLUE COLOR_DEF(0.4f, 0.6f, 0.9f, 1.0f)
#define COLOR_WHITE_TRANSPARENT COLOR_DEF(1.0f, 1.0f, 1.0f, 0.0f)
#define COLOR_BLACK_TRANSPARENT COLOR_DEF(0.0f, 0.0f, 0.0f, 0.0f)
#define COLOR_TRANSPARENT COLOR_BLACK_TRANSPARENT
}

View File

@ -7,9 +7,18 @@
using namespace Dawn;
FontManager::FontManager() {
}
void FontManager::init() {
// Init FreeType
if(FT_Init_FreeType(&fontLibrary)) {
std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
assertUnreachable();
}
}
FontManager::~FontManager() {
}

View File

@ -14,6 +14,10 @@ namespace Dawn {
public:
FT_Library fontLibrary;
FontManager();
void init();
~FontManager();
};
}

View File

@ -7,17 +7,30 @@
using namespace Dawn;
void Dawn::_newTrueTypePlaceholder(
FT_Face face,
Texture &texture,
std::map<FT_ULong, struct TrueTypeCharacterInfo> &charStore
NewTrueTypeFaceTexture::NewTrueTypeFaceTexture(
NewTrueTypeFace *trueTypeFace,
FT_Face &face,
struct NewTrueTypeFaceTextureStyle style
) {
assertNotNull(trueTypeFace);
assertTrue(this->style.fontSize < 256);
this->trueTypeFace = trueTypeFace;
this->face = &face;
this->style = style;
// Set freetype font size prior to baking.
if(FT_Set_Pixel_Sizes(face, 0, this->style.fontSize)) {
assertUnreachable();
}
size_t w = 0, h = 0;
FT_ULong c;
// First pass, determine the textures' dimensions.
for(c = NEW_TRUETYPE_CHAR_BEGIN; c < NEW_TRUETYPE_CHAR_END; c++) {
// Load the character
if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
if(FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME)) {
assertUnreachable();
}
@ -26,16 +39,18 @@ void Dawn::_newTrueTypePlaceholder(
h += face->glyph->bitmap.rows;
}
assertTrue(w > 0);
assertTrue(h > 0);
// Now buffer pixels to the texture
float_t y = 0;
// I'd love to just buffer straight to the GPU, but it seems that is a bit
// unstable right now.
uint8_t *buffer = (uint8_t *)memoryAllocate(w * h * sizeof(uint8_t));
memorySet(buffer, 0x00, sizeof(uint8_t) * w * h);
uint8_t *buffer = (uint8_t *)memoryFillWithZero(w * h * sizeof(uint8_t));
size_t offset = 0;
struct NewTrueTypeCharacter info;
for(c = NEW_TRUETYPE_CHAR_BEGIN; c < NEW_TRUETYPE_CHAR_END; c++) {
// Load the character
if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
@ -43,26 +58,51 @@ void Dawn::_newTrueTypePlaceholder(
}
// Store the character information
struct TrueTypeCharacterInfo info;
info.advance = glm::vec2(face->glyph->advance.x, face->glyph->advance.y);
info.advanceX = face->glyph->advance.x;
info.advanceY = face->glyph->advance.y;
info.bitmapSize = glm::vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows);
info.bitmapPosition = glm::vec2(face->glyph->bitmap_left, face->glyph->bitmap_top);
info.bitmapPosition = glm::vec2(face->glyph->bitmap_left, -face->glyph->bitmap_top);
info.textureY = y;
charStore[c] = info;
this->characterData[c] = info;
// Buffer the pixels, oh dear GOD there has to be a more efficient way.
for(uint32_t i = 0; i < face->glyph->bitmap.rows; i++) {
for(int32_t i = 0; i < face->glyph->bitmap.rows; i++) {
memoryCopy(
(void *)(face->glyph->bitmap.buffer + (i * face->glyph->bitmap.width)),
(void *)(buffer + offset),
face->glyph->bitmap.width * sizeof(uint8_t)
);
offset += w * sizeof(uint8_t);
assertTrue(offset <= (w * h * sizeof(uint8_t)));
}
y += face->glyph->bitmap.rows;
}
texture.setSize(w, h, TEXTURE_FORMAT_R);
texture.buffer(buffer);
this->texture.setSize(w, h, TEXTURE_FORMAT_R);
this->texture.buffer(buffer);
memoryFree(buffer);
}
struct NewTrueTypeCharacter NewTrueTypeFaceTexture::getCharacterData(FT_ULong c) {
return this->characterData[c];
}
NewTrueTypeFace::NewTrueTypeFace(FT_Face *face) {
assertNotNull(face);
this->face = face;
}
usagelockid_t NewTrueTypeFace::lock(struct NewTrueTypeFaceTextureStyle style) {
}
NewTrueTypeFace::~NewTrueTypeFace() {
auto it = this->textures.begin();
while(it != this->textures.end()) {
delete *it;
it = this->textures.erase(it);
}
}

View File

@ -6,22 +6,90 @@
#pragma once
#include "dawnlibs.hpp"
#include "util/mathutils.hpp"
#include "util/flag.hpp"
#include "display/Texture.hpp"
#include "util/UsageLock.hpp"
#define NEW_TRUETYPE_CHAR_BEGIN 0x00
#define NEW_TRUETYPE_CHAR_END 0xFF
#define NEW_TRUETYPE_CHAR_BEGIN 32
#define NEW_TRUETYPE_CHAR_END 192
#define NEW_TRUETYPE_VARIANT_BOLD FLAG_DEFINE(0)
#define NEW_TRUETYPE_VARIANT_ITALICS FLAG_DEFINE(1)
namespace Dawn {
struct TrueTypeCharacterInfo {
glm::vec2 advance;
class NewTrueTypeFace;
typedef uint32_t newtruetypelock_t;
struct NewTrueTypeCharacter {
int32_t advanceX;
int32_t advanceY;
glm::vec2 bitmapSize;
glm::vec2 bitmapPosition;
float_t textureY;
};
void _newTrueTypePlaceholder(
FT_Face face,
Texture &texture,
std::map<FT_ULong, struct TrueTypeCharacterInfo> &charStore
);
struct NewTrueTypeFaceTextureStyle {
uint32_t fontSize;
flag_t style;
};
class NewTrueTypeFaceTexture {
protected:
FT_Face *face;
NewTrueTypeFace *trueTypeFace;
std::map<FT_ULong, struct NewTrueTypeCharacter> characterData;
struct NewTrueTypeFaceTextureStyle style;
UsageLock locks;
public:
Texture texture;
/**
* Construct a new New True Type Face Texture object
*
* @param trueTypeFace Face that this texture belongs to.
* @param face The freetype face object.
* @param style Style that this font has, used for locking.
*/
NewTrueTypeFaceTexture(
NewTrueTypeFace *trueTypeFace,
FT_Face &face,
struct NewTrueTypeFaceTextureStyle style
);
/**
* Returns the character data for the given character.
*
* @param c Character to get data for.
* @return The Character data for the given character.
*/
struct NewTrueTypeCharacter getCharacterData(FT_ULong c);
/**
* Destroys this true type face texture.
*/
~NewTrueTypeFaceTexture();
friend class NewTrueTypeFace;
};
class NewTrueTypeFace {
protected:
std::vector<NewTrueTypeFaceTexture*> textures;
FT_Face *face;
std::map<struct NewTrueTypeFaceTextureStyle, NewTrueTypeFaceTexture*> texturesByStyle;
std::map<struct NewTrueTypeFaceTextureStyle, std::vector<usagelockid_t>> locksByStyle;
public:
NewTrueTypeFace(FT_Face *face);
usagelockid_t lock(struct NewTrueTypeFaceTextureStyle style);
void unlock(usagelockid_t lock);
NewTrueTypeFaceTexture * getTexture(usagelockid_t lock);
~NewTrueTypeFace();
};
}

View File

@ -8,7 +8,125 @@
using namespace Dawn;
void _uiLabelBake(
UILabelNew::UILabelNew(SceneItem *item) : UIComponentRenderable(item) {
}
void UILabelNew::onStart() {
this->shaderBuffer.init();
if(FT_New_Face(
getGame()->renderManager.getFontManager()->fontLibrary,
"/usr/share/fonts/TTF/arial.ttf",
// "C:\\Windows\\Fonts\\arial.ttf",
0,
&face
)) {
assertUnreachable();
}
UILabelNew::bakeTexture(defFace, face, 32);
if(FT_New_Face(
getGame()->renderManager.getFontManager()->fontLibrary,
"/usr/share/fonts/TTF/arialbd.ttf",
// "C:\\Windows\\Fonts\\arialbd.ttf",
0,
&faceBold
)) {
assertUnreachable();
}
UILabelNew::bakeTexture(defFaceBold, faceBold, 32);
if(FT_New_Face(
getGame()->renderManager.getFontManager()->fontLibrary,
"/usr/share/fonts/TTF/ariali.ttf",
// "C:\\Windows\\Fonts\\ariali.ttf",
0,
&faceItalics
)) {
assertUnreachable();
}
UILabelNew::bakeTexture(defFaceItalics, faceItalics, 32);
struct FontShaderBufferData fontData;
glm::vec2 position = glm::vec2(32, 32);
mesh.createBuffers(QUAD_VERTICE_COUNT * 128, QUAD_INDICE_COUNT * 128);
auto x = UILabelNew::bufferQuads(
"Hello ",
fontData,
defFace,
position,
0,
0
);
x += UILabelNew::bufferQuads(
" World",
fontData,
defFaceItalics,
position,
x,
1
);
x += UILabelNew::bufferQuads(
" How are you?",
fontData,
defFaceBold,
position,
x,
2
);
fontData.colors[0] = COLOR_MAGENTA;
fontData.textures[0] = 0;
fontData.colors[1] = COLOR_RED;
fontData.textures[1] = 1;
fontData.colors[2] = COLOR_GREEN;
fontData.textures[2] = 2;
shaderBuffer.buffer(&fontData);
}
std::vector<struct ShaderPassItem> UILabelNew::getUIRenderPasses() {
auto canvas = this->getCanvas();
auto shader = getGame()->renderManager.fontShader;
struct ShaderPassItem item;
item.shader = shader;
item.mesh = &this->mesh;
item.matrixValues[shader->paramModel] = transform->getWorldTransform();
item.parameterBuffers[shader->bufferUiCanvas] = &canvas->shaderBuffer;
item.parameterBuffers[shader->bufferFont] = &this->shaderBuffer;
item.renderFlags = RENDER_MANAGER_RENDER_FLAG_BLEND;
item.textureSlots[0] = &defFace.texture;
item.textureSlots[1] = &defFaceItalics.texture;
item.textureSlots[2] = &defFaceBold.texture;
item.textureValues[shader->paramTexture0] = 0;
item.textureValues[shader->paramTexture1] = 1;
item.textureValues[shader->paramTexture2] = 2;
return { item };
}
float_t UILabelNew::getWidth() {
return 0;
}
float_t UILabelNew::getHeight() {
return 0;
}
float_t UILabelNew::getContentWidth() {
return 0;
}
float_t UILabelNew::getContentHeight() {
return 0;
}
void UILabelNew::bakeTexture(
struct UILabelFontDef &fontDef,
FT_Face &face,
uint32_t fontSize
@ -78,155 +196,45 @@ void _uiLabelBake(
memoryFree(buffer);
}
int32_t _uiLabelQuad(
int32_t UILabelNew::bufferQuads(
std::string text,
Mesh *mesh,
struct FontShaderBufferData &bufferData,
struct UILabelFontDef &fontDef,
glm::vec2 &position,
int32_t quadStart,
int32_t partIndex
) {
// Get string length
int32_t len = text.length();
if(mesh == nullptr) return len;
// Loop each char
glm::vec2 wh = glm::vec2(fontDef.texture.getWidth(), fontDef.texture.getHeight());
// For each char
for(int32_t i = 0; i < len; i++) {
char ch = text[i];
int32_t j = quadStart + i;
FT_ULong c = text[i];
FT_ULong c = ch;
auto &charInfo = fontDef.charStore[c];
// Determine texture coordinates.
glm::vec2 uv0 = glm::vec2(0.0f, charInfo.textureY) / wh;
glm::vec2 uv1 = uv0 + (charInfo.bitmapSize / wh);
QuadMesh::bufferQuadMeshWithZ(mesh,
// Buffer the quad.
QuadMesh::bufferQuadMeshWithZ(&this->mesh,
position + charInfo.bitmapPosition, uv0,
position + charInfo.bitmapPosition + charInfo.bitmapSize, uv1,
0.0f,
j * QUAD_VERTICE_COUNT, j * QUAD_INDICE_COUNT
);
// Move the current position along.
position.x += (float_t)(charInfo.advanceX >> 6);
position.y += (float_t)(charInfo.advanceY >> 6);
bufferData.fontQuadParts[j] = partIndex;
// Set the part index to the quad mappings
bufferData.fontQuadMappings[j] = partIndex;
}
return len;
}
UILabelNew::UILabelNew(SceneItem *item) : UIComponentRenderable(item) {
}
void UILabelNew::onStart() {
std::cout << "Hello new Label" << std::endl;
this->shaderBuffer.init();
if(FT_New_Face(
getGame()->renderManager.getFontManager()->fontLibrary,
// "/usr/share/fonts/TTF/arial.ttf",
"C:\\Windows\\Fonts\\arial.ttf",
0,
&face
)) {
assertUnreachable();
}
_uiLabelBake(defFace, face, 32);
if(FT_New_Face(
getGame()->renderManager.getFontManager()->fontLibrary,
// "/usr/share/fonts/TTF/arialbd.ttf",
"C:\\Windows\\Fonts\\arialbd.ttf",
0,
&faceBold
)) {
assertUnreachable();
}
_uiLabelBake(defFaceBold, faceBold, 32);
if(FT_New_Face(
getGame()->renderManager.getFontManager()->fontLibrary,
// "/usr/share/fonts/TTF/ariali.ttf",
"C:\\Windows\\Fonts\\ariali.ttf",
0,
&faceItalics
)) {
assertUnreachable();
}
_uiLabelBake(defFaceItalics, faceItalics, 32);
struct FontShaderBufferData fontData;
glm::vec2 position = glm::vec2(32, 32);
testMesh.createBuffers(QUAD_VERTICE_COUNT * 96, QUAD_INDICE_COUNT * 96);
auto x = _uiLabelQuad(
"Hello ",
&this->testMesh,
fontData,
defFace,
position,
0,
0
);
x += _uiLabelQuad(
"World",
&this->testMesh,
fontData,
defFaceItalics,
position,
x,
1
);
fontData.fontParts[0].color = COLOR_MAGENTA;
fontData.fontParts[0].texture = 0;
fontData.fontParts[1].color = COLOR_RED;
fontData.fontParts[1].texture = 1;
shaderBuffer.buffer(&fontData);
}
std::vector<struct ShaderPassItem> UILabelNew::getUIRenderPasses() {
auto canvas = this->getCanvas();
auto shader = getGame()->renderManager.fontShader;
struct ShaderPassItem item;
item.shader = shader;
item.mesh = &testMesh;
item.matrixValues[shader->paramModel] = transform->getWorldTransform();
item.parameterBuffers[shader->bufferUiCanvas] = &canvas->shaderBuffer;
item.parameterBuffers[shader->bufferFont] = &this->shaderBuffer;
item.renderFlags = RENDER_MANAGER_RENDER_FLAG_BLEND;
item.textureSlots[0] = &defFace.texture;
item.textureSlots[1] = &defFaceItalics.texture;
item.textureValues[shader->paramTexture0] = 0;
item.textureValues[shader->paramTexture1] = 1;
return { item };
}
float_t UILabelNew::getWidth() {
return 0;
}
float_t UILabelNew::getHeight() {
return 0;
}
float_t UILabelNew::getContentWidth() {
return 0;
}
float_t UILabelNew::getContentHeight() {
return 0;
}

View File

@ -7,38 +7,17 @@
#include "scene/components/ui/UIComponentRenderable.hpp"
#include "display/mesh/QuadMesh.hpp"
#define NEW_LABEL_CHAR_BEGIN 32
#define NEW_LABEL_CHAR_END 192
namespace Dawn {
struct UILabelChar {
int32_t advanceX;
int32_t advanceY;
glm::vec2 bitmapSize;
glm::vec2 bitmapPosition;
float_t textureY;
};
struct UILabelFontDef {
Texture texture;
uint32_t fontSize;
FT_Face *face;
std::map<FT_ULong, struct UILabelChar> charStore;
};
struct UILabelPart {
struct UILabelStyle {
struct Color;
UILabelFontDef *fontDef;
std::string text;
};
class UILabelNew : public UIComponentRenderable {
protected:
private:
Mesh mesh;
FontShaderBuffer shaderBuffer;
Mesh testMesh;
FT_Face face;
FT_Face faceBold;
FT_Face faceItalics;
@ -47,6 +26,27 @@ namespace Dawn {
struct UILabelFontDef defFaceBold;
struct UILabelFontDef defFaceItalics;
/**
* Buffers the quads for the given text and updates the progressing values
* as the buffer process continues.
*
* @param text Text to buffer.
* @param bufferData The output quad mappings for the text.
* @param fontDef The font definition to use.
* @param position The 2D position to buffer the quads at.
* @param quadStart The starting quad index.
* @param partIndex The part index to store for each quad buffered.
* @return The number of quads buffered, not the string length.
*/
int32_t bufferQuads(
std::string text,
struct FontShaderBufferData &bufferData,
struct UILabelFontDef &fontDef,
glm::vec2 &position,
int32_t quadStart,
int32_t partIndex
);
public:
UILabelNew(SceneItem *item);