mirror of
https://github.com/ReMinecraftPE/mcpe.git
synced 2025-01-23 17:52:10 -05:00
195 lines
4 KiB
C++
195 lines
4 KiB
C++
/********************************************************************
|
|
Minecraft: Pocket Edition - Decompilation Project
|
|
Copyright (C) 2023 iProgramInCpp
|
|
|
|
The following code is licensed under the BSD 1 clause license.
|
|
SPDX-License-Identifier: BSD-1-Clause
|
|
********************************************************************/
|
|
|
|
#include "Font.hpp"
|
|
#include "Tesselator.hpp"
|
|
|
|
constexpr char COLOR_START_CHAR = '\xa7';
|
|
|
|
Font::Font(Options* pOpts, const std::string& fileName, Textures* pTexs)
|
|
{
|
|
m_fileName = fileName;
|
|
m_pOptions = pOpts;
|
|
m_pTextures = pTexs;
|
|
|
|
init(pOpts);
|
|
}
|
|
|
|
void Font::init(Options* pOpts)
|
|
{
|
|
GLuint texID = m_pTextures->loadTexture(m_fileName, true);
|
|
Texture* pTexture = m_pTextures->getTemporaryTextureData(texID);
|
|
if (!pTexture) return;
|
|
|
|
for (int i = 0; i < 256; i++) // character number
|
|
{
|
|
// note: the 'widthMax' behavior is assumed. It might not be like that exactly
|
|
int widthMax = 0;
|
|
|
|
if (i == 32) // space
|
|
{
|
|
widthMax = 2;
|
|
}
|
|
else
|
|
{
|
|
for (int j = 7; j >= 0; j--) // x position
|
|
{
|
|
int x = (i % 16), y = (i / 16);
|
|
int pixelDataIndex = pTexture->m_width * 8 * y + 8 * x + j;
|
|
|
|
for (int k = 0; k < 8; k++)
|
|
{
|
|
if ((uint8_t)pTexture->m_pixels[pixelDataIndex] != 0)
|
|
{
|
|
if (widthMax < j)
|
|
widthMax = j;
|
|
}
|
|
|
|
pixelDataIndex += pTexture->m_width;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_charWidthInt[i] = widthMax + 2;
|
|
m_charWidthFloat[i] = float (widthMax) + 2;
|
|
}
|
|
}
|
|
|
|
void Font::buildChar(unsigned char chr, float x, float y)
|
|
{
|
|
Tesselator& t = Tesselator::instance;
|
|
|
|
float u = float((chr % 16) * 8);
|
|
float v = float((chr / 16) * 8);
|
|
|
|
constexpr float D128 = (1.0f / 128.0f);
|
|
|
|
#define CO (7.99f)
|
|
|
|
t.vertexUV(x, y + CO, 0.0f, u * D128, (v + CO) * D128);
|
|
t.vertexUV(x + CO, y + CO, 0.0f, (u + CO) * D128, (v + CO) * D128);
|
|
t.vertexUV(x + CO, y, 0.0f, (u + CO) * D128, v * D128);
|
|
t.vertexUV(x, y, 0.0f, u * D128, v * D128);
|
|
|
|
#undef CO
|
|
}
|
|
|
|
void Font::draw(const std::string& str, int x, int y, int color)
|
|
{
|
|
draw(str, x, y, color, false);
|
|
}
|
|
|
|
void Font::drawShadow(const std::string& str, int x, int y, int color)
|
|
{
|
|
draw(str, x + 1, y + 1, color, true);
|
|
draw(str, x, y, color, false);
|
|
}
|
|
|
|
void Font::draw(const std::string& str, int x, int y, int color, bool bShadow)
|
|
{
|
|
drawSlow(str, x, y, color, bShadow);
|
|
}
|
|
|
|
void Font::drawSlow(const std::string& str, int x, int y, int colorI, bool bShadow)
|
|
{
|
|
if (str.empty()) return;
|
|
|
|
uint32_t color = colorI;
|
|
|
|
if (bShadow)
|
|
color = (color & 0xFF000000U) + ((color & 0xFCFCFCu) >> 2);
|
|
|
|
m_pTextures->loadAndBindTexture(m_fileName);
|
|
|
|
uint32_t red = (color >> 16) & 0xFF;
|
|
uint32_t grn = (color >> 8) & 0xFF;
|
|
uint32_t blu = (color >> 0) & 0xFF;
|
|
uint32_t alp = (color >> 24) & 0xFF;
|
|
|
|
float alpf = float(alp) / 255.0f;
|
|
if (alpf == 0.0f)
|
|
alpf = 1.0f;
|
|
|
|
glColor4f(float(red) / 255.0f, float(grn) / 255.0f, float(blu) / 255.0f, alpf);
|
|
glPushMatrix();
|
|
|
|
Tesselator& t = Tesselator::instance;
|
|
t.begin();
|
|
|
|
glTranslatef(float(x), float(y), 0.0f);
|
|
|
|
float cXPos = 0.0f, cYPos = 0.0f;
|
|
|
|
for (int i = 0; i < int(str.size()); i++)
|
|
{
|
|
if (str[i] == '\n')
|
|
{
|
|
cYPos += 12.0f;
|
|
cXPos = 0;
|
|
continue;
|
|
}
|
|
|
|
uint8_t x = uint8_t(str[i]);
|
|
|
|
buildChar(x, cXPos, cYPos);
|
|
|
|
cXPos += m_charWidthFloat[x];
|
|
}
|
|
|
|
t.draw();
|
|
|
|
glPopMatrix();
|
|
}
|
|
|
|
void Font::onGraphicsReset()
|
|
{
|
|
init(m_pOptions);
|
|
}
|
|
|
|
int Font::height(const std::string& str)
|
|
{
|
|
if (str.empty()) return 0;
|
|
|
|
int res = 0; // note: starting at 0 looks wrong
|
|
|
|
for (int i = 0; i < int(str.size()); i++)
|
|
if (str[i] == '\n')
|
|
res += 12;
|
|
|
|
return res;
|
|
}
|
|
|
|
int Font::width(const std::string& str)
|
|
{
|
|
int maxLineWidth = 0, currentLineWidth = 0;
|
|
|
|
for (int i = 0; i < int(str.size()); i++)
|
|
{
|
|
char chr = str[i];
|
|
|
|
if (chr == COLOR_START_CHAR)
|
|
{
|
|
// skip the color code as well
|
|
i++;
|
|
continue;
|
|
}
|
|
if (chr == '\n')
|
|
{
|
|
if (maxLineWidth < currentLineWidth)
|
|
maxLineWidth = currentLineWidth;
|
|
currentLineWidth = 0;
|
|
}
|
|
|
|
currentLineWidth += m_charWidthInt[uint8_t(str[i])];
|
|
}
|
|
|
|
if (maxLineWidth < currentLineWidth)
|
|
maxLineWidth = currentLineWidth;
|
|
|
|
return maxLineWidth;
|
|
}
|