mirror of
https://gitea.sffempire.ru/Kolyah35/minecraft-pe-0.6.1.git
synced 2026-03-19 22:43:32 +00:00
373 lines
8.5 KiB
C++
Executable File
373 lines
8.5 KiB
C++
Executable File
#include "Font.h"
|
||
|
||
//#include "SharedConstants.h"
|
||
#include "../Options.h"
|
||
#include "../renderer/Textures.h"
|
||
#include "../renderer/Tesselator.h"
|
||
#include "../../util/Mth.h"
|
||
#include <cstring>
|
||
|
||
Font::Font( Options* options, const std::string& name, Textures* textures )
|
||
: options(options),
|
||
fontTexture(0),
|
||
fontName(name),
|
||
index(0),
|
||
count(0),
|
||
_textures(textures),
|
||
_x(0), _y(0),
|
||
_cols(16), _rows(16),
|
||
_charOffset(0),
|
||
lineHeight(DefaultLineHeight)
|
||
{
|
||
init(options);
|
||
}
|
||
|
||
|
||
//Font::Font( Options* options, const std::string& name, Textures* textures, int imgW, int imgH, int x, int y, int cols, int rows, unsigned char charOffset )
|
||
//: options(options),
|
||
// fontTexture(0),
|
||
// fontName(name),
|
||
// index(0),
|
||
// count(0),
|
||
// _textures(textures),
|
||
// _x(x), _y(y),
|
||
// _cols(cols), _rows(rows),
|
||
// _charOffset(charOffset)
|
||
//{
|
||
// init(options);
|
||
//}
|
||
|
||
void Font::onGraphicsReset()
|
||
{
|
||
init(options);
|
||
}
|
||
|
||
void Font::init( Options* options )
|
||
{
|
||
TextureId fontTexture = _textures->loadTexture(fontName);
|
||
const TextureData* tex = _textures->getTemporaryTextureData(fontTexture);
|
||
|
||
if (!tex)
|
||
return;
|
||
|
||
unsigned char* rawPixels = tex->data;
|
||
|
||
const int numChars = _rows * _cols;
|
||
for (int i = 0; i < numChars; i++) {
|
||
int xt = i % _cols;
|
||
int yt = i / _cols;
|
||
|
||
int x = 7;
|
||
for (; x >= 0; x--) {
|
||
int xPixel = _x + xt * 8 + x;
|
||
bool emptyColumn = true;
|
||
for (int y = 0; y < 8 && emptyColumn; y++) {
|
||
int yPixel = _y + (yt * 8 + y) * tex->w;
|
||
unsigned char pixelalpha = rawPixels[(xPixel + yPixel) << 2];
|
||
if (pixelalpha > 0) emptyColumn = false;
|
||
}
|
||
if (!emptyColumn) {
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (i == ' ') x = 4 - 2;
|
||
charWidths[i] = x + 2;
|
||
fcharWidths[i] = (float) charWidths[i];
|
||
}
|
||
|
||
#ifdef USE_VBO
|
||
return; // this <1
|
||
#endif
|
||
|
||
#ifndef USE_VBO
|
||
listPos = glGenLists(256 + 32);
|
||
|
||
Tesselator& t = Tesselator::instance;
|
||
for (int i = 0; i < 256; i++) {
|
||
glNewList(listPos + i, GL_COMPILE);
|
||
// @attn @huge @note: This is some dangerous code right here / Aron, added ^1
|
||
t.begin();
|
||
buildChar(i);
|
||
t.end(false, -1);
|
||
|
||
glTranslatef2((GLfloat)charWidths[i], 0.0f, 0.0f);
|
||
glEndList();
|
||
}
|
||
|
||
for (int i = 0; i < 32; i++) {
|
||
int br = ((i >> 3) & 1) * 0x55;
|
||
int r = ((i >> 2) & 1) * 0xaa + br;
|
||
int g = ((i >> 1) & 1) * 0xaa + br;
|
||
int b = ((i >> 0) & 1) * 0xaa + br;
|
||
if (i == 6) {
|
||
r += 0x55;
|
||
}
|
||
bool darken = i >= 16;
|
||
|
||
if (options->anaglyph3d) {
|
||
int cr = (r * 30 + g * 59 + b * 11) / 100;
|
||
int cg = (r * 30 + g * 70) / (100);
|
||
int cb = (r * 30 + b * 70) / (100);
|
||
|
||
r = cr;
|
||
g = cg;
|
||
b = cb;
|
||
}
|
||
|
||
// color = r << 16 | g << 8 | b;
|
||
if (darken) {
|
||
r /= 4;
|
||
g /= 4;
|
||
b /= 4;
|
||
}
|
||
|
||
glNewList(listPos + 256 + i, GL_COMPILE);
|
||
glColor3f(r / 255.0f, g / 255.0f, b / 255.0f);
|
||
glEndList();
|
||
}
|
||
#endif
|
||
}
|
||
|
||
void Font::drawShadow( const std::string& str, float x, float y, int color )
|
||
{
|
||
draw(str, x + 1, y + 1, color, true);
|
||
draw(str, x, y, color);
|
||
}
|
||
void Font::drawShadow( const char* str, float x, float y, int color )
|
||
{
|
||
draw(str, x + 1, y + 1, color, true);
|
||
draw(str, x, y, color);
|
||
}
|
||
|
||
void Font::draw( const std::string& str, float x, float y, int color )
|
||
{
|
||
draw(str, x, y, color, false);
|
||
}
|
||
|
||
void Font::draw( const char* str, float x, float y, int color )
|
||
{
|
||
draw(str, x, y, color, false);
|
||
}
|
||
|
||
void Font::draw( const char* str, float x, float y, int color, bool darken )
|
||
{
|
||
#ifdef USE_VBO
|
||
drawSlow(str, x, y, color, darken);
|
||
#endif
|
||
}
|
||
|
||
void Font::draw( const std::string& str, float x, float y, int color, bool darken )
|
||
{
|
||
#ifdef USE_VBO
|
||
drawSlow(str, x, y, color, darken);
|
||
return;
|
||
#endif
|
||
|
||
if (str.empty()) return;
|
||
|
||
if (darken) {
|
||
int oldAlpha = color & 0xff000000;
|
||
color = (color & 0xfcfcfc) >> 2;
|
||
color += oldAlpha;
|
||
}
|
||
|
||
_textures->loadAndBindTexture(fontName);
|
||
float r = ((color >> 16) & 0xff) / 255.0f;
|
||
float g = ((color >> 8) & 0xff) / 255.0f;
|
||
float b = ((color) & 0xff) / 255.0f;
|
||
float a = ((color >> 24) & 0xff) / 255.0f;
|
||
if (a == 0) a = 1;
|
||
glColor4f2(r, g, b, a);
|
||
|
||
static const std::string hex("0123456789abcdef");
|
||
|
||
index = 0;
|
||
glPushMatrix2();
|
||
glTranslatef2((GLfloat)x, (GLfloat)y, 0.0f);
|
||
for (unsigned int i = 0; i < str.length(); i++) {
|
||
while (str.length() > i + 1 && str[i] == '<EFBFBD>') {
|
||
int cc = hex.find((char)tolower(str[i + 1]));
|
||
if (cc < 0 || cc > 15) cc = 15;
|
||
lists[index++] = listPos + 256 + cc + (darken ? 16 : 0);
|
||
|
||
if (index == 1024) {
|
||
count = index;
|
||
index = 0;
|
||
#ifndef USE_VBO
|
||
glCallLists(count, GL_UNSIGNED_INT, lists);
|
||
#endif
|
||
count = 1024;
|
||
}
|
||
|
||
i += 2;
|
||
}
|
||
|
||
if (i < str.length()) {
|
||
//int ch = SharedConstants.acceptableLetters.indexOf(str.charAt(i));
|
||
char ch = str[i];
|
||
if (ch >= 0) {
|
||
//ib.put(listPos + ch + 32);
|
||
lists[index++] = listPos + ch;
|
||
}
|
||
}
|
||
|
||
if (index == 1024) {
|
||
count = index;
|
||
index = 0;
|
||
#ifndef USE_VBO
|
||
glCallLists(count, GL_UNSIGNED_INT, lists);
|
||
#endif
|
||
count = 1024;
|
||
}
|
||
}
|
||
count = index;
|
||
index = 0;
|
||
#ifndef USE_VBO
|
||
glCallLists(count, GL_UNSIGNED_INT, lists);
|
||
#endif
|
||
glPopMatrix2();
|
||
}
|
||
|
||
int Font::width( const std::string& str )
|
||
{
|
||
int maxLen = 0;
|
||
int len = 0;
|
||
|
||
for (unsigned int i = 0; i < str.length(); i++) {
|
||
if (str[i] == '<EFBFBD>') {
|
||
i++;
|
||
} else {
|
||
//int ch = SharedConstants.acceptableLetters.indexOf(str.charAt(i));
|
||
//if (ch >= 0) {
|
||
// len += charWidths[ch + 32];
|
||
//}
|
||
if (str[i] == '\n') {
|
||
if (len > maxLen) maxLen = len;
|
||
len = 0;
|
||
}
|
||
else {
|
||
int charWidth = charWidths[ (unsigned char) str[i] ];
|
||
len += charWidth;
|
||
}
|
||
}
|
||
}
|
||
return maxLen>len? maxLen : len;
|
||
}
|
||
|
||
int Font::height( const std::string& str ) {
|
||
int h = 0;
|
||
bool hasLine = false;
|
||
for (unsigned int i = 0; i < str.length(); ++i) {
|
||
if (str[i] == '\n') hasLine = true;
|
||
else {
|
||
if (hasLine) h += lineHeight;
|
||
hasLine = false;
|
||
}
|
||
}
|
||
return h;
|
||
}
|
||
|
||
std::string Font::sanitize( const std::string& str )
|
||
{
|
||
std::string sanitized(str.length() + 1, 0);
|
||
int j = 0;
|
||
|
||
for (unsigned int i = 0; i < str.length(); i++) {
|
||
if (str[i] == '<EFBFBD>') {
|
||
i++;
|
||
//} else if (SharedConstants.acceptableLetters.indexOf(str.charAt(i)) >= 0) {
|
||
} else {
|
||
sanitized[j++] = str[i];
|
||
}
|
||
}
|
||
return sanitized.erase(j);
|
||
}
|
||
|
||
void Font::drawWordWrap( const std::string& str, float x, float y, float w, int col )
|
||
{
|
||
char* cstr = new char[str.length() + 1];
|
||
strncpy(cstr, str.c_str(), str.length());
|
||
cstr[str.length()] = 0;
|
||
|
||
const char* lims = " \n\t\r";
|
||
char* ptok = strtok(cstr, lims);
|
||
|
||
std::vector<std::string> words;
|
||
while (ptok != NULL) {
|
||
words.push_back( ptok );
|
||
ptok = strtok(NULL, lims);
|
||
}
|
||
|
||
delete[] cstr;
|
||
|
||
int pos = 0;
|
||
while (pos < (int)words.size()) {
|
||
std::string line = words[pos++] + " ";
|
||
while (pos < (int)words.size() && width(line + words[pos]) < w) {
|
||
line += words[pos++] + " ";
|
||
}
|
||
drawShadow(line, x, y, col);
|
||
y += lineHeight;
|
||
}
|
||
}
|
||
|
||
void Font::drawSlow( const std::string& str, float x, float y, int color, bool darken /*= false*/ ) {
|
||
drawSlow(str.c_str(), x, y, color, darken);
|
||
}
|
||
void Font::drawSlow( const char* str, float x, float y, int color, bool darken /*= false*/ )
|
||
{
|
||
if (!str) return;
|
||
|
||
if (darken) {
|
||
int oldAlpha = color & 0xff000000;
|
||
color = (color & 0xfcfcfc) >> 2;
|
||
color += oldAlpha;
|
||
}
|
||
|
||
_textures->loadAndBindTexture(fontName);
|
||
|
||
Tesselator& t = Tesselator::instance;
|
||
t.begin();
|
||
int alpha = (0xff000000 & color) >> 24;
|
||
if (!alpha) alpha = 0xff;
|
||
t.color((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, alpha);
|
||
|
||
t.addOffset((float)x, (float)y, 0);
|
||
float xOffset = 0;
|
||
float yOffset = 0;
|
||
|
||
while (unsigned char ch = *(str++)) {
|
||
if (ch == '\n') {
|
||
xOffset = 0;
|
||
yOffset += lineHeight;
|
||
} else {
|
||
buildChar(ch, xOffset, yOffset);
|
||
xOffset += fcharWidths[ch];
|
||
}
|
||
}
|
||
t.draw();
|
||
t.addOffset(-(float)x, -(float)y, 0);
|
||
}
|
||
|
||
void Font::buildChar( unsigned char i, float x /*= 0*/, float y /*=0*/ )
|
||
{
|
||
Tesselator& t = Tesselator::instance;
|
||
|
||
//i -= _charOffset;
|
||
//int ix = (i % _cols) * 8 + _x;
|
||
//int iy = (i / _cols) * 8 + _y;
|
||
float ix = (float)((i & 15) * 8);
|
||
float iy = (float)((i >> 4) * 8);
|
||
float s = 7.99f;
|
||
|
||
float uo = (0.0f) / 128.0f;
|
||
float vo = (0.0f) / 128.0f;
|
||
|
||
t.vertexUV(x, y + s, 0, ix / 128.0f + uo, (iy + s) / 128.0f + vo);
|
||
t.vertexUV(x + s, y + s, 0, (ix + s) / 128.0f + uo, (iy + s) / 128.0f + vo);
|
||
t.vertexUV(x + s, y, 0, (ix + s) / 128.0f + uo, iy / 128.0f + vo);
|
||
t.vertexUV(x, y, 0, ix / 128.0f + uo, iy / 128.0f + vo);
|
||
}
|
||
|