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

Add "Show String Picture" #2870

merged 16 commits into from
Mar 13, 2023

Conversation

Ghabry
Copy link
Member

@Ghabry Ghabry commented Dec 7, 2022

Depends on #2914 merge it first

WIP PR to get some feedback from testers in :)

https://easyrpg.org/play/pr2870/?game=strpic TestCase. Sound is messed up. Likely uses the Maniac extension to do this. Well is a good test for this soon

Incompatible change

Font location

Maniac Patch loads from the Windows font directory. Loading fonts in a cross platform way for all operating systems is alot of work so I decided to not support this.

Instead the Font is searched for in the Font folder of the game. Supported are all fonts that FreeType supports. The name must be the same as the one specified in the Show String Picture command.

To match with typical font naming conventions the search order is:

  1. (only when bold & italic) FONT_NAME-BoldItalic
  2. (only when bold) FONT_NAME-Bold
  3. (only when italic) FONT_NAME-Italic
  4. FONT_NAME-Regular
  5. FONT_NAME

Savegames

The StrPics are loaded and saved. However the way how the save data is structured is incompatible to the Maniac approach. I could have been compatible here but I want to have more flexibility for further custom Window functionality.

Using the built-in font

The built-in font is a bitmap font and does not support scaling.

Though you can replace the built-in font by providing "Font/Font.ttf" and "Font/Font2.ttf" depending on the system graphic font setting. Then scaling will work.

Known issues, do not report them, I work on them:

  • Gradient looks broken for larger font sizes
  • Disable Text Gradient option unimplemented
  • Built-in & ExFont is not scaled to larger resolutions (though this will usually look bad)
  • Emscripten Async loading missing
  • When using the same font with different sizes the rendering looks wrong (the font is shared to save memory). My guess is that the size HarfBuzz uses becomes desynced with the size FreeType uses.
  • The "pad to N digits" (I think this was \d[n]) is not supported yet

New features

You can translate the text with lcftrans :)

Full Harfbuzz shaping support for rendering complex scripts.

Not planned

"The rendering is not pixel perfect to Maniacs". Well yes. This is just how fonts work. FreeType renders them a bit different. Nothing I can do here. But the size and position of the window when using "auto" should be the same in both engines.

Loading fonts installed on the current system.

The letter spacing option is not supported because this is not supported by HarfBuzz and doing it manual will fail for any non-trivial case (that needs some kind of shaping logic).

Bold/Italic: Will only work when the font provides a bold/italic typeface. No automatic transformation is happening.

Implementation is through a new class Game_Window which provides more flexibility when we add even more event controlled window functionality later.
By converting from pt to px
These are used to store StringPictures in an incompatible but more flexible way.

Removed the sprites deque as I'm unsure what the purpose of this queue is.
Makes the window interaction easier to implement.
@Ghabry Ghabry added this to the 0.7.1 milestone Dec 7, 2022
@Ghabry Ghabry changed the title WIP: Add "Show String Picture" WIP: Add "Show String Picture" liblcf #445 Dec 7, 2022
@Ghabry
Copy link
Member Author

Ghabry commented Dec 7, 2022

Needs liblcf changes so our CI has some issues building it

I built Windows manually:

Windows (x64) build for testing: Player.zip Outdated see next comment

@Ghabry
Copy link
Member Author

Ghabry commented Dec 7, 2022

New exe with this patch (Old text lines were not removed, wups :)):

Player.zip

