commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View File

@ -0,0 +1,377 @@
/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include <cstring>
#include "font/font_renderer.h"
#include "picture/pict.h"
#include "ascii/parser.h"
#include "log/log.h"
using namespace GS;
using namespace GS::AsciiParser;
float FontRenderer::default_text_tracking = 0;
float FontRenderer::default_text_heading = 0;
//
struct GS::SubString
{
const char *entry;
int char_count;
int space_count;
int width; // 26.6
int height;
void Reset(const char *string)
{
entry = string;
char_count = 0;
space_count = 0;
width = 0;
height = 0;
}
};
int substring_count = 0;
SubString substring_array[1024];
//------------------------------------------------------------------------------
const char *FontRenderer::CheckCommand(const char *string, Command &command)
{
command.code = CommandNone;
if (!string[0] || !string[1])
return string;
if ((string[0] == '~') && (string[1] == '~'))
{
//----------------------------------------------------------------------
#define PARSE_COMPONENT(_C_, _M_)\
{\
string = SkipSpace(string + 1, eos);\
command.vector._C_ = (float)String::atoi(string);\
string = NextEntry(string, eos);\
if (string[0] != (_M_))\
{\
command.code = CommandParseError;\
__LOG_E__ << "Error parsing text command components.\n";\
return NULL;\
}\
}
//----------------------------------------------------------------------
const char *eos = string + std::strlen(string);
if (!strncmp("Color(", string + 2, 6) || !strncmp("COLOR(", string + 2, 6)) // [EJ] 1st may: range is [0;255]
{
command.code = CommandColor;
string += 7;
const char *eop = Find(string, eos, ')');
if (!eop)
{
command.code = CommandParseError;
return NULL;
}
PARSE_COMPONENT(x, ',');
PARSE_COMPONENT(y, ',');
PARSE_COMPONENT(z, ',');
PARSE_COMPONENT(w, ')');
string = eop + 1;
}
else if (!strncmp("Size(", string + 2, 5) || !strncmp("SIZE(", string + 2, 5))
{
command.code = CommandSize;
string += 6;
const char *eop = Find(string, eos, ')');
if (!eop)
{
command.code = CommandParseError;
return NULL;
}
PARSE_COMPONENT(x, ')');
string = eop + 1;
}
}
return string;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
const char *FontRenderer::FetchSubString(const char *string, SubString &substring, TextState &state, int max_width, int max_char)
{
if (!string)
return NULL;
// Jump over leading spaces.
forever
{
if (string[0] != ' ')
break;
if (!string[0] || (string[0] == '\n'))
{
substring.Reset(NULL);
return string;
}
string++;
}
// Start sub-string.
substring.Reset(string);
int previous_codepoint = 0;
state.font->SetPixelSize(state.GetSize());
max_width <<= 6;
// Word cut point.
bool rollback_available = false;
SubString rollback_substring;
const char *rollback_string = NULL;
int tracking = int(state.GetTracking() * 64.f);
forever
{
Command command;
if ((string = CheckCommand(string, command)) == 0)
break;
if (command.code == CommandNone)
{
if (string[0] == '\n')
{
string++;
break;
}
if ((string[0] == '\\') && (string[1] == 'n'))
{
string += 2;
break;
}
if (string[0] == 0)
break;
if ((max_char > 0) && (substring.char_count == max_char))
break;
// Get glyph.
uint codepoint;
int codelength = String::Utf8toUtf32((const uchar *)string, &codepoint);
state.font->LoadGlyph(codepoint, false);
// Retrieve glyph formatting informations.
int advance = state.font->GetAdvance();
int kerning = (state.font->HasKerning() && (previous_codepoint != 0)) ? state.font->GetKerning(previous_codepoint, codepoint) : 0;
// Width constraint.
if ((max_width > 0) && ((substring.width + advance) >= max_width))
{
rollback_available = true;
break;
}
substring.width += advance + kerning + tracking;
substring.height = Types::Max(state.font->GetHeight(), substring.height);
// Count space.
if (string[0] == ' ')
{
substring.space_count++;
// Store the word rollback position.
Command dummy_command;
CheckCommand(string, dummy_command);
if ((dummy_command.code == CommandNone) && (string[1] != ' '))
{
rollback_substring = substring;
rollback_string = string;
}
}
substring.char_count++;
// Next glyph.
string += codelength ? codelength : 1;
previous_codepoint = codepoint;
}
else
switch (command.code)
{
case CommandColor: // Irrelevant when not composing.
break;
case CommandSize:
state.SetSize((int)command.vector.x);
state.font->SetPixelSize(state.GetSize());
break;
default: break;
}
}
// Rollback to the last word position.
if (rollback_available && rollback_string)
{
substring = rollback_substring;
string = rollback_string;
}
return string;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void FontRenderer::DrawSubString(SubString &line, Picture &output, TextState &state, const iRect &_out_rect, const iRect &clip_rect, int justification)
{
const char *string = line.entry;
state.font->SetPixelSize(state.GetSize());
iRect out_rect(_out_rect);
uint previous_codepoint = 0;
int tracking = int(state.GetTracking() * 64.f);
for (int n = 0; n < line.char_count; ++n)
{
Command command;
string = CheckCommand(string, command);
if (command.code == CommandNone)
{
// Get glyph.
uint codepoint;
int codelength = String::Utf8toUtf32((const uchar *)string, &codepoint);
state.font->LoadGlyph(codepoint, true);
// Retrieve glyph formatting informations.
int advance = state.font->GetAdvance();
int kerning = (state.font->HasKerning() && (previous_codepoint != 0)) ? state.font->GetKerning(previous_codepoint, codepoint) : 0;
// Render.
int px = out_rect.sx >> 6;
int py = (out_rect.sy + (line.height * 3) / 4) >> 6; // FIXME smells the hack... at best!
state.font->RenderCurrentGlyph(output, iPoint(px, py), clip_rect, state.color);
out_rect.sx += advance + kerning + tracking;
// Next glyph.
string += codelength;
previous_codepoint = codepoint;
}
else
{
switch (command.code)
{
case CommandColor:
state.color = command.vector ;/// 255.f;
break;
case CommandSize:
state.SetSize((int)command.vector.x);
state.font->SetPixelSize(state.GetSize());
break;
default: break;
}
--n;
}
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
iRect FontRenderer::Format(const char *txt, const TextState &in_state, const iRect &out_rect)
{
if (!in_state.font)
return iRect (0, 0, 0, 0);
// Create working state.
TextState state = in_state;
// Setup formatting rules.
int max_width = (state.format == TextState::Line) ? -1 : out_rect.GetWidth(),
max_char = (state.format != TextState::Column) ? -1 : state.column_width;
// Fetch all substrings.
substring_count = 0;
while (txt && txt[0])
txt = FetchSubString(txt, substring_array[substring_count++], state, max_width, max_char);
// Create full text rectangle.
iRect text_rect;
text_rect.Set(0, 0, 0, 0);
int leading = int(state.GetLeading() * 64);
for (int n = 0; n < substring_count; ++n)
{
if (text_rect.ex < substring_array[n].width)
text_rect.ex = substring_array[n].width;
text_rect.ey += substring_array[n].height + leading;
}
if (substring_count > 0)
text_rect.ey -= leading;
text_rect.ex = text_rect.ex / 64;
text_rect.ey = text_rect.ey / 64;
return text_rect;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
iRect FontRenderer::Compose(Picture &output, const char *txt, const TextState &in_state, const iRect &out_rect, const iRect &clip_rect)
{
if (in_state.font.IsNull() || (output.GetPixelFormat().GetBpp() != 32))
return iRect(0, 0, 0, 0);
// Create working state.
TextState state = in_state;
int leading = int(state.GetLeading() * 64);
// Draw substrings.
iRect work_out_rect(out_rect * 64);
for (int n = 0; n < substring_count; ++n)
{
iRect line_rect(work_out_rect);
line_rect.ex = line_rect.sx + substring_array[n].width;
int offset = 0, justification = 0;
switch (state.alignment)
{
case TextState::Left:
offset = out_rect.sx * 64 - line_rect.sx;
break;
case TextState::Center:
offset = (out_rect.GetWidth() * 64 - line_rect.GetWidth()) / 2;
break;
case TextState::Right:
offset = out_rect.ex * 64 - line_rect.ex;
break;
case TextState::Justify:
if (n < (substring_count - 1))
justification = (out_rect.GetWidth() * 64 - line_rect.GetWidth()) / substring_array[n].space_count;
break;
default: break;
}
line_rect.sx += offset;
DrawSubString(substring_array[n], output, state, line_rect, clip_rect, justification);
work_out_rect.sy += substring_array[n].height + leading;
}
return out_rect;
}
//------------------------------------------------------------------------------