mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 11:35:08 -04:00
Merge pull request #922 from UnknownShadow200/WebSystemFonts
WIP on web system fonts
This commit is contained in:
commit
67507c4ab5
@ -678,24 +678,69 @@ struct IGameComponent Drawer2D_Component = {
|
||||
*#########################################################################################################################*/
|
||||
#ifdef CC_BUILD_WEB
|
||||
const cc_string* Font_UNSAFE_GetDefault(void) { return &font_candidates[0]; }
|
||||
void Font_GetNames(struct StringsBuffer* buffer) { }
|
||||
cc_string Font_Lookup(const cc_string* fontName, int flags) { return String_Empty; }
|
||||
|
||||
void Font_GetNames(struct StringsBuffer* buffer) {
|
||||
static const char* font_names[] = {
|
||||
"Arial", "Arial Black", "Courier New", "Comic Sans MS", "Georgia", "Garamond",
|
||||
"Helvetica", "Impact", "Tahoma", "Times New Roman", "Trebuchet MS", "Verdana",
|
||||
"cursive", "fantasy", "monospace", "sans-serif", "serif", "system-ui"
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < Array_Elems(font_names); i++) {
|
||||
cc_string str = String_FromReadonly(font_names[i]);
|
||||
StringsBuffer_Add(buffer, &str);
|
||||
}
|
||||
}
|
||||
|
||||
cc_result Font_Make(struct FontDesc* desc, const cc_string* fontName, int size, int flags) {
|
||||
desc->size = size;
|
||||
desc->flags = flags;
|
||||
desc->height = 0;
|
||||
desc->height = size;
|
||||
|
||||
desc->handle = Mem_TryAlloc(fontName->length + 1, 1);
|
||||
if (!desc->handle) return 0;
|
||||
|
||||
String_CopyToRaw(desc->handle, fontName->length + 1, fontName);
|
||||
return 0;
|
||||
}
|
||||
void Font_MakeDefault(struct FontDesc* desc, int size, int flags) { Font_Make(desc, NULL, size, flags); }
|
||||
|
||||
void Font_MakeDefault(struct FontDesc* desc, int size, int flags) {
|
||||
cc_string str = font_candidates[0];
|
||||
/* Fallback to arial */
|
||||
if (!str.length) str = font_candidates[1];
|
||||
|
||||
Font_Make(desc, &str, size, flags);
|
||||
}
|
||||
|
||||
void Font_Free(struct FontDesc* desc) {
|
||||
Mem_Free(desc->handle);
|
||||
desc->handle = NULL;
|
||||
desc->size = 0;
|
||||
}
|
||||
|
||||
void SysFonts_Register(const cc_string* path) { }
|
||||
static int Font_SysTextWidth(struct DrawTextArgs* args) { return 0; }
|
||||
static void Font_SysTextDraw(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { }
|
||||
extern void interop_SetFont(const char* font, int size, int flags);
|
||||
extern int interop_TextWidth(const char* text, const int len);
|
||||
extern void interop_TextDraw(const char* text, const int len, struct Bitmap* bmp, int x, int y, cc_bool shadow);
|
||||
|
||||
static int Font_SysTextWidth(struct DrawTextArgs* args) {
|
||||
struct FontDesc* font = args->font;
|
||||
char buffer[NATIVE_STR_LEN];
|
||||
int len = Platform_EncodeUtf8(buffer, &args->text);
|
||||
|
||||
interop_SetFont(font->handle, font->size, font->flags);
|
||||
return interop_TextWidth(buffer, len);
|
||||
}
|
||||
|
||||
static void Font_SysTextDraw(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) {
|
||||
struct FontDesc* font = args->font;
|
||||
char buffer[NATIVE_STR_LEN];
|
||||
int len = Platform_EncodeUtf8(buffer, &args->text);
|
||||
|
||||
interop_SetFont(font->handle, font->size, font->flags);
|
||||
interop_TextDraw(buffer, len, bmp, x, y, shadow);
|
||||
}
|
||||
#else
|
||||
#include "freetype/ft2build.h"
|
||||
#include "freetype/freetype.h"
|
||||
@ -706,6 +751,8 @@ static FT_Library ft_lib;
|
||||
static struct FT_MemoryRec_ ft_mem;
|
||||
static struct StringsBuffer font_list;
|
||||
static cc_bool fonts_changed;
|
||||
/* Finds the path and face number of the given system font, with closest matching style */
|
||||
static cc_string Font_Lookup(const cc_string* fontName, int flags);
|
||||
|
||||
struct SysFont {
|
||||
FT_Face face;
|
||||
@ -952,6 +999,7 @@ void Font_GetNames(struct StringsBuffer* buffer) {
|
||||
name.length -= 2;
|
||||
StringsBuffer_Add(buffer, &name);
|
||||
}
|
||||
StringsBuffer_Sort(buffer);
|
||||
}
|
||||
|
||||
static cc_string Font_LookupOf(const cc_string* fontName, const char type) {
|
||||
|
@ -109,8 +109,6 @@ CC_API void Font_GetNames(struct StringsBuffer* buffer);
|
||||
|
||||
/* Sets padding for a bitmapped font */
|
||||
void Font_SetPadding(struct FontDesc* desc, int amount);
|
||||
/* Finds the path and face number of the given system font, with closest matching style */
|
||||
cc_string Font_Lookup(const cc_string* fontName, int flags);
|
||||
/* Allocates a new system font from the given arguments */
|
||||
cc_result Font_Make(struct FontDesc* desc, const cc_string* fontName, int size, int flags);
|
||||
/* Allocates a new system font from the given arguments using default system font */
|
||||
|
38
src/Menus.c
38
src/Menus.c
@ -289,32 +289,6 @@ static void ListScreen_MoveForwards(void* screen, void* b) {
|
||||
ListScreen_PageClick(s, true);
|
||||
}
|
||||
|
||||
static void ListScreen_QuickSort(int left, int right) {
|
||||
struct StringsBuffer* buffer = &ListScreen.entries;
|
||||
cc_uint32* keys = buffer->flagsBuffer; cc_uint32 key;
|
||||
|
||||
while (left < right) {
|
||||
int i = left, j = right;
|
||||
cc_string pivot = StringsBuffer_UNSAFE_Get(buffer, (i + j) >> 1);
|
||||
cc_string strI, strJ;
|
||||
|
||||
/* partition the list */
|
||||
while (i <= j) {
|
||||
while ((strI = StringsBuffer_UNSAFE_Get(buffer, i), String_Compare(&pivot, &strI)) > 0) i++;
|
||||
while ((strJ = StringsBuffer_UNSAFE_Get(buffer, j), String_Compare(&pivot, &strJ)) < 0) j--;
|
||||
QuickSort_Swap_Maybe();
|
||||
}
|
||||
/* recurse into the smaller subset */
|
||||
QuickSort_Recurse(ListScreen_QuickSort)
|
||||
}
|
||||
}
|
||||
|
||||
CC_NOINLINE static void ListScreen_Sort(struct ListScreen* s) {
|
||||
if (s->entries.count) {
|
||||
ListScreen_QuickSort(0, s->entries.count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static cc_string ListScreen_UNSAFE_GetCur(struct ListScreen* s, void* widget) {
|
||||
int i = Screen_Index(s, widget);
|
||||
return ListScreen_UNSAFE_Get(s, s->currentIndex + i);
|
||||
@ -1583,7 +1557,7 @@ static void TexturePackScreen_FilterFiles(const cc_string* path, void* obj) {
|
||||
static void TexturePackScreen_LoadEntries(struct ListScreen* s) {
|
||||
static const cc_string path = String_FromConst(TEXPACKS_DIR);
|
||||
Directory_Enum(&path, &s->entries, TexturePackScreen_FilterFiles);
|
||||
ListScreen_Sort(s);
|
||||
StringsBuffer_Sort(&s->entries);
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_WEB
|
||||
@ -1648,7 +1622,6 @@ static void FontListScreen_UpdateEntry(struct ListScreen* s, struct ButtonWidget
|
||||
|
||||
static void FontListScreen_LoadEntries(struct ListScreen* s) {
|
||||
Font_GetNames(&s->entries);
|
||||
ListScreen_Sort(s);
|
||||
ListScreen_Select(s, Font_UNSAFE_GetDefault());
|
||||
}
|
||||
|
||||
@ -1720,7 +1693,7 @@ static void HotkeyListScreen_LoadEntries(struct ListScreen* s) {
|
||||
|
||||
/* Placeholder for 'add new hotkey' */
|
||||
StringsBuffer_Add(&s->entries, &String_Empty);
|
||||
ListScreen_Sort(s);
|
||||
StringsBuffer_Sort(&s->entries);
|
||||
}
|
||||
|
||||
static void HotkeyListScreen_UpdateEntry(struct ListScreen* s, struct ButtonWidget* button, const cc_string* text) {
|
||||
@ -1774,7 +1747,7 @@ static void LoadLevelScreen_FilterFiles(const cc_string* path, void* obj) {
|
||||
static void LoadLevelScreen_LoadEntries(struct ListScreen* s) {
|
||||
static const cc_string path = String_FromConst("maps");
|
||||
Directory_Enum(&path, &s->entries, LoadLevelScreen_FilterFiles);
|
||||
ListScreen_Sort(s);
|
||||
StringsBuffer_Sort(&s->entries);
|
||||
}
|
||||
|
||||
#ifdef CC_BUILD_WEB
|
||||
@ -2934,11 +2907,6 @@ static void GuiOptionsScreen_InitWidgets(struct MenuOptionsScreen* s) {
|
||||
s->numCore = 7;
|
||||
s->maxVertices += 7 * BUTTONWIDGET_MAX;
|
||||
MenuOptionsScreen_InitButtons(s, buttons, Array_Elems(buttons), Menu_SwitchOptions);
|
||||
#ifdef CC_BUILD_WEB
|
||||
/* TODO: Support system fonts in webclient */
|
||||
s->buttons[5].disabled = true;
|
||||
s->buttons[6].disabled = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void GuiOptionsScreen_Show(void) {
|
||||
|
26
src/String.c
26
src/String.c
@ -872,6 +872,32 @@ void StringsBuffer_Remove(struct StringsBuffer* buffer, int index) {
|
||||
buffer->totalLength -= len;
|
||||
}
|
||||
|
||||
static struct StringsBuffer* sort_buffer;
|
||||
static void StringsBuffer_QuickSort(int left, int right) {
|
||||
struct StringsBuffer* buffer = sort_buffer;
|
||||
cc_uint32* keys = buffer->flagsBuffer; cc_uint32 key;
|
||||
|
||||
while (left < right) {
|
||||
int i = left, j = right;
|
||||
cc_string pivot = StringsBuffer_UNSAFE_Get(buffer, (i + j) >> 1);
|
||||
cc_string strI, strJ;
|
||||
|
||||
/* partition the list */
|
||||
while (i <= j) {
|
||||
while ((strI = StringsBuffer_UNSAFE_Get(buffer, i), String_Compare(&pivot, &strI)) > 0) i++;
|
||||
while ((strJ = StringsBuffer_UNSAFE_Get(buffer, j), String_Compare(&pivot, &strJ)) < 0) j--;
|
||||
QuickSort_Swap_Maybe();
|
||||
}
|
||||
/* recurse into the smaller subset */
|
||||
QuickSort_Recurse(StringsBuffer_QuickSort)
|
||||
}
|
||||
}
|
||||
|
||||
void StringsBuffer_Sort(struct StringsBuffer* buffer) {
|
||||
sort_buffer = buffer;
|
||||
StringsBuffer_QuickSort(0, buffer->count - 1);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*------------------------------------------------------Word wrapper-------------------------------------------------------*
|
||||
|
@ -241,6 +241,8 @@ STRING_REF void StringsBuffer_UNSAFE_GetRaw(struct StringsBuffer* buffer, int i,
|
||||
CC_API void StringsBuffer_Add(struct StringsBuffer* buffer, const cc_string* str);
|
||||
/* Removes the i'th string from the given buffer, shifting following strings downwards */
|
||||
CC_API void StringsBuffer_Remove(struct StringsBuffer* buffer, int index);
|
||||
/* Sorts all the entries in the given buffer using String_Compare */
|
||||
void StringsBuffer_Sort(struct StringsBuffer* buffer);
|
||||
|
||||
/* Performs line wrapping on the given string. */
|
||||
/* e.g. "some random tex|t* (| is lineLen) becomes "some random" "text" */
|
||||
|
@ -815,4 +815,88 @@ mergeInto(LibraryManager.library, {
|
||||
var str = AUDIO.errors[errCode - 1];
|
||||
return stringToUTF8(str, buffer, bufferLen);
|
||||
},
|
||||
|
||||
|
||||
//########################################################################################################################
|
||||
//-----------------------------------------------------------Font---------------------------------------------------------
|
||||
//########################################################################################################################
|
||||
interop_SetFont: function(fontStr, size, flags) {
|
||||
if (!window.FONT_CANVAS) {
|
||||
window.FONT_CANVAS = document.createElement('canvas');
|
||||
window.FONT_CONTEXT = window.FONT_CANVAS.getContext('2d');
|
||||
}
|
||||
|
||||
var prefix = '';
|
||||
if (flags & 1) prefix += 'Bold ';
|
||||
|
||||
var font = UTF8ToString(fontStr);
|
||||
var ctx = window.FONT_CONTEXT;
|
||||
ctx.font = prefix + size + 'px ' + font;
|
||||
ctx.textAlign = 'left';
|
||||
ctx.textBaseline = 'top';
|
||||
return ctx;
|
||||
},
|
||||
interop_TextWidth: function(textStr, textLen) {
|
||||
var text = UTF8ArrayToString(HEAPU8, textStr, textLen);
|
||||
var ctx = window.FONT_CONTEXT;
|
||||
var data = ctx.measureText(text);
|
||||
return Math.ceil(data.width)|0;
|
||||
},
|
||||
interop_TextDraw: function(textStr, textLen, bmp, dstX, dstY, shadow) {
|
||||
var text = UTF8ArrayToString(HEAPU8, textStr, textLen);
|
||||
var ctx = window.FONT_CONTEXT;
|
||||
|
||||
// resize canvas if necessary so test fits
|
||||
var data = ctx.measureText(text);
|
||||
var text_width = Math.ceil(data.width)|0;
|
||||
if (text_width > ctx.canvas.width)
|
||||
ctx.canvas.width = text_width;
|
||||
|
||||
var text_offset = 0.0;
|
||||
ctx.fillStyle = "#ffffff";
|
||||
if (shadow) {
|
||||
text_offset = 1.3;
|
||||
ctx.fillStyle = "#7f7f7f";
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
ctx.fillText(text, text_offset, text_offset);
|
||||
|
||||
bmp = bmp|0;
|
||||
dstX = dstX|0;
|
||||
dstY = dstY|0;
|
||||
|
||||
var dst_pixels = HEAP32[(bmp + 0|0)>>2] + (dstX << 2);
|
||||
var dst_width = HEAP32[(bmp + 4|0)>>2];
|
||||
var dst_height = HEAP32[(bmp + 8|0)>>2];
|
||||
|
||||
// TODO not all of it
|
||||
var src = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height);
|
||||
var src_pixels = src.data;
|
||||
var src_width = src.width|0;
|
||||
var src_height = src.height|0;
|
||||
|
||||
var img_width = Math.min(src_width, dst_width);
|
||||
var img_height = Math.min(src_height, dst_height);
|
||||
|
||||
for (var y = 0; y < img_height; y++)
|
||||
{
|
||||
var yy = y + dstY;
|
||||
if (yy < 0 || yy >= dst_height) continue;
|
||||
|
||||
var src_row = (y *(src_width << 2))|0;
|
||||
var dst_row = dst_pixels + (yy*(dst_width << 2))|0;
|
||||
|
||||
for (var x = 0; x < img_width; x++)
|
||||
{
|
||||
var xx = x + dstX;
|
||||
if (xx < 0 || xx >= dst_width) continue;
|
||||
|
||||
HEAPU8[dst_row + (x<<2)+0] = src_pixels[src_row + (x<<2)+0];
|
||||
HEAPU8[dst_row + (x<<2)+1] = src_pixels[src_row + (x<<2)+1];
|
||||
HEAPU8[dst_row + (x<<2)+2] = src_pixels[src_row + (x<<2)+2];
|
||||
HEAPU8[dst_row + (x<<2)+3] = src_pixels[src_row + (x<<2)+3];
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user