diff --git a/src/game_windows.cpp b/src/game_windows.cpp
index cad84c1b..3cae08ad 100644
--- a/src/game_windows.cpp
+++ b/src/game_windows.cpp
@@ -87,6 +87,8 @@ Game_Windows::Window_User* Game_Windows::GetWindowPtr(int id) {
 }

 bool Game_Windows::Window_User::Create(const WindowParams& params) {
+       Erase();
+
        data.width = params.width;
        data.height = params.height;
        data.system_name = lcf::DBString(params.system_name);

@BlisterB
Copy link
Member

BlisterB commented Dec 8, 2022

Display position Top-Left doesn't seem to be correctly positioned
RPG_RT
EasyRPG
Code

@MackValentine
Copy link
Contributor

Hi !
I found 2 bug with StringPic :

the origin is not taken into consideration
To fix it I just add "ApplyOrigin(false);" inside the "AttachWindow" function

If you use a StringPic, then a normal Picture with the same ID, the Picture will keep the StringPic inside the "new" Picture
To fix it I just add "data.easyrpg_type = lcf::rpg::SavePicture::EasyRpgType_default;" at the beginning of the "Show" function

( Sorry I'm really a noob with Git, I don't know how I can explain better >< )

@Ghabry Ghabry force-pushed the maniac/stringpic branch 2 times, most recently from 45a97a0 to 7e7fce9 Compare December 22, 2022 22:12
@Ghabry
Copy link
Member Author

Ghabry commented Dec 22, 2022

@MackValentine thanks I added your fixes

@MackValentine
Copy link
Contributor

I found some other bugs :
1/ ExFont is broken
2/ When the Picture Size is on Constant / Variable / Variable ID, if width or height is a 0, it should be calculated, not 0
3/ if you use the Auto size, and you write \c[X], the size is misscalculated
4/ Position of the text when the window back is disabled ( no margin / no draw frame ) is not correct ( It's a little too high, and if you select a "Right" origin, it's too far to the left )

https://github.com/MackValentine/easyrpg-player-maniacs/blob/master/src/game_windows.cpp
In the Game_Windows::Window_User::Refresh i made some change to try a correction for 2/3

@fdelapena fdelapena added the Awaiting Rebase Pull requests with conflicting files due to former merge label Feb 24, 2023
@Ghabry Ghabry force-pushed the maniac/stringpic branch from cc2693f to 5c83433 Compare March 7, 2023 15:10
@Ghabry Ghabry force-pushed the maniac/stringpic branch from 5c83433 to 27160a9 Compare March 7, 2023 15:42
@Ghabry
Copy link
Member Author

Ghabry commented Mar 7, 2023

Pretty annoying to add but StringPic works now in the web player:

image

@Ghabry
Copy link
Member Author

Ghabry commented Mar 7, 2023

@MackValentine

/1 is now resolved

/3 is imo a bug in Maniac Patch. It adds space for a command that should be zero space. So I won't implement this.

edit: now also /2 and /4 are fixed

@Ghabry Ghabry removed the Awaiting Rebase Pull requests with conflicting files due to former merge label Mar 7, 2023
@Ghabry
Copy link
Member Author

Ghabry commented Mar 7, 2023

more bugs in Maniac ShowStringPic: ExFont adds a full-width space after it 🤷

$ABlabla
blabla$a

image

Player does not because because there is no space in the text:

image

- size autocalc when width or height are 0
- system graphic always loaded
- always correct system graphic used
- style (no shadow etc.) correctly applied
- drawing without border margin works
@Ghabry
Copy link
Member Author

Ghabry commented Mar 8, 2023

jenkins: test this please

@Ghabry Ghabry removed the Has PR Dependencies This PR depends on another PR label Mar 8, 2023
@Ghabry Ghabry added the Has PR Dependencies This PR depends on another PR label Mar 8, 2023
@Ghabry Ghabry force-pushed the maniac/stringpic branch from d52137b to c47f7dc Compare March 8, 2023 10:17
@Ghabry Ghabry changed the title WIP: Add "Show String Picture" liblcf #445 WIP: Add "Show String Picture" Mar 8, 2023
@Ghabry Ghabry force-pushed the maniac/stringpic branch from c47f7dc to ffb660e Compare March 8, 2023 10:19
@Ghabry Ghabry changed the title WIP: Add "Show String Picture" Add "Show String Picture" Mar 8, 2023
@Ghabry Ghabry marked this pull request as ready for review March 8, 2023 10:21
@Ghabry
Copy link
Member Author

Ghabry commented Mar 8, 2023

I'm still totally confused concerning the font metrics.

As already noticed earlier there are multiple confusions about pt/px in the layouting of the text.

Found another one:

The ExFont is automatically rescaled but because it is not a font (so not handled by WinApi) it uses the "pt" value verbatim as "px" without converting it.

So for larger fonts with ExFont you get nonsense like this (much larger than the rest):

grafik


diff for resizable ExFont I gave up on for now because the metrics are so fcked up

diff --git a/src/cache.cpp b/src/cache.cpp
index a6ae6693f..f2c379e91 100644
--- a/src/cache.cpp
+++ b/src/cache.cpp
@@ -385,12 +385,29 @@ BitmapRef Cache::System(StringView file) {
 	return LoadBitmap<Material::System>(file);
 }
 
-BitmapRef Cache::Exfont() {
-	const auto key = MakeHashKey("ExFont", "ExFont", false);
+BitmapRef Cache::Exfont(int size) {
+	const auto key = MakeHashKey("ExFont", std::to_string(size), false);
 
 	auto it = cache.find(key);
 
 	if (it == cache.end()) {
+		if (size != 12) {
+			// Allow ExFont of custom size
+			auto is = FileFinder::OpenImage("ExFont", "ExFont" + std::to_string(size));
+			if (is) {
+				auto bmp = Bitmap::Create(std::move(is), true);
+				if (bmp) {
+					return AddToCache(key, bmp);
+				}
+			}
+
+			// Not found: Resize the original (result will look bad)
+			auto bmp = Bitmap::Create(size, size, true);
+			auto exfont = Exfont(12);
+			bmp->ZoomOpacityBlit(0, 0, 0, 0, *exfont, exfont->GetRect(), size / 12.0, size / 12.0, Opacity::Opaque());
+			return AddToCache(key, bmp);
+		}
+
 		// Allow overwriting of built-in exfont with a custom ExFont image file
 		// exfont_custom is filled by Player::CreateGameObjects
 		BitmapRef exfont_img;
diff --git a/src/cache.h b/src/cache.h
index 5ea53a5cf..c288be5bf 100644
--- a/src/cache.h
+++ b/src/cache.h
@@ -43,7 +43,7 @@ namespace Cache {
 	BitmapRef Battlecharset(StringView filename);
 	BitmapRef Battleweapon(StringView filename);
 	BitmapRef Charset(StringView filename);
-	BitmapRef Exfont();
+	BitmapRef Exfont(int size = 12);
 	BitmapRef Faceset(StringView filename);
 	BitmapRef Frame(StringView filename, bool transparent = true);
 	BitmapRef Gameover(StringView filename);
diff --git a/src/font.cpp b/src/font.cpp
index bc6ae2a8c..99adc2efe 100644
--- a/src/font.cpp
+++ b/src/font.cpp
@@ -185,7 +185,7 @@ namespace {
 			Rect vGetSize(char32_t glyph) const override;
 			GlyphRet vRender(char32_t glyph) const override;
 		private:
-			mutable BitmapRef bm;
+			mutable BitmapRef bm12;
 	};
 
 	/** FreeType Font Cache */
@@ -792,38 +792,44 @@ ExFont::ExFont() : Font("exfont", HEIGHT, false, false) {
 FontRef Font::exfont = std::make_shared<ExFont>();
 
 Font::GlyphRet ExFont::vRender(char32_t glyph) const {
-	if (EP_UNLIKELY(!bm)) { bm = Bitmap::Create(WIDTH, HEIGHT, true); }
-	auto exfont = Cache::Exfont();
+	if (EP_UNLIKELY(!bm12)) { bm12 = Bitmap::Create(WIDTH, HEIGHT, true); }
+
+	auto bm = bm12;
+	if (EP_UNLIKELY(current_style.size != 12)) {
+		bm = Bitmap::Create(current_style.size, current_style.size, true);
+	}
+
+	auto exfont = Cache::Exfont(current_style.size);
 
 	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 };
+		return { bm, {current_style.size, 0}, {0, 0}, false };
 	}
 
 	glyph = is_lower ? (glyph - 'a' + 26) : (glyph - 'A');
 
-	Rect const rect((glyph % 13) * WIDTH, (glyph / 13) * HEIGHT, WIDTH, HEIGHT);
+	Rect const rect((glyph % 13) * current_style.size, (glyph / 13) * current_style.size, current_style.size, current_style.size);
 	bm->Clear();
 	bm->Blit(0, 0, *exfont, rect, Opacity::Opaque());
 
 	// EasyRPG Extension: Support for colored ExFont
 	bool has_color = false;
 	const auto* pixels = reinterpret_cast<uint8_t*>(bm->pixels());
-	// For performance reasons only check the red channel of every 4th pixel (16 = 4 * 4 RGBA pixel) for color
+	// For performance reasons only check every 4th pixel for color
 	for (int i = 0; i < bm->pitch() * bm->height(); i += 16) {
-		auto pixel = pixels[i];
-		if (pixel != 0 && pixel != 255) {
+		auto pixel = *reinterpret_cast<const uint32_t*>(pixels + i);
+		if (pixel != 0 && pixel != 0xFFFFFFFF) {
 			has_color = true;
 			break;
 		}
 	}
 
-	return { bm, {WIDTH, 0}, {0, 0}, has_color };
+	return { bm, {current_style.size, 0}, {0, 0}, has_color };
 }
 
 Rect ExFont::vGetSize(char32_t) const {
-	return Rect(0, 0, WIDTH, HEIGHT);
+	return { 0, 0, current_style.size, current_style.size };
 }

@fdelapena fdelapena removed the Has PR Dependencies This PR depends on another PR label Mar 9, 2023
Copy link
Contributor

@fdelapena fdelapena left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A great foundation on free text rendering 👍.

@Ghabry Ghabry force-pushed the maniac/stringpic branch from 7034b03 to 1ea24c6 Compare March 13, 2023 13:40
@fdelapena fdelapena merged commit f928608 into EasyRPG:master Mar 13, 2023
@Ghabry Ghabry deleted the maniac/stringpic branch June 12, 2023 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

4 participants