// SPDX-License-Identifier: MPL-2.0 #include #include #include #include #include #include #include #include #define STB_IMAGE_IMPLEMENTATION #include "stb_image.h" using namespace std; namespace fs=filesystem; struct color { uint8_t r,g,b; }; struct pixel { bool shade_1; bool check_1; bool shade_2; bool check_2; bool shade_3; bool check_3; bool shade_4; bool enabled; }; struct character { uint32_t codepoint; vector data; }; struct fbm_header { uint8_t sig[3]={'F','B','M'}; uint8_t encoding; uint32_t charnum; uint8_t width; uint8_t height; }; uint32_t charname_to_uint32(string charname) { uint32_t value=0; stringstream ss; ss<>value; int shift=(8-charname.size())*4; value<<=shift; return value; } int get_shade_from_color(const color &c,const color gradient[16]) { for (int i=0;i<16;++i) { if (gradient[i].r==c.r && gradient[i].g==c.g && gradient[i].b==c.b) { return i; } } return -1; } uint8_t pixel_to_byte(pixel p) { uint8_t out=0x00; out|=(uint8_t)p.shade_1<<7; out|=(uint8_t)p.check_1<<6; out|=(uint8_t)p.shade_2<<5; out|=(uint8_t)p.check_2<<4; out|=(uint8_t)p.shade_3<<3; out|=(uint8_t)p.check_3<<2; out|=(uint8_t)p.shade_4<<1; out|=(uint8_t)p.enabled; return out; } map> chars_data; vector known_encoding={"ascii","utf8","utf16"}; int main(int argc,char **argv) { if (argc!=5) { cout<<"[Fontgen] Error: wrong amount of arguments."<(bg))) { cout<<"[Fontgen] Error: invalid background color."<(ft))) { cout<<"[Fontgen] Error: invalid font color."<(std::stoi(bg_color.substr(1,2),nullptr,16)); start.g=static_cast(std::stoi(bg_color.substr(3,2),nullptr,16)); start.b=static_cast(std::stoi(bg_color.substr(5,2),nullptr,16)); end.r=static_cast(std::stoi(ft_color.substr(1,2),nullptr,16)); end.g=static_cast(std::stoi(ft_color.substr(3,2),nullptr,16)); end.b=static_cast(std::stoi(ft_color.substr(5,2),nullptr,16)); color gradient[16]; for (int i=0;i<16;++i) { gradient[i].r=start.r+i*(end.r-start.r)/15.0f; gradient[i].g=start.g+i*(end.g-start.g)/15.0f; gradient[i].b=start.b+i*(end.b-start.b)/15.0f; } string encoding=string(argv[3]); if (find(known_encoding.begin(),known_encoding.end(),encoding)==known_encoding.end()) { cout<<"[Fontgen] Error: encoding not supported."<8) { cout<<"[Fontgen] Warning: "< pixels(data,data+w*h*channel); stbi_image_free(data); chars_data[key]=std::move(pixels); i++; } vector characters; for (auto it:chars_data) { character chara; chara.codepoint=it.first; uint8_t byte1=(chara.codepoint>>24) & 0xFF; uint8_t byte2=(chara.codepoint>>16) & 0xFF; uint8_t byte3=(chara.codepoint>>8) & 0xFF; bool pcheck_1=(byte1>>1) & 1; bool pcheck_2=(byte2>>3) & 1; bool pcheck_3=(byte3>>5) & 1; for (int y=0;y15 || i<0) { cout<<"[Fontgen] Error: found a color that isn't in shade map. Codepoint that caused the error: "<>3)&1; p.shade_2=(shade>>2)&1; p.shade_3=(shade>>1)&1; p.shade_4=(shade>>0)&1; if (shade!=0) { p.enabled=true; } else { p.enabled=false; } p.check_1=pcheck_1; p.check_2=pcheck_2; p.check_3=pcheck_3; uint8_t byte=pixel_to_byte(p); chara.data.push_back(byte); } } characters.push_back(chara); } fbm_header header; header.charnum=(uint32_t)characters.size(); if (width>255 || width<1) { cout<<"[Fontgen] Error: width isn't between 1 and 255."<255 || height<1) { cout<<"[Fontgen] Error: height isn't between 1 and 255."< fbm_font; size_t charsize=4+header.width*header.height; fbm_font.resize(10+header.charnum*charsize); memcpy(fbm_font.data(),header.sig,3); memcpy(fbm_font.data()+3,&header.encoding,1); memcpy(fbm_font.data()+4,&header.charnum,4); memcpy(fbm_font.data()+8,&header.width,1); memcpy(fbm_font.data()+9,&header.height,1); for (int i=0;i(fbm_font.data()),fbm_font.size()); fileout.close(); cout<<"[Fontgen] Successfully generated font.fbm ("<