Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add "Show String Picture" #2870

Merged
merged 16 commits into from
Mar 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ add_library(${PROJECT_NAME} STATIC
src/game_variables.h
src/game_vehicle.cpp
src/game_vehicle.h
src/game_windows.cpp
src/game_windows.h
src/graphics.cpp
src/graphics.h
src/hslrgb.cpp
Expand Down
2 changes: 2 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ libeasyrpg_player_a_SOURCES = \
src/game_variables.h \
src/game_vehicle.cpp \
src/game_vehicle.h \
src/game_windows.cpp \
src/game_windows.h \
src/graphics.cpp \
src/graphics.h \
src/hslrgb.cpp \
Expand Down
15 changes: 11 additions & 4 deletions src/async_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,9 +284,15 @@ void FileRequestAsync::Start() {
if (it != file_mapping.end()) {
request_path += it->second;
} else {
// Fall through if not found, will fail in the ajax request
Output::Debug("{} not in index.json", modified_path);
request_path += path;
if (file_mapping.empty()) {
// index.json not fetched yet, fallthrough and fetch
request_path += path;
} else {
// Fire immediately (error)
Output::Debug("{} not in index.json", modified_path);
DownloadDone(false);
return;
}
}

// URL encode %, # and +
Expand Down Expand Up @@ -341,10 +347,11 @@ FileRequestBinding FileRequestAsync::Bind(std::function<void(FileRequestResult*)
}

void FileRequestAsync::CallListeners(bool success) {
FileRequestResult result { directory, file, success };
FileRequestResult result { directory, file, -1, success };

for (auto& listener : listeners) {
if (!listener.first.expired()) {
result.request_id = *listener.first.lock();
(listener.second)(&result);
} else {
Output::Debug("Request cancelled: {}", GetPath());
Expand Down
2 changes: 2 additions & 0 deletions src/async_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,13 @@ class FileRequestAsync {
* Contains the result of an async request.
* directory: Directory name
* file: Name of requested file
* request_id assigned to the callback that fired
* success: true if requested was successful, otherwise false.
*/
struct FileRequestResult {
const std::string& directory;
const std::string& file;
int request_id;
bool success;
};

Expand Down
15 changes: 15 additions & 0 deletions src/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,21 @@ void Bitmap::CheckPixels(uint32_t flags) {
}
}

Color Bitmap::GetColorAt(int x, int y) const {
if (x < 0 || x >= width() || y < 0 || y >= height()) {
return {};
}

Color color;
int pix = y * width();

const uint8_t* pos = &reinterpret_cast<const uint8_t*>(pixels())[y * pitch() + x * bpp()];
uint32_t pixel = *reinterpret_cast<const uint32_t*>(pos);
format.uint32_to_rgba(pixel, color.red, color.green, color.blue, color.alpha);

return color;
}

void Bitmap::HueChangeBlit(int x, int y, Bitmap const& src, Rect const& src_rect_, double hue_) {
Rect dst_rect(x, y, 0, 0), src_rect = src_rect_;

Expand Down
7 changes: 7 additions & 0 deletions src/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,13 @@ class Bitmap {

void CheckPixels(uint32_t flags);

/**
* @param x x-coordinate
* @param y y-coordinate
* @return color at the pixel location
*/
Color GetColorAt(int x, int y) const;

/**
* Draws text to bitmap using the Font::Default() font.
*
Expand Down
5 changes: 2 additions & 3 deletions src/filefinder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -355,9 +355,8 @@ std::string FileFinder::FindSound(StringView name) {
}

std::string FileFinder::FindFont(StringView name) {
std::string path = Game().FindFile({ MakePath("Font", name), FONTS_TYPES, 1, true });

return path;
DirectoryTree::Args args = { MakePath("Font", name), FONTS_TYPES, 1, true };
return find_generic(args);
}

Filesystem_Stream::InputStream open_generic(StringView dir, StringView name, DirectoryTree::Args& args) {
Expand Down
57 changes: 43 additions & 14 deletions src/font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,9 @@ void Font::Dispose() {
Font::Font(StringView name, int size, bool bold, bool italic)
: name(ToString(name))
{
original_style = {size, bold, italic, true};
original_style.size = size;
original_style.bold = bold;
original_style.italic = italic;
current_style = original_style;
}

Expand All @@ -626,7 +628,10 @@ Rect Font::GetSize(char32_t glyph) const {
return {};
}

return vGetSize(glyph);
Rect size = vGetSize(glyph);
size.x += current_style.letter_spacing;

return size;
}

Point Font::Render(Bitmap& dest, int const x, int const y, const Bitmap& sys, int color, char32_t glyph) const {
Expand Down Expand Up @@ -655,24 +660,32 @@ Point Font::Render(Bitmap& dest, int const x, int const y, const Bitmap& sys, in

src_x = color % 10 * 16 + 2;
src_y = color / 10 * 16 + 48 + 16 - 12 - gret.offset.y;

// When the glyph is large the system graphic color mask will be outside the rectangle
// Move the mask slightly up to avoid this
int offset = gret.bitmap->height() - gret.offset.y;
if (offset > 12) {
src_y -= offset - 12;
}
} else {
src_x = 16;
src_y = 32;
}

if (!gret.has_color) {
dest.MaskedBlit(rect, *gret.bitmap, 0, 0, sys, src_x, src_y);
if (current_style.draw_gradient) {
// When the glyph is large the system graphic color mask will be outside the rectangle
// Move the mask slightly up to avoid this
int offset = gret.bitmap->height() - gret.offset.y;
if (offset > 12) {
src_y -= offset - 12;
}

dest.MaskedBlit(rect, *gret.bitmap, 0, 0, sys, src_x, src_y);
} else {
auto col = sys.GetColorAt(current_style.color_offset.x + src_x, current_style.color_offset.y + src_y);
auto col_bm = Bitmap::Create(gret.bitmap->width(), gret.bitmap->height(), col);
dest.MaskedBlit(rect, *gret.bitmap, 0, 0, *col_bm, 0, 0);
}
} else {
dest.Blit(rect.x, rect.y, *gret.bitmap, gret.bitmap->GetRect(), Opacity::Opaque());
}

gret.advance.x += current_style.letter_spacing;

return gret.advance;
}

Expand Down Expand Up @@ -720,7 +733,8 @@ Point Font::Render(Bitmap& dest, int const x, int const y, const Bitmap& sys, in
dest.Blit(rect.x, rect.y, *gret.bitmap, gret.bitmap->GetRect(), Opacity::Opaque());
}

return shape.advance;
Point advance = { shape.advance.x + current_style.letter_spacing, shape.advance.y };
return advance;
}

Point Font::Render(Bitmap& dest, int x, int y, Color const& color, char32_t glyph) const {
Expand All @@ -733,6 +747,8 @@ Point Font::Render(Bitmap& dest, int x, int y, Color const& color, char32_t glyp
auto rect = Rect(x, y, gret.bitmap->width(), gret.bitmap->height());
dest.MaskedBlit(rect, *gret.bitmap, 0, 0, color);

gret.advance.x += current_style.letter_spacing;

return gret.advance;
}

Expand All @@ -750,21 +766,27 @@ void Font::SetFallbackFont(FontRef fallback_font) {
this->fallback_font = fallback_font;
}

bool Font::IsStyleApplied() const {
return style_applied;
}

Font::Style Font::GetCurrentStyle() const {
return current_style;
}

Font::StyleScopeGuard Font::ApplyStyle(Style new_style) {
vApplyStyle(new_style);
current_style = new_style;
style_applied = true;

return lcf::ScopeGuard<std::function<void()>>([&]() {
vApplyStyle(original_style);
current_style = original_style;
style_applied = false;
});
}

ExFont::ExFont() : Font("exfont", 12, false, false) {
ExFont::ExFont() : Font("exfont", HEIGHT, false, false) {
}

FontRef Font::exfont = std::make_shared<ExFont>();
Expand All @@ -773,8 +795,15 @@ Font::GlyphRet ExFont::vRender(char32_t glyph) const {
if (EP_UNLIKELY(!bm)) { bm = Bitmap::Create(WIDTH, HEIGHT, true); }
auto exfont = Cache::Exfont();

// Remove offset introduced by Utils::ExFontNext to bypass ControlCharacter detection
glyph -= 32;
bool is_lower = (glyph >= 'a' && glyph <= 'z');
bool is_upper = (glyph >= 'A' && glyph <= 'Z');

if (!is_lower && !is_upper) {
// Invalid ExFont
return { bm, {WIDTH, 0}, {0, 0}, false };
}

glyph = is_lower ? (glyph - 'a' + 26) : (glyph - 'A');

Rect const rect((glyph % 13) * WIDTH, (glyph / 13) * HEIGHT, WIDTH, HEIGHT);
bm->Clear();
Expand Down
17 changes: 16 additions & 1 deletion src/font.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,16 @@ class Font {
/** Whether to render text in italic (currently unsupported) */
bool italic = false;
/** Whether to render a drop shadow */
bool draw_shadow = false;
bool draw_shadow = true;
/** Whether to draw the system color using a gradient */
bool draw_gradient = true;
/** When draw_gradient is false specifies the pixel of the current system color to use */
Point color_offset = {};
/**
* Specifies how far the drawing cursor is advanced in x direction after rendering a glyph.
* This will yield incorrect results for anything that involves complex shaping.
**/
int letter_spacing = 0;
};

virtual ~Font() = default;
Expand Down Expand Up @@ -169,6 +178,11 @@ class Font {

using StyleScopeGuard = lcf::ScopeGuard<std::function<void()>>;

/**
* @return Whether a custom style is currently active
*/
bool IsStyleApplied() const;

/**
* Returns the current font style used for rendering.
*
Expand Down Expand Up @@ -225,6 +239,7 @@ class Font {
Font(StringView name, int size, bool bold, bool italic);

std::string name;
bool style_applied = false;
Style original_style;
Style current_style;
FontRef fallback_font;
Expand Down
Loading