[Scummvm-git-logs] scummvm master -> 448bb2d77ef4e49aaaa4ad5298ab07fa1737115a
dreammaster
noreply at scummvm.org
Tue Mar 15 04:52:55 UTC 2022
This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
399a89825f AGS: New auto outline supports AA TTFs in 32- and 16-bit games
641ade11fa AGS: Fixed crash in auto outline in case of empty text argument
fd0e16ffc3 AGS: implemented stencil cache per Font for automatic outlining
8b8bc2f32f AGS: support reading font extension "v360_fonts"
255a739eca AGS: Encapsulate game object draw caches in draw.cpp
2d995bbe07 AGS: Simplified use of ReplaceBitmapWithSupportedFormat()
448bb2d77e AGS: Moved "LucasFan" font hack to game_init, enable for all systems
Commit: 399a89825f4c2be0d3693924bb37c90d32849a89
https://github.com/scummvm/scummvm/commit/399a89825f4c2be0d3693924bb37c90d32849a89
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:04:07-07:00
Commit Message:
AGS: New auto outline supports AA TTFs in 32- and 16-bit games
>From upstream cae84d689019313cad49b6dca7e916866b90e49e
Changed paths:
engines/ags/engine/ac/display.cpp
engines/ags/engine/gfx/blender.cpp
engines/ags/engine/gfx/blender.h
engines/ags/shared/gfx/allegro_bitmap.cpp
engines/ags/shared/gfx/allegro_bitmap.h
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index a41fe099027..77e70cfdef0 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -43,6 +43,7 @@
#include "ags/engine/ac/system.h"
#include "ags/engine/ac/top_bar_settings.h"
#include "ags/engine/debugging/debug_log.h"
+#include "ags/engine/gfx/blender.h"
#include "ags/shared/gui/gui_button.h"
#include "ags/shared/gui/gui_main.h"
#include "ags/engine/main/game_run.h"
@@ -452,31 +453,46 @@ bool ShouldAntiAliasText() {
}
void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *texx, int &xxp, int &yyp) {
- using AGS::Shared::kBitmap_Transparency;
-
- int thickness = _GP(game).fonts.at(font).AutoOutlineThickness;
- auto style = _GP(game).fonts.at(font).AutoOutlineStyle;
+ int const thickness = _GP(game).fonts.at(font).AutoOutlineThickness;
+ auto const style = _GP(game).fonts.at(font).AutoOutlineStyle;
if (thickness <= 0)
return;
+ // 16-bit games should use 32-bit stencils to keep anti-aliasing working
+ // because 16-bit blending works correctly if there's an actual color
+ // on the destination bitmap (and our intermediate bitmaps are transparent).
+ int const ds_cd = ds->GetColorDepth();
+ bool const antialias = ds_cd >= 16 && _GP(game).options[OPT_ANTIALIASFONTS] != 0 && !is_bitmap_font(font);
+ int const stencil_cd = antialias ? 32 : ds_cd;
+ if (antialias) // This is to make sure TTFs render proper alpha channel in 16-bit games too
+ color |= makeacol32(0, 0, 0, 0xff);
+
size_t const t_width = wgettextwidth(texx, font);
size_t const t_height = wgettextheight(texx, font);
- if (t_width == 0 || t_height == 0)
- return;
-
- Bitmap *outline_stencil =
- CreateTransparentBitmap(t_width, t_height + 2 * thickness, ds->GetColorDepth());
- Bitmap *texx_stencil =
- CreateTransparentBitmap(t_width, t_height, ds->GetColorDepth());
- if (!outline_stencil || !texx_stencil)
+ Bitmap texx_stencil, outline_stencil;
+ texx_stencil.CreateTransparent(t_width, t_height, stencil_cd);
+ outline_stencil.CreateTransparent(t_width, t_height + 2 * thickness, stencil_cd);
+ if (outline_stencil.IsNull() || texx_stencil.IsNull())
return;
- wouttextxy(texx_stencil, 0, 0, font, color, texx);
+ wouttextxy(&texx_stencil, 0, 0, font, color, texx);
+
+ // Anti-aliased TTFs require to be alpha-blended, not blit,
+ // or the alpha values will be plain copied and final image will be broken.
+ void(Bitmap:: * pfn_drawstencil)(Bitmap * src, int dst_x, int dst_y);
+ if (antialias) { // NOTE: we must set out blender AFTER wouttextxy, or it will be overidden
+ set_argb2any_blender();
+ pfn_drawstencil = &Bitmap::TransBlendBlt;
+ } else {
+ pfn_drawstencil = &Bitmap::MaskedBlit;
+ }
// move start of text so that the outline doesn't drop off the bitmap
xxp += thickness;
int const outline_y = yyp;
yyp += thickness;
+ // What we do here: first we paint text onto outline_stencil offsetting vertically;
+ // then we paint resulting outline_stencil onto final dest offsetting horizontally.
int largest_y_diff_reached_so_far = -1;
for (int x_diff = thickness; x_diff >= 0; x_diff--) {
// Integer arithmetics: In the following, we use terms k*(k + 1) to account for rounding.
@@ -485,24 +501,21 @@ void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *
if (FontInfo::kRounded == style)
y_term_limit -= x_diff * x_diff;
- // extend the outline stencil to the top and bottom
+ // Extend the outline stencil to the top and bottom
for (int y_diff = largest_y_diff_reached_so_far + 1;
y_diff <= thickness && y_diff * y_diff <= y_term_limit;
y_diff++) {
- outline_stencil->Blit(texx_stencil, 0, thickness - y_diff, kBitmap_Transparency);
+ (outline_stencil.*pfn_drawstencil)(&texx_stencil, 0, thickness - y_diff);
if (y_diff > 0)
- outline_stencil->Blit(texx_stencil, 0, thickness + y_diff, kBitmap_Transparency);
+ (outline_stencil.*pfn_drawstencil)(&texx_stencil, 0, thickness + y_diff);
largest_y_diff_reached_so_far = y_diff;
}
- // stamp the outline stencil to the left and right of the text
- ds->Blit(outline_stencil, xxp - x_diff, outline_y, kBitmap_Transparency);
+ // Stamp the outline stencil to the left and right of the text
+ (ds->*pfn_drawstencil)(&outline_stencil, xxp - x_diff, outline_y);
if (x_diff > 0)
- ds->Blit(outline_stencil, xxp + x_diff, outline_y, kBitmap_Transparency);
+ (ds->*pfn_drawstencil)(&outline_stencil, xxp + x_diff, outline_y);
}
-
- delete texx_stencil;
- delete outline_stencil;
}
// Draw an outline if requested, then draw the text on top
diff --git a/engines/ags/engine/gfx/blender.cpp b/engines/ags/engine/gfx/blender.cpp
index fb15d581499..949060695e1 100644
--- a/engines/ags/engine/gfx/blender.cpp
+++ b/engines/ags/engine/gfx/blender.cpp
@@ -43,4 +43,9 @@ void set_opaque_alpha_blender() {
set_blender_mode(kOpaqueBlenderMode, 0, 0, 0, 0);
}
+void set_argb2any_blender() {
+ // TODO: Properly implement this new mode
+ set_blender_mode(kArgbToArgbBlender, 0, 0, 0, 0xff);
+}
+
} // namespace AGS3
diff --git a/engines/ags/engine/gfx/blender.h b/engines/ags/engine/gfx/blender.h
index 747186bf6e8..fd949fabf75 100644
--- a/engines/ags/engine/gfx/blender.h
+++ b/engines/ags/engine/gfx/blender.h
@@ -50,6 +50,8 @@ void set_my_trans_blender(int r, int g, int b, int a);
void set_additive_alpha_blender();
// Opaque alpha blender plain copies src over, applying opaque alpha value.
void set_opaque_alpha_blender();
+// Sets argb2argb for 32-bit mode, and provides appropriate funcs for blending 32-bit onto 15/16/24-bit destination
+void set_argb2any_blender();
} // namespace AGS3
diff --git a/engines/ags/shared/gfx/allegro_bitmap.cpp b/engines/ags/shared/gfx/allegro_bitmap.cpp
index c8552d07673..5d934da340d 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.cpp
+++ b/engines/ags/shared/gfx/allegro_bitmap.cpp
@@ -198,6 +198,10 @@ void Bitmap::Blit(Bitmap *src, int src_x, int src_y, int dst_x, int dst_y, int w
}
}
+void Bitmap::MaskedBlit(Bitmap *src, int dst_x, int dst_y) {
+ draw_sprite(_alBitmap, src->_alBitmap, dst_x, dst_y);
+}
+
void Bitmap::StretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask) {
BITMAP *al_src_bmp = src->_alBitmap;
// WARNING: For some evil reason Allegro expects dest and src bitmaps in different order for blit and draw_sprite
diff --git a/engines/ags/shared/gfx/allegro_bitmap.h b/engines/ags/shared/gfx/allegro_bitmap.h
index f067b04ff1b..b6bb3d9919b 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.h
+++ b/engines/ags/shared/gfx/allegro_bitmap.h
@@ -176,7 +176,9 @@ public:
// Draw other bitmap over current one
void Blit(Bitmap *src, int dst_x = 0, int dst_y = 0, BitmapMaskOption mask = kBitmap_Copy);
void Blit(Bitmap *src, int src_x, int src_y, int dst_x, int dst_y, int width, int height, BitmapMaskOption mask = kBitmap_Copy);
- // Copy other bitmap, stretching or shrinking its size to given values
+ // Draw other bitmap in a masked mode (kBitmap_Transparency)
+ void MaskedBlit(Bitmap *src, int dst_x, int dst_y);
+ // Draw other bitmap, stretching or shrinking its size to given values
void StretchBlt(Bitmap *src, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
void StretchBlt(Bitmap *src, const Rect &src_rc, const Rect &dst_rc, BitmapMaskOption mask = kBitmap_Copy);
// Antia-aliased stretch-blit
Commit: 641ade11fa4cc4daa89011dae028190dbd078a9d
https://github.com/scummvm/scummvm/commit/641ade11fa4cc4daa89011dae028190dbd078a9d
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:04:08-07:00
Commit Message:
AGS: Fixed crash in auto outline in case of empty text argument
>From upstream e3665a3c073e574d3e4fade869b3c0c3e88508e5
Changed paths:
engines/ags/engine/ac/display.cpp
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 77e70cfdef0..190e2ecc5e0 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -469,6 +469,9 @@ void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *
size_t const t_width = wgettextwidth(texx, font);
size_t const t_height = wgettextheight(texx, font);
+ if (t_width == 0 || t_height == 0)
+ return;
+
Bitmap texx_stencil, outline_stencil;
texx_stencil.CreateTransparent(t_width, t_height, stencil_cd);
outline_stencil.CreateTransparent(t_width, t_height + 2 * thickness, stencil_cd);
Commit: fd0e16ffc3d348e2e5fe9d89947c8956f7b5e098
https://github.com/scummvm/scummvm/commit/fd0e16ffc3d348e2e5fe9d89947c8956f7b5e098
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:04:08-07:00
Commit Message:
AGS: implemented stencil cache per Font for automatic outlining
>From upstream e32c4bf46b5f74b904ac491bb6017ceb8f8e2bbf
Changed paths:
engines/ags/engine/ac/display.cpp
engines/ags/shared/font/fonts.cpp
engines/ags/shared/font/fonts.h
engines/ags/shared/gfx/allegro_bitmap.cpp
engines/ags/shared/gfx/allegro_bitmap.h
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 190e2ecc5e0..4734132dac1 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -453,8 +453,9 @@ bool ShouldAntiAliasText() {
}
void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *texx, int &xxp, int &yyp) {
- int const thickness = _GP(game).fonts.at(font).AutoOutlineThickness;
- auto const style = _GP(game).fonts.at(font).AutoOutlineStyle;
+ const FontInfo &finfo = get_fontinfo(font);
+ int const thickness = finfo.AutoOutlineThickness;
+ auto const style = finfo.AutoOutlineStyle;
if (thickness <= 0)
return;
@@ -472,12 +473,14 @@ void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *
if (t_width == 0 || t_height == 0)
return;
- Bitmap texx_stencil, outline_stencil;
- texx_stencil.CreateTransparent(t_width, t_height, stencil_cd);
- outline_stencil.CreateTransparent(t_width, t_height + 2 * thickness, stencil_cd);
- if (outline_stencil.IsNull() || texx_stencil.IsNull())
- return;
- wouttextxy(&texx_stencil, 0, 0, font, color, texx);
+ // Prepare stencils
+ Bitmap *texx_stencil, *outline_stencil;
+ alloc_font_outline_buffers(font, &texx_stencil, &outline_stencil,
+ t_width, t_height, stencil_cd);
+ texx_stencil->ClearTransparent();
+ outline_stencil->ClearTransparent();
+ // Ready text stencil
+ wouttextxy(texx_stencil, 0, 0, font, color, texx);
// Anti-aliased TTFs require to be alpha-blended, not blit,
// or the alpha values will be plain copied and final image will be broken.
@@ -508,16 +511,16 @@ void wouttextxy_AutoOutline(Bitmap *ds, size_t font, int32_t color, const char *
for (int y_diff = largest_y_diff_reached_so_far + 1;
y_diff <= thickness && y_diff * y_diff <= y_term_limit;
y_diff++) {
- (outline_stencil.*pfn_drawstencil)(&texx_stencil, 0, thickness - y_diff);
+ (outline_stencil->*pfn_drawstencil)(texx_stencil, 0, thickness - y_diff);
if (y_diff > 0)
- (outline_stencil.*pfn_drawstencil)(&texx_stencil, 0, thickness + y_diff);
+ (outline_stencil->*pfn_drawstencil)(texx_stencil, 0, thickness + y_diff);
largest_y_diff_reached_so_far = y_diff;
}
// Stamp the outline stencil to the left and right of the text
- (ds->*pfn_drawstencil)(&outline_stencil, xxp - x_diff, outline_y);
+ (ds->*pfn_drawstencil)(outline_stencil, xxp - x_diff, outline_y);
if (x_diff > 0)
- (ds->*pfn_drawstencil)(&outline_stencil, xxp + x_diff, outline_y);
+ (ds->*pfn_drawstencil)(outline_stencil, xxp + x_diff, outline_y);
}
}
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index bc385ad262a..5451f57b140 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -37,17 +37,6 @@ namespace AGS3 {
using namespace AGS::Shared;
-namespace AGS {
-namespace Shared {
-
-Font::Font()
- : Renderer(nullptr)
- , Renderer2(nullptr) {
-}
-
-} // namespace Shared
-} // namespace AGS
-
FontInfo::FontInfo()
: Flags(0)
, SizePt(0)
@@ -346,6 +335,12 @@ void set_fontinfo(size_t fontNumber, const FontInfo &finfo) {
_GP(fonts)[fontNumber].Info = finfo;
}
+FontInfo get_fontinfo(size_t font_number) {
+ if (font_number < _GP(fonts).size())
+ return _GP(fonts)[font_number].Info;
+ return FontInfo();
+}
+
// Loads a font from disk
bool wloadfont_size(size_t fontNumber, const FontInfo &font_info) {
if (_GP(fonts).size() <= fontNumber)
@@ -386,10 +381,40 @@ void wgtprintf(Shared::Bitmap *ds, int xxx, int yyy, size_t fontNumber, color_t
wouttextxy(ds, xxx, yyy, fontNumber, text_color, tbuffer);
}
+void alloc_font_outline_buffers(size_t font_number,
+ Bitmap **text_stencil, Bitmap **outline_stencil,
+ int text_width, int text_height, int color_depth) {
+ if (font_number >= _GP(fonts).size())
+ return;
+ Font &f = _GP(fonts)[font_number];
+ const int thick = 2 * f.Info.AutoOutlineThickness;
+ if (f.TextStencil.IsNull() || (f.TextStencil.GetColorDepth() != color_depth) ||
+ (f.TextStencil.GetWidth() < text_width) || (f.TextStencil.GetHeight() < text_height)) {
+ int sw = f.TextStencil.IsNull() ? 0 : f.TextStencil.GetWidth();
+ int sh = f.TextStencil.IsNull() ? 0 : f.TextStencil.GetHeight();
+ sw = std::max(text_width, sw);
+ sh = std::max(text_height, sh);
+ f.TextStencil.Create(sw, sh, color_depth);
+ f.OutlineStencil.Create(sw, sh + thick, color_depth);
+ f.TextStencilSub.CreateSubBitmap(&f.TextStencil, RectWH(Size(text_width, text_height)));
+ f.OutlineStencilSub.CreateSubBitmap(&f.OutlineStencil, RectWH(Size(text_width, text_height + thick)));
+ } else {
+ f.TextStencilSub.ResizeSubBitmap(text_width, text_height);
+ f.OutlineStencilSub.ResizeSubBitmap(text_width, text_height + thick);
+ }
+ *text_stencil = &f.TextStencilSub;
+ *outline_stencil = &f.OutlineStencilSub;
+}
+
void wfreefont(size_t fontNumber) {
if (fontNumber >= _GP(fonts).size())
return;
+ _GP(fonts)[fontNumber].TextStencilSub.Destroy();
+ _GP(fonts)[fontNumber].OutlineStencilSub.Destroy();
+ _GP(fonts)[fontNumber].TextStencil.Destroy();
+ _GP(fonts)[fontNumber].OutlineStencil.Destroy();
+
if (_GP(fonts)[fontNumber].Renderer != nullptr)
_GP(fonts)[fontNumber].Renderer->FreeMemory(fontNumber);
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index 67d11513ed8..2c6bb129438 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -50,7 +50,7 @@ struct Font {
Bitmap TextStencil, TextStencilSub;
Bitmap OutlineStencil, OutlineStencilSub;
- Font();
+ Font() {}
};
} // namespace Shared
diff --git a/engines/ags/shared/gfx/allegro_bitmap.cpp b/engines/ags/shared/gfx/allegro_bitmap.cpp
index 5d934da340d..3ffd00e7a9f 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.cpp
+++ b/engines/ags/shared/gfx/allegro_bitmap.cpp
@@ -90,6 +90,16 @@ bool Bitmap::CreateSubBitmap(Bitmap *src, const Rect &rc) {
return _alBitmap != nullptr;
}
+bool Bitmap::ResizeSubBitmap(int width, int height) {
+ if (!isSubBitmap())
+ return false;
+ // TODO: can't clamp to parent size, because subs do not keep parent ref;
+ // might require amending allegro bitmap struct
+ _alBitmap->w = _alBitmap->cr = width;
+ _alBitmap->h = _alBitmap->cb = height;
+ return true;
+}
+
bool Bitmap::CreateCopy(Bitmap *src, int color_depth) {
if (Create(src->_alBitmap->w, src->_alBitmap->h, color_depth ? color_depth : bitmap_color_depth(src->_alBitmap))) {
blit(src->_alBitmap, _alBitmap, 0, 0, 0, 0, _alBitmap->w, _alBitmap->h);
diff --git a/engines/ags/shared/gfx/allegro_bitmap.h b/engines/ags/shared/gfx/allegro_bitmap.h
index b6bb3d9919b..18fab261b19 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.h
+++ b/engines/ags/shared/gfx/allegro_bitmap.h
@@ -57,6 +57,8 @@ public:
bool CreateTransparent(int width, int height, int color_depth = 0);
// Allow this object to share existing bitmap data
bool CreateSubBitmap(Bitmap *src, const Rect &rc);
+ // Resizes existing sub-bitmap within the borders of its parent
+ bool ResizeSubBitmap(int width, int height);
// Create a copy of given bitmap
bool CreateCopy(Bitmap *src, int color_depth = 0);
// TODO: a temporary solution for plugin support
Commit: 8b8bc2f32f048fff6f148f4953b6b3555931ba3c
https://github.com/scummvm/scummvm/commit/8b8bc2f32f048fff6f148f4953b6b3555931ba3c
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:04:08-07:00
Commit Message:
AGS: support reading font extension "v360_fonts"
>From upstream 668430c4d21e6c39ae4c1c3a7e5be2c3a0ad7062
Changed paths:
engines/ags/shared/ac/game_version.h
engines/ags/shared/game/main_game_file.cpp
diff --git a/engines/ags/shared/ac/game_version.h b/engines/ags/shared/ac/game_version.h
index b6e1cc1336e..37acb875118 100644
--- a/engines/ags/shared/ac/game_version.h
+++ b/engines/ags/shared/ac/game_version.h
@@ -113,6 +113,10 @@ Font custom line spacing.
Sprites have "real" resolution. Expanded FontInfo data format.
Option to allow legacy relative asset resolutions.
+3.6.0 :
+Format value is defined as AGS version represented as NN,NN,NN,NN.
+Fonts have adjustable outline
+
*/
enum GameDataVersion {
@@ -146,7 +150,7 @@ enum GameDataVersion {
kGameVersion_341_2 = 49,
kGameVersion_350 = 50,
kGameVersion_360 = 3060000,
- kGameVersion_Current = kGameVersion_350
+ kGameVersion_Current = kGameVersion_360
};
} // namespace AGS3
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 1a3d8ca2d4c..dcbc0a1d33e 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -716,6 +716,21 @@ HError GameDataExtReader::ReadBlock(int block_id, const String &ext_id,
// {
// // read new gui properties
// }
+ if (ext_id.CompareNoCase("v360_fonts") == 0) {
+ for (int i = 0; i < _ents.Game.numfonts; ++i) {
+ // adjustable font outlines
+ _ents.Game.fonts[i].AutoOutlineThickness = _in->ReadInt32();
+ _ents.Game.fonts[i].AutoOutlineStyle =
+ static_cast<enum FontInfo::AutoOutlineStyle>(_in->ReadInt32());
+ // reserved
+ _in->ReadInt32();
+ _in->ReadInt32();
+ _in->ReadInt32();
+ _in->ReadInt32();
+ }
+ return HError::None();
+ }
+
return new MainGameFileError(kMGFErr_ExtUnknown, String::FromFormat("Type: %s", ext_id.GetCStr()));
}
Commit: 255a739eca896ed8f71d69eace676514a1305979
https://github.com/scummvm/scummvm/commit/255a739eca896ed8f71d69eace676514a1305979
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:04:09-07:00
Commit Message:
AGS: Encapsulate game object draw caches in draw.cpp
>From upstream e04ebc0039580faf017ceb0acbeeab975bf44fcc
Changed paths:
engines/ags/engine/ac/character.cpp
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/global_object.cpp
engines/ags/engine/ac/gui.cpp
engines/ags/engine/ac/gui.h
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/game_init.cpp
engines/ags/engine/game/savegame.cpp
engines/ags/engine/main/engine.cpp
engines/ags/globals.cpp
engines/ags/globals.h
diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index 0a925bc0227..705639a4778 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -2068,11 +2068,12 @@ void CheckViewFrameForCharacter(CharacterInfo *chi) {
Bitmap *GetCharacterImage(int charid, int *isFlipped) {
if (!_G(gfxDriver)->HasAcceleratedTransform()) {
- if (_G(actsps)[charid + MAX_ROOM_OBJECTS] != nullptr) {
- // the actsps image is pre-flipped, so no longer register the image as such
+ Bitmap *actsp = get_cached_character_image(charid);
+ if (actsp) {
+ // the cached image is pre-flipped, so no longer register the image as such
if (isFlipped)
*isFlipped = 0;
- return _G(actsps)[charid + MAX_ROOM_OBJECTS];
+ return actsp;
}
}
CharacterInfo *chin = &_GP(game).chars[charid];
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 7685dcbe16b..f72ed968335 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -150,7 +150,7 @@ Bitmap *convert_32_to_32bgr(Bitmap *tempbl) {
// could copy them to texture without additional changes.
// AGS own OpenGL renderer tries to sync its behavior with the former one.
//
-// TODO: make gfxDriver->GetCompatibleBitmapFormat describe all necessary
+// TODO: make _G(gfxDriver)->GetCompatibleBitmapFormat describe all necessary
// conversions, so that we did not have to guess.
//
Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
@@ -397,11 +397,69 @@ void dispose_draw_method() {
destroy_blank_image();
}
+void init_game_drawdata() {
+ for (int i = 0; i < MAX_ROOM_OBJECTS; ++i)
+ _G(objcache)[i].image = nullptr;
+
+ size_t actsps_num = _GP(game).numcharacters + MAX_ROOM_OBJECTS;
+ _GP(actsps).resize(actsps_num);
+ _GP(actspsbmp).resize(actsps_num);
+ _GP(actspswb).resize(actsps_num);
+ _GP(actspswbbmp).resize(actsps_num);
+ _GP(actspswbcache).resize(actsps_num);
+ _GP(guibg).resize(_GP(game).numgui);
+ _GP(guibgbmp).resize(_GP(game).numgui);
+}
+
+void dispose_game_drawdata() {
+ clear_drawobj_cache();
+
+ _GP(actsps).clear();
+ _GP(actspsbmp).clear();
+ _GP(actspswb).clear();
+ _GP(actspswbbmp).clear();
+ _GP(actspswbcache).clear();
+ _GP(guibg).clear();
+}
+
void dispose_room_drawdata() {
_GP(CameraDrawData).clear();
dispose_invalid_regions(true);
}
+void clear_drawobj_cache() {
+ // clear the object cache
+ for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
+ delete _G(objcache)[i].image;
+ _G(objcache)[i].image = nullptr;
+ }
+
+ // cleanup Character + Room object textures
+ for (int i = 0; i < MAX_ROOM_OBJECTS + _GP(game).numcharacters; ++i) {
+ delete _GP(actsps)[i];
+ _GP(actsps)[i] = nullptr;
+ if (_GP(actspsbmp)[i] != nullptr)
+ _G(gfxDriver)->DestroyDDB(_GP(actspsbmp)[i]);
+ _GP(actspsbmp)[i] = nullptr;
+
+ delete _GP(actspswb)[i];
+ _GP(actspswb)[i] = nullptr;
+ if (_GP(actspswbbmp)[i] != nullptr)
+ _G(gfxDriver)->DestroyDDB(_GP(actspswbbmp)[i]);
+ _GP(actspswbbmp)[i] = nullptr;
+ _GP(actspswbcache)[i].valid = 0;
+ }
+
+ // cleanup GUI backgrounds
+ for (int i = 0; i < _GP(game).numgui; ++i) {
+ delete _GP(guibg)[i];
+ _GP(guibg)[i] = nullptr;
+ if (_GP(guibgbmp)[i])
+ _G(gfxDriver)->DestroyDDB(_GP(guibgbmp)[i]);
+ _GP(guibgbmp)[i] = nullptr;
+ }
+}
+
void on_mainviewport_changed() {
if (!_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
const auto &view = _GP(play).GetMainViewport();
@@ -705,7 +763,7 @@ IDriverDependantBitmap *recycle_ddb_bitmap(IDriverDependantBitmap *bimp, Bitmap
}
void invalidate_cached_walkbehinds() {
- memset(&_G(actspswbcache)[0], 0, sizeof(CachedActSpsData) * _G(actSpsCount));
+ memset(&_GP(actspswbcache)[0], 0, sizeof(CachedActSpsData) * _GP(actspswbcache).size());
}
// sort_out_walk_behinds: modifies the supplied sprite by overwriting parts
@@ -823,26 +881,26 @@ void sort_out_char_sprite_walk_behind(int actspsIndex, int xx, int yy, int basel
if (_G(noWalkBehindsAtAll))
return;
- if ((!_G(actspswbcache)[actspsIndex].valid) ||
- (_G(actspswbcache)[actspsIndex].xWas != xx) ||
- (_G(actspswbcache)[actspsIndex].yWas != yy) ||
- (_G(actspswbcache)[actspsIndex].baselineWas != basel)) {
- _G(actspswb)[actspsIndex] = recycle_bitmap(_G(actspswb)[actspsIndex], _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth(), width, height, true);
- Bitmap *wbSprite = _G(actspswb)[actspsIndex];
-
- _G(actspswbcache)[actspsIndex].isWalkBehindHere = sort_out_walk_behinds(wbSprite, xx, yy, basel, _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), _G(actsps)[actspsIndex], zoom);
- _G(actspswbcache)[actspsIndex].xWas = xx;
- _G(actspswbcache)[actspsIndex].yWas = yy;
- _G(actspswbcache)[actspsIndex].baselineWas = basel;
- _G(actspswbcache)[actspsIndex].valid = 1;
-
- if (_G(actspswbcache)[actspsIndex].isWalkBehindHere) {
- _G(actspswbbmp)[actspsIndex] = recycle_ddb_bitmap(_G(actspswbbmp)[actspsIndex], _G(actspswb)[actspsIndex], false);
+ if ((!_GP(actspswbcache)[actspsIndex].valid) ||
+ (_GP(actspswbcache)[actspsIndex].xWas != xx) ||
+ (_GP(actspswbcache)[actspsIndex].yWas != yy) ||
+ (_GP(actspswbcache)[actspsIndex].baselineWas != basel)) {
+ _GP(actspswb)[actspsIndex] = recycle_bitmap(_GP(actspswb)[actspsIndex], _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic->GetColorDepth(), width, height, true);
+ Bitmap *wbSprite = _GP(actspswb)[actspsIndex];
+
+ _GP(actspswbcache)[actspsIndex].isWalkBehindHere = sort_out_walk_behinds(wbSprite, xx, yy, basel, _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), _GP(actsps)[actspsIndex], zoom);
+ _GP(actspswbcache)[actspsIndex].xWas = xx;
+ _GP(actspswbcache)[actspsIndex].yWas = yy;
+ _GP(actspswbcache)[actspsIndex].baselineWas = basel;
+ _GP(actspswbcache)[actspsIndex].valid = 1;
+
+ if (_GP(actspswbcache)[actspsIndex].isWalkBehindHere) {
+ _GP(actspswbbmp)[actspsIndex] = recycle_ddb_bitmap(_GP(actspswbbmp)[actspsIndex], _GP(actspswb)[actspsIndex], false);
}
}
- if (_G(actspswbcache)[actspsIndex].isWalkBehindHere) {
- add_to_sprite_list(_G(actspswbbmp)[actspsIndex], xx, yy, basel, 0, -1, true);
+ if (_GP(actspswbcache)[actspsIndex].isWalkBehindHere) {
+ add_to_sprite_list(_GP(actspswbbmp)[actspsIndex], xx, yy, basel, 0, -1, true);
}
}
@@ -987,6 +1045,18 @@ Bitmap *recycle_bitmap(Bitmap *bimp, int coldep, int wid, int hit, bool make_tra
return bimp;
}
+// Allocates texture for the GUI
+void recreate_guibg_image(GUIMain *tehgui) {
+ int ifn = tehgui->ID;
+ delete _GP(guibg)[ifn];
+ _GP(guibg)[ifn] = BitmapHelper::CreateBitmap(tehgui->Width, tehgui->Height, _GP(game).GetColorDepth());
+ _GP(guibg)[ifn] = ReplaceBitmapWithSupportedFormat(_GP(guibg)[ifn]);
+
+ if (_GP(guibgbmp)[ifn] != nullptr) {
+ _G(gfxDriver)->DestroyDDB(_GP(guibgbmp)[ifn]);
+ _GP(guibgbmp)[ifn] = nullptr;
+ }
+}
// Get the local tint at the specified X & Y co-ordinates, based on
// room regions and SetAmbientTint
@@ -1089,7 +1159,7 @@ void apply_tint_or_light(int actspsindex, int light_level,
}
// we can only do tint/light if the colour depths match
- if (_GP(game).GetColorDepth() == _G(actsps)[actspsindex]->GetColorDepth()) {
+ if (_GP(game).GetColorDepth() == _GP(actsps)[actspsindex]->GetColorDepth()) {
Bitmap *oldwas;
// if the caller supplied a source bitmap, ->Blit from it
// (used as a speed optimisation where possible)
@@ -1097,10 +1167,10 @@ void apply_tint_or_light(int actspsindex, int light_level,
oldwas = blitFrom;
// otherwise, make a new target bmp
else {
- oldwas = _G(actsps)[actspsindex];
- _G(actsps)[actspsindex] = BitmapHelper::CreateBitmap(oldwas->GetWidth(), oldwas->GetHeight(), coldept);
+ oldwas = _GP(actsps)[actspsindex];
+ _GP(actsps)[actspsindex] = BitmapHelper::CreateBitmap(oldwas->GetWidth(), oldwas->GetHeight(), coldept);
}
- Bitmap *active_spr = _G(actsps)[actspsindex];
+ Bitmap *active_spr = _GP(actsps)[actspsindex];
if (tint_amount) {
// It is an RGB tint
@@ -1134,13 +1204,13 @@ void apply_tint_or_light(int actspsindex, int light_level,
} else if (blitFrom) {
// sprite colour depth != game colour depth, so don't try and tint
// but we do need to do something, so copy the source
- Bitmap *active_spr = _G(actsps)[actspsindex];
+ Bitmap *active_spr = _GP(actsps)[actspsindex];
active_spr->Blit(blitFrom, 0, 0, 0, 0, active_spr->GetWidth(), active_spr->GetHeight());
}
}
-// Draws the specified 'sppic' sprite onto actsps[useindx] at the
+// Draws the specified 'sppic' sprite onto _GP(actsps)[useindx] at the
// specified width and height, and flips the sprite if necessary.
// Returns 1 if something was drawn to actsps; returns 0 if no
// scaling or stretching was required, in which case nothing was done
@@ -1151,8 +1221,8 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
int actsps_used = 1;
// create and blank out the new sprite
- _G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, newwidth, newheight, true);
- Bitmap *active_spr = _G(actsps)[useindx];
+ _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, newwidth, newheight, true);
+ Bitmap *active_spr = _GP(actsps)[useindx];
if (zoom_level != 100) {
// Scaled character
@@ -1167,7 +1237,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
if (isMirrored) {
Bitmap *tempspr = BitmapHelper::CreateBitmap(newwidth, newheight, coldept);
- tempspr->Fill(_G(actsps)[useindx]->GetMaskColor());
+ tempspr->Fill(_GP(actsps)[useindx]->GetMaskColor());
if ((IS_ANTIALIAS_SPRITES) && ((_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) == 0))
tempspr->AAStretchBlt(_GP(spriteset)[sppic], RectWH(0, 0, newwidth, newheight), Shared::kBitmap_Transparency);
else
@@ -1188,17 +1258,17 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
aa_mode |= AA_HFLIP;
aa_set_mode(aa_mode);
- ->AAStretchBlt(_G(actsps)[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
+ ->AAStretchBlt(_GP(actsps)[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
}
else if (isMirrored) {
Bitmap *tempspr = BitmapHelper::CreateBitmap_ (coldept, newwidth, newheight);
- ->Clear (tempspr, ->GetMaskColor(_G(actsps)[useindx]));
+ ->Clear (tempspr, ->GetMaskColor(_GP(actsps)[useindx]));
->StretchBlt (tempspr, _GP(spriteset)[sppic], 0, 0, newwidth, newheight);
- ->FlipBlt(Shared::kBitmap_HFlip, (_G(actsps)[useindx], tempspr, 0, 0);
+ ->FlipBlt(Shared::kBitmap_HFlip, (_GP(actsps)[useindx], tempspr, 0, 0);
wfreeblock (tempspr);
}
else
- ->StretchBlt(_G(actsps)[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
+ ->StretchBlt(_GP(actsps)[useindx],_GP(spriteset)[sppic],0,0,newwidth,newheight);
*/
if (_G(in_new_room))
unselect_palette();
@@ -1212,7 +1282,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
active_spr->FlipBlt(_GP(spriteset)[sppic], 0, 0, Shared::kBitmap_HFlip);
else
actsps_used = 0;
- //->Blit (_GP(spriteset)[sppic], _G(actsps)[useindx], 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
+ //->Blit (_GP(spriteset)[sppic], _GP(actsps)[useindx], 0, 0, 0, 0, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
}
return actsps_used;
@@ -1220,7 +1290,7 @@ int scale_and_flip_sprite(int useindx, int coldept, int zoom_level,
-// create the actsps[aa] image with the object drawn correctly
+// create the _GP(actsps)[aa] image with the object drawn correctly
// returns 1 if nothing at all has changed and actsps is still
// intact from last time; 0 otherwise
int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware) {
@@ -1300,7 +1370,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
(_G(walkBehindMethod) != DrawOverCharSprite) &&
(_G(objcache)[aa].image != nullptr) &&
(_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
- (_G(actsps)[useindx] != nullptr)) {
+ (_GP(actsps)[useindx] != nullptr)) {
// HW acceleration
_G(objcache)[aa].tintamntwas = tint_level;
_G(objcache)[aa].tintredwas = tint_red;
@@ -1333,17 +1403,17 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
(_G(objcache)[aa].mirroredWas == isMirrored)) {
// the image is the same, we can use it cached!
if ((_G(walkBehindMethod) != DrawOverCharSprite) &&
- (_G(actsps)[useindx] != nullptr))
+ (_GP(actsps)[useindx] != nullptr))
return 1;
// Check if the X & Y co-ords are the same, too -- if so, there
// is scope for further optimisations
if ((_G(objcache)[aa].xwas == _G(objs)[aa].x) &&
(_G(objcache)[aa].ywas == _G(objs)[aa].y) &&
- (_G(actsps)[useindx] != nullptr) &&
+ (_GP(actsps)[useindx] != nullptr) &&
(_G(walk_behind_baselines_changed) == 0))
return 1;
- _G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, sprwidth, sprheight);
- _G(actsps)[useindx]->Blit(_G(objcache)[aa].image, 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
+ _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, sprwidth, sprheight);
+ _GP(actsps)[useindx]->Blit(_G(objcache)[aa].image, 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
return 0;
}
@@ -1356,7 +1426,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
_G(objs)[aa].num, sprwidth, sprheight, isMirrored);
} else {
// ensure actsps exists
- _G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
+ _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
}
// direct read from source bitmap, where possible
@@ -1371,13 +1441,13 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
tint_green, tint_blue, tint_light, coldept,
comeFrom);
} else if (!actspsUsed) {
- _G(actsps)[useindx]->Blit(_GP(spriteset)[_G(objs)[aa].num], 0, 0, 0, 0, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
+ _GP(actsps)[useindx]->Blit(_GP(spriteset)[_G(objs)[aa].num], 0, 0, 0, 0, _GP(game).SpriteInfos[_G(objs)[aa].num].Width, _GP(game).SpriteInfos[_G(objs)[aa].num].Height);
}
// Re-use the bitmap if it's the same size
_G(objcache)[aa].image = recycle_bitmap(_G(objcache)[aa].image, coldept, sprwidth, sprheight);
// Create the cached image and store it
- _G(objcache)[aa].image->Blit(_G(actsps)[useindx], 0, 0, 0, 0, sprwidth, sprheight);
+ _G(objcache)[aa].image->Blit(_GP(actsps)[useindx], 0, 0, 0, 0, sprwidth, sprheight);
_G(objcache)[aa].sppic = _G(objs)[aa].num;
_G(objcache)[aa].tintamntwas = tint_level;
_G(objcache)[aa].tintredwas = tint_red;
@@ -1424,36 +1494,36 @@ void prepare_objects_for_drawing() {
} else if (_G(walkBehindMethod) == DrawAsSeparateCharSprite) {
sort_out_char_sprite_walk_behind(useindx, atxp, atyp, usebasel, _G(objs)[aa].zoom, _G(objs)[aa].last_width, _G(objs)[aa].last_height);
} else if ((!actspsIntact) && (_G(walkBehindMethod) == DrawOverCharSprite)) {
- sort_out_walk_behinds(_G(actsps)[useindx], atxp, atyp, usebasel);
+ sort_out_walk_behinds(_GP(actsps)[useindx], atxp, atyp, usebasel);
}
- if ((!actspsIntact) || (_G(actspsbmp)[useindx] == nullptr)) {
+ if ((!actspsIntact) || (_GP(actspsbmp)[useindx] == nullptr)) {
bool hasAlpha = (_GP(game).SpriteInfos[_G(objs)[aa].num].Flags & SPF_ALPHACHANNEL) != 0;
- if (_G(actspsbmp)[useindx] != nullptr)
- _G(gfxDriver)->DestroyDDB(_G(actspsbmp)[useindx]);
- _G(actspsbmp)[useindx] = _G(gfxDriver)->CreateDDBFromBitmap(_G(actsps)[useindx], hasAlpha);
+ if (_GP(actspsbmp)[useindx] != nullptr)
+ _G(gfxDriver)->DestroyDDB(_GP(actspsbmp)[useindx]);
+ _GP(actspsbmp)[useindx] = _G(gfxDriver)->CreateDDBFromBitmap(_GP(actsps)[useindx], hasAlpha);
}
if (_G(gfxDriver)->HasAcceleratedTransform()) {
- _G(actspsbmp)[useindx]->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
- _G(actspsbmp)[useindx]->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
- _G(actspsbmp)[useindx]->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
+ _GP(actspsbmp)[useindx]->SetFlippedLeftRight(_G(objcache)[aa].mirroredWas != 0);
+ _GP(actspsbmp)[useindx]->SetStretch(_G(objs)[aa].last_width, _G(objs)[aa].last_height);
+ _GP(actspsbmp)[useindx]->SetTint(_G(objcache)[aa].tintredwas, _G(objcache)[aa].tintgrnwas, _G(objcache)[aa].tintbluwas, (_G(objcache)[aa].tintamntwas * 256) / 100);
if (_G(objcache)[aa].tintamntwas > 0) {
if (_G(objcache)[aa].tintlightwas == 0) // luminance of 0 -- pass 1 to enable
- _G(actspsbmp)[useindx]->SetLightLevel(1);
+ _GP(actspsbmp)[useindx]->SetLightLevel(1);
else if (_G(objcache)[aa].tintlightwas < 250)
- _G(actspsbmp)[useindx]->SetLightLevel(_G(objcache)[aa].tintlightwas);
+ _GP(actspsbmp)[useindx]->SetLightLevel(_G(objcache)[aa].tintlightwas);
else
- _G(actspsbmp)[useindx]->SetLightLevel(0);
+ _GP(actspsbmp)[useindx]->SetLightLevel(0);
} else if (_G(objcache)[aa].lightlevwas != 0)
- _G(actspsbmp)[useindx]->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
+ _GP(actspsbmp)[useindx]->SetLightLevel((_G(objcache)[aa].lightlevwas * 25) / 10 + 256);
else
- _G(actspsbmp)[useindx]->SetLightLevel(0);
+ _GP(actspsbmp)[useindx]->SetLightLevel(0);
}
- add_to_sprite_list(_G(actspsbmp)[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, _G(objs)[aa].num);
+ add_to_sprite_list(_GP(actspsbmp)[useindx], atxp, atyp, usebasel, _G(objs)[aa].transparent, _G(objs)[aa].num);
}
}
@@ -1608,8 +1678,8 @@ void prepare_characters_for_drawing() {
(_G(charcache)[aa].tintlightwas == tint_light) &&
(_G(charcache)[aa].lightlevwas == light_level)) {
if (_G(walkBehindMethod) == DrawOverCharSprite) {
- _G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
- _G(actsps)[useindx]->Blit(_G(charcache)[aa].image, 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
+ _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], _G(charcache)[aa].image->GetColorDepth(), _G(charcache)[aa].image->GetWidth(), _G(charcache)[aa].image->GetHeight());
+ _GP(actsps)[useindx]->Blit(_G(charcache)[aa].image, 0, 0, 0, 0, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
} else {
usingCachedImage = true;
}
@@ -1659,7 +1729,7 @@ void prepare_characters_for_drawing() {
// If cache needs to be re-drawn
if (!_G(charcache)[aa].inUse) {
- // create the base sprite in actsps[useindx], which will
+ // create the base sprite in _GP(actsps)[useindx], which will
// be scaled and/or flipped, as appropriate
int actspsUsed = 0;
if (!_G(gfxDriver)->HasAcceleratedTransform()) {
@@ -1668,7 +1738,7 @@ void prepare_characters_for_drawing() {
newwidth, newheight, isMirrored);
} else {
// ensure actsps exists
- _G(actsps)[useindx] = recycle_bitmap(_G(actsps)[useindx], coldept, _GP(game).SpriteInfos[sppic].Width, _GP(game).SpriteInfos[sppic].Height);
+ _GP(actsps)[useindx] = recycle_bitmap(_GP(actsps)[useindx], coldept, _GP(game).SpriteInfos[sppic].Width, _GP(game).SpriteInfos[sppic].Height);
}
_G(our_eip) = 335;
@@ -1686,14 +1756,14 @@ void prepare_characters_for_drawing() {
comeFrom);
} else if (!actspsUsed) {
// no scaling, flipping or tinting was done, so just blit it normally
- _G(actsps)[useindx]->Blit(_GP(spriteset)[sppic], 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
+ _GP(actsps)[useindx]->Blit(_GP(spriteset)[sppic], 0, 0, 0, 0, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
}
// update the character cache with the new image
_G(charcache)[aa].inUse = 1;
- //_G(charcache)[aa].image = BitmapHelper::CreateBitmap_ (coldept, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
- _G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
- _G(charcache)[aa].image->Blit(_G(actsps)[useindx], 0, 0, 0, 0, _G(actsps)[useindx]->GetWidth(), _G(actsps)[useindx]->GetHeight());
+ //_G(charcache)[aa].image = BitmapHelper::CreateBitmap_ (coldept, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
+ _G(charcache)[aa].image = recycle_bitmap(_G(charcache)[aa].image, coldept, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
+ _G(charcache)[aa].image->Blit(_GP(actsps)[useindx], 0, 0, 0, 0, _GP(actsps)[useindx]->GetWidth(), _GP(actsps)[useindx]->GetHeight());
} // end if !cache.inUse
@@ -1712,31 +1782,31 @@ void prepare_characters_for_drawing() {
} else if (_G(walkBehindMethod) == DrawAsSeparateCharSprite) {
sort_out_char_sprite_walk_behind(useindx, bgX, bgY, usebasel, _G(charextra)[aa].zoom, newwidth, newheight);
} else if (_G(walkBehindMethod) == DrawOverCharSprite) {
- sort_out_walk_behinds(_G(actsps)[useindx], bgX, bgY, usebasel);
+ sort_out_walk_behinds(_GP(actsps)[useindx], bgX, bgY, usebasel);
}
- if ((!usingCachedImage) || (_G(actspsbmp)[useindx] == nullptr)) {
+ if ((!usingCachedImage) || (_GP(actspsbmp)[useindx] == nullptr)) {
bool hasAlpha = (_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) != 0;
- _G(actspsbmp)[useindx] = recycle_ddb_bitmap(_G(actspsbmp)[useindx], _G(actsps)[useindx], hasAlpha);
+ _GP(actspsbmp)[useindx] = recycle_ddb_bitmap(_GP(actspsbmp)[useindx], _GP(actsps)[useindx], hasAlpha);
}
if (_G(gfxDriver)->HasAcceleratedTransform()) {
- _G(actspsbmp)[useindx]->SetStretch(newwidth, newheight);
- _G(actspsbmp)[useindx]->SetFlippedLeftRight(isMirrored != 0);
- _G(actspsbmp)[useindx]->SetTint(tint_red, tint_green, tint_blue, (tint_amount * 256) / 100);
+ _GP(actspsbmp)[useindx]->SetStretch(newwidth, newheight);
+ _GP(actspsbmp)[useindx]->SetFlippedLeftRight(isMirrored != 0);
+ _GP(actspsbmp)[useindx]->SetTint(tint_red, tint_green, tint_blue, (tint_amount * 256) / 100);
if (tint_amount != 0) {
if (tint_light == 0) // tint with 0 luminance, pass as 1 instead
- _G(actspsbmp)[useindx]->SetLightLevel(1);
+ _GP(actspsbmp)[useindx]->SetLightLevel(1);
else if (tint_light < 250)
- _G(actspsbmp)[useindx]->SetLightLevel(tint_light);
+ _GP(actspsbmp)[useindx]->SetLightLevel(tint_light);
else
- _G(actspsbmp)[useindx]->SetLightLevel(0);
+ _GP(actspsbmp)[useindx]->SetLightLevel(0);
} else if (light_level != 0)
- _G(actspsbmp)[useindx]->SetLightLevel((light_level * 25) / 10 + 256);
+ _GP(actspsbmp)[useindx]->SetLightLevel((light_level * 25) / 10 + 256);
else
- _G(actspsbmp)[useindx]->SetLightLevel(0);
+ _GP(actspsbmp)[useindx]->SetLightLevel(0);
}
@@ -1745,10 +1815,17 @@ void prepare_characters_for_drawing() {
chin->actx = atxp;
chin->acty = atyp;
- add_to_sprite_list(_G(actspsbmp)[useindx], bgX, bgY, usebasel, chin->transparency, sppic);
+ add_to_sprite_list(_GP(actspsbmp)[useindx], bgX, bgY, usebasel, chin->transparency, sppic);
}
}
+Shared::Bitmap *get_cached_character_image(int charid) {
+ return _GP(actsps)[charid + MAX_ROOM_OBJECTS];
+}
+
+Shared::Bitmap *get_cached_object_image(int objid) {
+ return _GP(actsps)[objid];
+}
// Compiles a list of room sprites (characters, objects, background)
void prepare_room_sprites() {
@@ -1917,14 +1994,15 @@ void draw_gui_and_overlays() {
if (_GP(guis)[aa].Transparency == 255) continue;
_GP(guis)[aa].ClearChanged();
- if (_G(guibg)[aa] == nullptr)
+ if (_GP(guibg)[aa] == nullptr ||
+ _GP(guibg)[aa]->GetSize() != Size(_GP(guis)[aa].Width, _GP(guis)[aa].Height))
recreate_guibg_image(&_GP(guis)[aa]);
_G(eip_guinum) = aa;
_G(our_eip) = 370;
- _G(guibg)[aa]->ClearTransparent();
+ _GP(guibg)[aa]->ClearTransparent();
_G(our_eip) = 372;
- _GP(guis)[aa].DrawAt(_G(guibg)[aa], 0, 0);
+ _GP(guis)[aa].DrawAt(_GP(guibg)[aa], 0, 0);
_G(our_eip) = 373;
bool isAlpha = false;
@@ -1933,14 +2011,14 @@ void draw_gui_and_overlays() {
if ((_GP(game).options[OPT_NEWGUIALPHA] == kGuiAlphaRender_Legacy) && (_GP(guis)[aa].BgImage > 0)) {
// old-style (pre-3.0.2) GUI alpha rendering
- repair_alpha_channel(_G(guibg)[aa], _GP(spriteset)[_GP(guis)[aa].BgImage]);
+ repair_alpha_channel(_GP(guibg)[aa], _GP(spriteset)[_GP(guis)[aa].BgImage]);
}
}
- if (_G(guibgbmp)[aa] != nullptr) {
- _G(gfxDriver)->UpdateDDBFromBitmap(_G(guibgbmp)[aa], _G(guibg)[aa], isAlpha);
+ if (_GP(guibgbmp)[aa] != nullptr) {
+ _G(gfxDriver)->UpdateDDBFromBitmap(_GP(guibgbmp)[aa], _GP(guibg)[aa], isAlpha);
} else {
- _G(guibgbmp)[aa] = _G(gfxDriver)->CreateDDBFromBitmap(_G(guibg)[aa], isAlpha);
+ _GP(guibgbmp)[aa] = _G(gfxDriver)->CreateDDBFromBitmap(_GP(guibg)[aa], isAlpha);
}
_G(our_eip) = 374;
}
@@ -1958,7 +2036,7 @@ void draw_gui_and_overlays() {
(_GP(guis)[aa].PopupStyle != kGUIPopupNoAutoRemove))
continue;
- add_thing_to_draw(_G(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency, _GP(guis)[aa].HasAlphaChannel());
+ add_thing_to_draw(_GP(guibgbmp)[aa], _GP(guis)[aa].X, _GP(guis)[aa].Y, _GP(guis)[aa].Transparency, _GP(guis)[aa].HasAlphaChannel());
// only poll if the interface is enabled (mouseovers should not
// work while in Wait state)
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 455757b604c..00ec67e08ec 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -73,12 +73,18 @@ class Camera;
// Initializes drawing methods and optimisation
void init_draw_method();
+// Initializes global game drawing resources
+void init_game_drawdata();
// Initializes drawing resources upon entering new room
void init_room_drawdata();
// Disposes resources related to the current drawing methods
void dispose_draw_method();
+// Disposes global game drawing resources
+void dispose_game_drawdata();
// Disposes any temporary resources on leaving current room
void dispose_room_drawdata();
+// Releases all the cached textures of game objects
+void clear_drawobj_cache();
// Updates drawing settings depending on main viewport's size and position on screen
void on_mainviewport_changed();
// Notifies that a new room viewport was created
@@ -106,6 +112,7 @@ void invalidate_rect(int x1, int y1, int x2, int y2, bool in_room);
void mark_current_background_dirty();
void invalidate_cached_walkbehinds();
+
// Avoid freeing and reallocating the memory if possible
Shared::Bitmap *recycle_bitmap(Shared::Bitmap *bimp, int coldep, int wid, int hit, bool make_transparent = false);
Engine::IDriverDependantBitmap *recycle_ddb_bitmap(Engine::IDriverDependantBitmap *bimp, Shared::Bitmap *source, bool hasAlpha = false, bool opaque = false);
@@ -117,6 +124,9 @@ void construct_game_scene(bool full_redraw = false);
void construct_game_screen_overlay(bool draw_mouse = true);
// Construct engine overlay with debugging tools (fps, console)
void construct_engine_overlay();
+// Clears black game borders in legacy letterbox mode
+void clear_letterbox_borders();
+
void add_to_sprite_list(Engine::IDriverDependantBitmap *spp, int xx, int yy, int baseline, int trans, int sprNum, bool isWalkBehind = false);
void tint_image(Shared::Bitmap *g, Shared::Bitmap *source, int red, int grn, int blu, int light_level, int luminance = 255);
void draw_sprite_support_alpha(Shared::Bitmap *ds, bool ds_has_alpha, int xpos, int ypos, Shared::Bitmap *image, bool src_has_alpha,
@@ -136,7 +146,10 @@ void putpixel_compensate(Shared::Bitmap *g, int xx, int yy, int col);
// returns 1 if nothing at all has changed and actsps is still
// intact from last time; 0 otherwise
int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware);
-void clear_letterbox_borders();
+// Returns a cached character image prepared for the render
+Shared::Bitmap *get_cached_character_image(int charid);
+// Returns a cached object image prepared for the render
+Shared::Bitmap *get_cached_object_image(int objid);
void draw_and_invalidate_text(Shared::Bitmap *ds, int x1, int y1, int font, color_t text_color, const char *text);
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index e2b20d0f966..d6ebdf22709 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -400,11 +400,8 @@ void unload_game_file() {
_GP(characterScriptObjNames).clear();
free(_G(charextra));
free(_G(mls));
- free(_G(actsps));
- free(_G(actspsbmp));
- free(_G(actspswb));
- free(_G(actspswbbmp));
- free(_G(actspswbcache));
+
+ dispose_game_drawdata();
if ((_G(gameinst) != nullptr) && (_G(gameinst)->pc != 0)) {
quit("Error: unload_game called while script still running");
@@ -472,13 +469,7 @@ void unload_game_file() {
delete[] _G(scrDialog);
_G(scrDialog) = nullptr;
- for (int i = 0; i < _GP(game).numgui; ++i) {
- free(_G(guibg)[i]);
- _G(guibg)[i] = nullptr;
- }
-
_GP(guiScriptObjNames).clear();
- free(_G(guibg));
_GP(guis).clear();
free(_G(scrGui));
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index af6f9a7b973..9d227077700 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -277,17 +277,16 @@ void MergeObject(int obn) {
int theHeight;
construct_object_gfx(obn, nullptr, &theHeight, true);
+ Bitmap *actsp = get_cached_object_image(obn);
- //Bitmap *oldabuf = graphics->bmp;
- //abuf = _GP(thisroom).BgFrames.Graphic[_GP(play).bg_frame];
PBitmap bg_frame = _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic;
- if (bg_frame->GetColorDepth() != _G(actsps)[obn]->GetColorDepth())
+ if (bg_frame->GetColorDepth() != actsp->GetColorDepth())
quit("!MergeObject: unable to merge object due to color depth differences");
int xpos = data_to_game_coord(_G(objs)[obn].x);
int ypos = (data_to_game_coord(_G(objs)[obn].y) - theHeight);
- draw_sprite_support_alpha(bg_frame.get(), false, xpos, ypos, _G(actsps)[obn], (_GP(game).SpriteInfos[_G(objs)[obn].num].Flags & SPF_ALPHACHANNEL) != 0);
+ draw_sprite_support_alpha(bg_frame.get(), false, xpos, ypos, actsp, (_GP(game).SpriteInfos[_G(objs)[obn].num].Flags & SPF_ALPHACHANNEL) != 0);
invalidate_screen();
mark_current_background_dirty();
@@ -522,15 +521,14 @@ void GetObjectPropertyText(int item, const char *property, char *bufer) {
Bitmap *GetObjectImage(int obj, int *isFlipped) {
if (!_G(gfxDriver)->HasAcceleratedTransform()) {
- if (_G(actsps)[obj] != nullptr) {
- // the _G(actsps) image is pre-flipped, so no longer register the image as such
+ if (_GP(actsps)[obj] != nullptr) {
+ // the actsps image is pre-flipped, so no longer register the image as such
if (isFlipped)
*isFlipped = 0;
- return _G(actsps)[obj];
+ return _GP(actsps)[obj];
}
}
-
return _GP(spriteset)[_G(objs)[obj].num];
}
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index f2b48785fa6..6e011ac4729 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -125,8 +125,6 @@ void GUI_SetSize(ScriptGUI *sgui, int widd, int hitt) {
tehgui->Width = widd;
tehgui->Height = hitt;
- recreate_guibg_image(tehgui);
-
tehgui->MarkChanged();
}
@@ -549,20 +547,6 @@ int adjust_y_for_guis(int yy) {
return yy;
}
-void recreate_guibg_image(GUIMain *tehgui) {
- int ifn = tehgui->ID;
- delete _G(guibg)[ifn];
- _G(guibg)[ifn] = BitmapHelper::CreateBitmap(tehgui->Width, tehgui->Height, _GP(game).GetColorDepth());
- if (_G(guibg)[ifn] == nullptr)
- quit("SetGUISize: internal error: unable to reallocate gui cache");
- _G(guibg)[ifn] = ReplaceBitmapWithSupportedFormat(_G(guibg)[ifn]);
-
- if (_G(guibgbmp)[ifn] != nullptr) {
- _G(gfxDriver)->DestroyDDB(_G(guibgbmp)[ifn]);
- _G(guibgbmp)[ifn] = nullptr;
- }
-}
-
int gui_get_interactable(int x, int y) {
if ((_GP(game).options[OPT_DISABLEOFF] == 3) && (_G(all_buttons_disabled) > 0))
return -1;
diff --git a/engines/ags/engine/ac/gui.h b/engines/ags/engine/ac/gui.h
index 2aa2992b1b1..41d848634ca 100644
--- a/engines/ags/engine/ac/gui.h
+++ b/engines/ags/engine/ac/gui.h
@@ -78,7 +78,6 @@ int convert_gui_disabled_style(int oldStyle);
void update_gui_disabled_status();
int adjust_x_for_guis(int xx, int yy);
int adjust_y_for_guis(int yy);
-void recreate_guibg_image(GUIMain *tehgui);
int gui_get_interactable(int x, int y);
int gui_on_mouse_move();
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 0b7be963f7d..7e80bc5ad0f 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -302,31 +302,10 @@ void unload_old_room() {
croom_ptr_clear();
- // clear the object cache
- for (ff = 0; ff < MAX_ROOM_OBJECTS; ff++) {
- delete _G(objcache)[ff].image;
- _G(objcache)[ff].image = nullptr;
- }
- // clear the _G(actsps) buffers to save memory, since the
+ // clear the _GP(actsps) buffers to save memory, since the
// objects/characters involved probably aren't on the
// new screen. this also ensures all cached data is flushed
- for (ff = 0; ff < MAX_ROOM_OBJECTS + _GP(game).numcharacters; ff++) {
- delete _G(actsps)[ff];
- _G(actsps)[ff] = nullptr;
-
- if (_G(actspsbmp)[ff] != nullptr)
- _G(gfxDriver)->DestroyDDB(_G(actspsbmp)[ff]);
- _G(actspsbmp)[ff] = nullptr;
-
- delete _G(actspswb)[ff];
- _G(actspswb)[ff] = nullptr;
-
- if (_G(actspswbbmp)[ff] != nullptr)
- _G(gfxDriver)->DestroyDDB(_G(actspswbbmp)[ff]);
- _G(actspswbbmp)[ff] = nullptr;
-
- _G(actspswbcache)[ff].valid = 0;
- }
+ clear_drawobj_cache();
// if Hide Player Character was ticked, restore it to visible
if (_GP(play).temporarily_turned_off_character >= 0) {
@@ -950,15 +929,6 @@ void new_room(int newnum, CharacterInfo *forchar) {
// Delete all cached sprites
_GP(spriteset).DisposeAll();
- // Delete all gui background images
- for (int i = 0; i < _GP(game).numgui; i++) {
- delete _G(guibg)[i];
- _G(guibg)[i] = nullptr;
-
- if (_G(guibgbmp)[i])
- _G(gfxDriver)->DestroyDDB(_G(guibgbmp)[i]);
- _G(guibgbmp)[i] = nullptr;
- }
GUI::MarkAllGUIForUpdate();
}
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 4017d596ec3..3ba652ab5f5 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -354,12 +354,8 @@ HGameInitError InitGameState(const LoadedGameEntities &ents, GameDataVersion dat
_G(charextra) = (CharacterExtras *)calloc(_GP(game).numcharacters, sizeof(CharacterExtras));
_G(charcache) = (CharacterCache *)calloc(1, sizeof(CharacterCache) * _GP(game).numcharacters + 5);
_G(mls) = (MoveList *)calloc(_GP(game).numcharacters + MAX_ROOM_OBJECTS + 1, sizeof(MoveList));
- _G(actSpsCount) = _GP(game).numcharacters + MAX_ROOM_OBJECTS + 2;
- _G(actsps) = (Bitmap **)calloc(_G(actSpsCount), sizeof(Bitmap *));
- _G(actspsbmp) = (IDriverDependantBitmap **)calloc(_G(actSpsCount), sizeof(IDriverDependantBitmap *));
- _G(actspswb) = (Bitmap **)calloc(_G(actSpsCount), sizeof(Bitmap *));
- _G(actspswbbmp) = (IDriverDependantBitmap **)calloc(_G(actSpsCount), sizeof(IDriverDependantBitmap *));
- _G(actspswbcache) = (CachedActSpsData *)calloc(_G(actSpsCount), sizeof(CachedActSpsData));
+ init_game_drawdata();
+
_GP(play).charProps.resize(_GP(game).numcharacters);
_G(old_dialog_scripts) = ents.OldDialogScripts;
_G(old_speech_lines) = ents.OldSpeechLines;
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index c8ed7b98f95..ccb9f296fe3 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -344,15 +344,8 @@ void DoBeforeRestore(PreservedParams &pp) {
}
}
- // cleanup GUI backgrounds
- for (int i = 0; i < _GP(game).numgui; ++i) {
- delete _G(guibg)[i];
- _G(guibg)[i] = nullptr;
-
- if (_G(guibgbmp)[i])
- _G(gfxDriver)->DestroyDDB(_G(guibgbmp)[i]);
- _G(guibgbmp)[i] = nullptr;
- }
+ // Cleanup drawn caches
+ clear_drawobj_cache();
// preserve script data sizes and cleanup scripts
pp.GlScDataSize = _G(gameinst)->globaldatasize;
@@ -608,11 +601,6 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
}
update_directional_sound_vol();
- for (int i = 0; i < _GP(game).numgui; ++i) {
- _G(guibg)[i] = BitmapHelper::CreateBitmap(_GP(guis)[i].Width, _GP(guis)[i].Height, _GP(game).GetColorDepth());
- _G(guibg)[i] = ReplaceBitmapWithSupportedFormat(_G(guibg)[i]);
- }
-
recreate_overlay_ddbs();
GUI::MarkAllGUIForUpdate();
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index c76e468c8d5..1dca064cbce 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -577,9 +577,6 @@ void engine_init_game_settings() {
int ee;
- for (ee = 0; ee < MAX_ROOM_OBJECTS + _GP(game).numcharacters; ee++)
- _G(actsps)[ee] = nullptr;
-
for (ee = 0; ee < 256; ee++) {
if (_GP(game).paluses[ee] != PAL_BACKGROUND)
_G(palette)[ee] = _GP(game).defpal[ee];
@@ -602,9 +599,6 @@ void engine_init_game_settings() {
if (_G(playerchar)->view >= 0)
precache_view(_G(playerchar)->view);
- for (ee = 0; ee < MAX_ROOM_OBJECTS; ee++)
- _G(objcache)[ee].image = nullptr;
-
/* dummygui.guiId = -1;
dummyguicontrol.guin = -1;
dummyguicontrol.objn = -1;*/
@@ -644,13 +638,6 @@ void engine_init_game_settings() {
_G(charextra)[ee].slow_move_counter = 0;
_G(charextra)[ee].animwait = 0;
}
- // multiply up gui positions
- _G(guibg) = (Bitmap **)malloc(sizeof(Bitmap *) * _GP(game).numgui);
- _G(guibgbmp) = (IDriverDependantBitmap **)malloc(sizeof(IDriverDependantBitmap *) * _GP(game).numgui);
- for (ee = 0; ee < _GP(game).numgui; ee++) {
- _G(guibg)[ee] = nullptr;
- _G(guibgbmp)[ee] = nullptr;
- }
_G(our_eip) = -5;
for (ee = 0; ee < _GP(game).numinvitems; ee++) {
diff --git a/engines/ags/globals.cpp b/engines/ags/globals.cpp
index d603b142ca1..613366bda3b 100644
--- a/engines/ags/globals.cpp
+++ b/engines/ags/globals.cpp
@@ -173,6 +173,15 @@ Globals::Globals() {
_dynamicallyCreatedSurfaces = new AGS::Shared::Bitmap *[MAX_DYNAMIC_SURFACES];
Common::fill(_dynamicallyCreatedSurfaces, _dynamicallyCreatedSurfaces +
MAX_DYNAMIC_SURFACES, (AGS::Shared::Bitmap *)nullptr);
+
+ _actsps = new std::vector<Shared::Bitmap *>();
+ _actspsbmp = new std::vector<Engine::IDriverDependantBitmap *>();
+ _actspswb = new std::vector<Shared::Bitmap *>();
+ _actspswbbmp = new std::vector<Engine::IDriverDependantBitmap *>();
+ _actspswbcache = new std::vector<CachedActSpsData>();
+ _guibg = new std::vector<Shared::Bitmap *>();
+ _guibgbmp = new std::vector<Engine::IDriverDependantBitmap *>();
+
_maincoltable = new COLOR_MAP();
_palette = new color[256];
for (int i = 0; i < PALETTE_COUNT; ++i)
@@ -413,6 +422,13 @@ Globals::~Globals() {
delete _CameraDrawData;
delete _sprlist;
delete _thingsToDrawList;
+ delete _actsps;
+ delete _actspsbmp;
+ delete _actspswb;
+ delete _actspswbbmp;
+ delete _actspswbcache;
+ delete _guibg;
+ delete _guibgbmp;
delete[] _dynamicallyCreatedSurfaces;
delete[] _palette;
delete _maincoltable;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 29e14c52bca..18ed2a1d4ee 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -569,18 +569,19 @@ public:
// actsps is used for temporary storage of the bitamp image
// of the latest version of the sprite
- int _actSpsCount = 0;
- AGS::Shared::Bitmap **_actsps = nullptr;
- AGS::Engine::IDriverDependantBitmap **_actspsbmp = nullptr;
+ std::vector<Shared::Bitmap *> *_actsps;
+ std::vector<Engine::IDriverDependantBitmap *> *_actspsbmp;
// temporary cache of walk-behind for this actsps image
- AGS::Shared::Bitmap **_actspswb = nullptr;
- AGS::Engine::IDriverDependantBitmap **_actspswbbmp = nullptr;
- CachedActSpsData *_actspswbcache = nullptr;
+ std::vector<Shared::Bitmap *> *_actspswb;
+ std::vector<Engine::IDriverDependantBitmap *> *_actspswbbmp;
+ std::vector<CachedActSpsData> *_actspswbcache;
+ // GUI surfaces
+ std::vector<Shared::Bitmap *> *_guibg;
+ std::vector<Engine::IDriverDependantBitmap *> *_guibgbmp;
+
bool _current_background_is_dirty = false;
// Room background sprite
AGS::Engine::IDriverDependantBitmap *_roomBackgroundBmp = nullptr;
- AGS::Shared::Bitmap **_guibg = nullptr;
- AGS::Engine::IDriverDependantBitmap **_guibgbmp = nullptr;
AGS::Shared::Bitmap *_debugConsoleBuffer = nullptr;
// whether there are currently remnants of a DisplaySpeech
bool _screen_is_dirty = false;
Commit: 2d995bbe074cd1badd3cfef05f727de52ec74fa0
https://github.com/scummvm/scummvm/commit/2d995bbe074cd1badd3cfef05f727de52ec74fa0
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:33:38-07:00
Commit Message:
AGS: Simplified use of ReplaceBitmapWithSupportedFormat()
>From upstream 2132ba833b9d4508ed3f81a65f531b88f6087cb5
Changed paths:
engines/ags/engine/ac/dialog.cpp
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/ac/dynamic_sprite.cpp
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/global_dynamic_sprite.cpp
engines/ags/engine/ac/screen.cpp
engines/ags/engine/gui/gui_dialog.cpp
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 98c181a14dc..0e262a32300 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -766,8 +766,8 @@ void DialogOptions::Redraw() {
update_polled_stuff_if_runtime();
- subBitmap = recycle_bitmap(subBitmap, tempScrn->GetColorDepth(), dirtywidth, dirtyheight);
- subBitmap = ReplaceBitmapWithSupportedFormat(subBitmap);
+ subBitmap = recycle_bitmap(subBitmap,
+ _G(gfxDriver)->GetCompatibleBitmapFormat(tempScrn->GetColorDepth()), dirtywidth, dirtyheight);
update_polled_stuff_if_runtime();
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index f72ed968335..e0177b19098 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -155,8 +155,14 @@ Bitmap *convert_32_to_32bgr(Bitmap *tempbl) {
//
Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
const int bmp_col_depth = bitmap->GetColorDepth();
- // const int sys_col_depth = System_GetColorDepth();
+ const int sys_col_depth = System_GetColorDepth();
const int game_col_depth = _GP(game).GetColorDepth();
+ const int compat_col_depth = _G(gfxDriver)->GetCompatibleBitmapFormat(game_col_depth);
+
+ const bool must_switch_palette = bitmap->GetColorDepth() == 8 && game_col_depth > 8;
+ if (must_switch_palette)
+ select_palette(_G(palette));
+
Bitmap *new_bitmap = bitmap;
//
@@ -184,54 +190,48 @@ Bitmap *AdjustBitmapForUseWithDisplayMode(Bitmap *bitmap, bool has_alpha) {
}
// In 32-bit game hicolor bitmaps must be converted to the true color
else if (game_col_depth == 32 && (bmp_col_depth > 8 && bmp_col_depth <= 16)) {
- new_bitmap = BitmapHelper::CreateBitmapCopy(bitmap, game_col_depth);
+ new_bitmap = BitmapHelper::CreateBitmapCopy(bitmap, compat_col_depth);
}
// In non-32-bit game truecolor bitmaps must be downgraded
else if (game_col_depth <= 16 && bmp_col_depth > 16) {
if (has_alpha) // if has valid alpha channel, convert it to regular transparency mask
new_bitmap = remove_alpha_channel(bitmap);
else // else simply convert bitmap
- new_bitmap = BitmapHelper::CreateBitmapCopy(bitmap, game_col_depth);
+ new_bitmap = BitmapHelper::CreateBitmapCopy(bitmap, compat_col_depth);
}
// Special case when we must convert 16-bit RGB to BGR
else if (_G(convert_16bit_bgr) == 1 && bmp_col_depth == 16) {
new_bitmap = convert_16_to_16bgr(bitmap);
}
+
+ // Finally, if we did not create a new copy already, - convert to driver compatible format
+ if ((new_bitmap == bitmap) && (bmp_col_depth != compat_col_depth))
+ new_bitmap = GfxUtil::ConvertBitmap(bitmap, compat_col_depth);
+
+ if (must_switch_palette)
+ unselect_palette();
+
return new_bitmap;
}
+Bitmap *CreateCompatBitmap(int width, int height, int col_depth) {
+ return new Bitmap(width, height,
+ _G(gfxDriver)->GetCompatibleBitmapFormat(col_depth == 0 ? _GP(game).GetColorDepth() : col_depth));
+}
+
Bitmap *ReplaceBitmapWithSupportedFormat(Bitmap *bitmap) {
- Bitmap *new_bitmap = GfxUtil::ConvertBitmap(bitmap, _G(gfxDriver)->GetCompatibleBitmapFormat(bitmap->GetColorDepth()));
- if (new_bitmap != bitmap)
- delete bitmap;
- return new_bitmap;
+ return GfxUtil::ConvertBitmap(bitmap, _G(gfxDriver)->GetCompatibleBitmapFormat(bitmap->GetColorDepth()));
}
Bitmap *PrepareSpriteForUse(Bitmap *bitmap, bool has_alpha) {
- bool must_switch_palette = bitmap->GetColorDepth() == 8 && _GP(game).GetColorDepth() > 8;
- if (must_switch_palette)
- select_palette(_G(palette));
-
Bitmap *new_bitmap = AdjustBitmapForUseWithDisplayMode(bitmap, has_alpha);
if (new_bitmap != bitmap)
delete bitmap;
- new_bitmap = ReplaceBitmapWithSupportedFormat(new_bitmap);
-
- if (must_switch_palette)
- unselect_palette();
return new_bitmap;
}
PBitmap PrepareSpriteForUse(PBitmap bitmap, bool has_alpha) {
- bool must_switch_palette = bitmap->GetColorDepth() == 8 && System_GetColorDepth() > 8;
- if (must_switch_palette)
- select_palette(_G(palette));
-
Bitmap *new_bitmap = AdjustBitmapForUseWithDisplayMode(bitmap.get(), has_alpha);
- new_bitmap = ReplaceBitmapWithSupportedFormat(new_bitmap);
-
- if (must_switch_palette)
- unselect_palette();
return new_bitmap == bitmap.get() ? bitmap : PBitmap(new_bitmap); // if bitmap is same, don't create new smart ptr!
}
@@ -349,8 +349,7 @@ void create_blank_image(int coldepth) {
// so it's the most likey place for a crash
//try
//{
- Bitmap *blank = BitmapHelper::CreateBitmap(16, 16, coldepth);
- blank = ReplaceBitmapWithSupportedFormat(blank);
+ Bitmap *blank = CreateCompatBitmap(16, 16, coldepth);
blank->Clear();
_G(blankImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
_G(blankSidebarImage) = _G(gfxDriver)->CreateDDBFromBitmap(blank, false, true);
@@ -1049,8 +1048,7 @@ Bitmap *recycle_bitmap(Bitmap *bimp, int coldep, int wid, int hit, bool make_tra
void recreate_guibg_image(GUIMain *tehgui) {
int ifn = tehgui->ID;
delete _GP(guibg)[ifn];
- _GP(guibg)[ifn] = BitmapHelper::CreateBitmap(tehgui->Width, tehgui->Height, _GP(game).GetColorDepth());
- _GP(guibg)[ifn] = ReplaceBitmapWithSupportedFormat(_GP(guibg)[ifn]);
+ _GP(guibg)[ifn] = CreateCompatBitmap(tehgui->Width, tehgui->Height);
if (_GP(guibgbmp)[ifn] != nullptr) {
_G(gfxDriver)->DestroyDDB(_GP(guibgbmp)[ifn]);
@@ -1917,8 +1915,7 @@ void draw_fps(const Rect &viewport) {
static Bitmap *fpsDisplay = nullptr;
const int font = FONT_NORMAL;
if (fpsDisplay == nullptr) {
- fpsDisplay = BitmapHelper::CreateBitmap(viewport.GetWidth(), (getfontheight_outlined(font) + get_fixed_pixel_size(5)), _GP(game).GetColorDepth());
- fpsDisplay = ReplaceBitmapWithSupportedFormat(fpsDisplay);
+ fpsDisplay = CreateCompatBitmap(viewport.GetWidth(), (getfontheight_outlined(font) + get_fixed_pixel_size(5)), _GP(game).GetColorDepth());
}
fpsDisplay->ClearTransparent();
@@ -2274,8 +2271,7 @@ void construct_engine_overlay() {
int barheight = getheightoflines(font, DEBUG_CONSOLE_NUMLINES - 1) + 4;
if (_G(debugConsoleBuffer) == nullptr) {
- _G(debugConsoleBuffer) = BitmapHelper::CreateBitmap(viewport.GetWidth(), barheight, _GP(game).GetColorDepth());
- _G(debugConsoleBuffer) = ReplaceBitmapWithSupportedFormat(_G(debugConsoleBuffer));
+ _G(debugConsoleBuffer) = CreateCompatBitmap(viewport.GetWidth(), barheight);
}
color_t draw_color = _G(debugConsoleBuffer)->GetCompatibleColor(15);
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 00ec67e08ec..9a5bccce96d 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -178,11 +178,11 @@ extern AGS_INLINE int game_to_ctx_data_size(int size, bool hires_ctx);
// This function converts game coordinates coming from script to the actual game resolution.
extern AGS_INLINE void defgame_to_finalgame_coords(int &x, int &y);
-// Checks if the bitmap needs to be converted and **deletes original** if a new bitmap
-// had to be created (by default).
-// TODO: this helper function was meant to remove bitmap deletion from the GraphicsDriver's
-// implementations while keeping code changes to minimum. The proper solution would probably
-// be to use shared pointers when storing Bitmaps, or make Bitmap reference-counted object.
+// Creates bitmap of a format compatible with the gfxdriver;
+// if col_depth is 0, uses game's native color depth.
+Shared::Bitmap *CreateCompatBitmap(int width, int height, int col_depth = 0);
+// Checks if the bitmap is compatible with the gfxdriver;
+// returns same bitmap or its copy of a compatible format.
Shared::Bitmap *ReplaceBitmapWithSupportedFormat(Shared::Bitmap *bitmap);
// Checks if the bitmap needs any kind of adjustments before it may be used
// in AGS sprite operations. Also handles number of certain special cases
diff --git a/engines/ags/engine/ac/dynamic_sprite.cpp b/engines/ags/engine/ac/dynamic_sprite.cpp
index 6e4f68eb0db..f64067144d7 100644
--- a/engines/ags/engine/ac/dynamic_sprite.cpp
+++ b/engines/ags/engine/ac/dynamic_sprite.cpp
@@ -322,7 +322,7 @@ ScriptDynamicSprite *DynamicSprite_CreateFromScreenShot(int width, int height) {
update_polled_stuff_if_runtime();
// replace the bitmap in the sprite set
- add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(newPic));
+ add_dynamic_sprite(gotSlot, newPic);
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
return new_spr;
}
@@ -385,14 +385,15 @@ ScriptDynamicSprite *DynamicSprite_Create(int width, int height, int alphaChanne
if (gotSlot <= 0)
return nullptr;
- Bitmap *newPic = BitmapHelper::CreateTransparentBitmap(width, height, _GP(game).GetColorDepth());
+ Bitmap *newPic = CreateCompatBitmap(width, height);
if (newPic == nullptr)
return nullptr;
+ newPic->ClearTransparent();
if ((alphaChannel) && (_GP(game).GetColorDepth() < 32))
alphaChannel = false;
- add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(newPic), alphaChannel != 0);
+ add_dynamic_sprite(gotSlot, newPic, alphaChannel != 0);
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
return new_spr;
}
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index d6ebdf22709..0e55ad221d2 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -961,7 +961,7 @@ bool read_savedgame_screenshot(const String &savedgame, int &want_shot) {
int slot = _GP(spriteset).GetFreeIndex();
if (slot > 0) {
// add it into the sprite set
- add_dynamic_sprite(slot, ReplaceBitmapWithSupportedFormat(desc.UserImage.release()));
+ add_dynamic_sprite(slot, PrepareSpriteForUse(desc.UserImage.release(), false));
want_shot = slot;
}
}
diff --git a/engines/ags/engine/ac/global_dynamic_sprite.cpp b/engines/ags/engine/ac/global_dynamic_sprite.cpp
index 2891916577b..bccc16e00cf 100644
--- a/engines/ags/engine/ac/global_dynamic_sprite.cpp
+++ b/engines/ags/engine/ac/global_dynamic_sprite.cpp
@@ -48,7 +48,7 @@ int LoadImageFile(const char *filename) {
if (gotSlot <= 0)
return 0;
- add_dynamic_sprite(gotSlot, ReplaceBitmapWithSupportedFormat(loadedFile));
+ add_dynamic_sprite(gotSlot, PrepareSpriteForUse(loadedFile, false));
return gotSlot;
}
diff --git a/engines/ags/engine/ac/screen.cpp b/engines/ags/engine/ac/screen.cpp
index 89d01aa4f08..a2fc8de46b1 100644
--- a/engines/ags/engine/ac/screen.cpp
+++ b/engines/ags/engine/ac/screen.cpp
@@ -85,7 +85,6 @@ IDriverDependantBitmap *prepare_screen_for_transition_in() {
if (_G(saved_viewport_bitmap) == nullptr)
quit("Crossfade: buffer is null attempting transition");
- _G(saved_viewport_bitmap) = ReplaceBitmapWithSupportedFormat(_G(saved_viewport_bitmap));
const Rect &viewport = _GP(play).GetMainViewport();
if (_G(saved_viewport_bitmap)->GetHeight() < viewport.GetHeight()) {
Bitmap *enlargedBuffer = BitmapHelper::CreateBitmap(_G(saved_viewport_bitmap)->GetWidth(), viewport.GetHeight(), _G(saved_viewport_bitmap)->GetColorDepth());
diff --git a/engines/ags/engine/gui/gui_dialog.cpp b/engines/ags/engine/gui/gui_dialog.cpp
index 6ee7eb6458c..665d943096d 100644
--- a/engines/ags/engine/gui/gui_dialog.cpp
+++ b/engines/ags/engine/gui/gui_dialog.cpp
@@ -60,8 +60,7 @@ Bitmap *prepare_gui_screen(int x, int y, int width, int height, bool opaque) {
if (_G(windowBuffer)) {
_G(windowBuffer) = recycle_bitmap(_G(windowBuffer), _G(windowBuffer)->GetColorDepth(), _G(windowPosWidth), _G(windowPosHeight), !opaque);
} else {
- _G(windowBuffer) = BitmapHelper::CreateBitmap(_G(windowPosWidth), _G(windowPosHeight), _GP(game).GetColorDepth());
- _G(windowBuffer) = ReplaceBitmapWithSupportedFormat(_G(windowBuffer));
+ _G(windowBuffer) = CreateCompatBitmap(_G(windowPosWidth), _G(windowPosHeight));
}
_G(dialogDDB) = recycle_ddb_bitmap(_G(dialogDDB), _G(windowBuffer), false, opaque);
return _G(windowBuffer);
Commit: 448bb2d77ef4e49aaaa4ad5298ab07fa1737115a
https://github.com/scummvm/scummvm/commit/448bb2d77ef4e49aaaa4ad5298ab07fa1737115a
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2022-03-14T21:46:58-07:00
Commit Message:
AGS: Moved "LucasFan" font hack to game_init, enable for all systems
>From upstream 5d84ea958f9d2ba5582e69f211dbcb006ed4e187
Changed paths:
engines/ags/engine/game/game_init.cpp
engines/ags/shared/font/ags_font_renderer.h
engines/ags/shared/font/fonts.cpp
engines/ags/shared/font/fonts.h
engines/ags/shared/font/ttf_font_renderer.cpp
engines/ags/shared/font/ttf_font_renderer.h
engines/ags/shared/font/wfn_font_renderer.h
diff --git a/engines/ags/engine/game/game_init.cpp b/engines/ags/engine/game/game_init.cpp
index 3ba652ab5f5..55fa74b409a 100644
--- a/engines/ags/engine/game/game_init.cpp
+++ b/engines/ags/engine/game/game_init.cpp
@@ -52,6 +52,7 @@
#include "ags/engine/script/exports.h"
#include "ags/engine/script/script.h"
#include "ags/engine/script/script_runtime.h"
+#include "ags/shared/util/string_compat.h"
#include "ags/shared/util/string_utils.h"
#include "ags/engine/media/audio/audio_system.h"
#include "ags/globals.h"
@@ -281,6 +282,24 @@ void LoadFonts(GameDataVersion data_ver) {
}
}
}
+
+ // Additional fixups - after all the fonts are registered
+ for (int i = 0; i < _GP(game).numfonts; ++i) {
+ if (!is_bitmap_font(i)) {
+ // Check for the LucasFan font since it comes with an outline font that
+ // is drawn incorrectly with Freetype versions > 2.1.3.
+ // A simple workaround is to disable outline fonts for it and use
+ // automatic outline drawing.
+ const int outline_font = get_font_outline(i);
+ if (outline_font < 0)
+ continue;
+ const char *name = get_font_name(i);
+ const char *outline_name = get_font_name(outline_font);
+ if ((ags_stricmp(name, "LucasFan-Font") == 0) &&
+ (ags_stricmp(outline_name, "Arcade") == 0))
+ set_font_outline(i, FONT_OUTLINE_AUTO);
+ }
+ }
}
void LoadLipsyncData() {
diff --git a/engines/ags/shared/font/ags_font_renderer.h b/engines/ags/shared/font/ags_font_renderer.h
index 9cfaa8ee092..0936d2ddfdb 100644
--- a/engines/ags/shared/font/ags_font_renderer.h
+++ b/engines/ags/shared/font/ags_font_renderer.h
@@ -59,10 +59,13 @@ struct FontMetrics {
// NOTE: this extending interface is not yet exposed to plugins
class IAGSFontRenderer2 {
public:
+ // Tells if this is a bitmap font (otherwise it's a vector font)
virtual bool IsBitmapFont() = 0;
// Load font, applying extended font rendering parameters
virtual bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
FontMetrics *metrics) = 0;
+ // Gets font's name; must return an empty string if no name is available
+ virtual const char *GetName(int fontNumber) = 0;
protected:
IAGSFontRenderer2() {}
~IAGSFontRenderer2() {}
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index 5451f57b140..49bb4438bba 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -110,6 +110,13 @@ bool font_supports_extended_characters(size_t fontNumber) {
return _GP(fonts)[fontNumber].Renderer->SupportsExtendedCharacters(fontNumber);
}
+const char *get_font_name(size_t fontNumber) {
+ if (fontNumber >= _GP(fonts).size() || !_GP(fonts)[fontNumber].Renderer2)
+ return "";
+ const char *name = _GP(fonts)[fontNumber].Renderer2->GetName(fontNumber);
+ return name ? name : "";
+}
+
void ensure_text_valid_for_font(char *text, size_t fontnum) {
if (fontnum >= _GP(fonts).size() || !_GP(fonts)[fontnum].Renderer)
return;
diff --git a/engines/ags/shared/font/fonts.h b/engines/ags/shared/font/fonts.h
index 2c6bb129438..b09c5d1fb84 100644
--- a/engines/ags/shared/font/fonts.h
+++ b/engines/ags/shared/font/fonts.h
@@ -71,6 +71,8 @@ bool font_first_renderer_loaded();
bool is_font_loaded(size_t fontNumber);
bool is_bitmap_font(size_t fontNumber);
bool font_supports_extended_characters(size_t fontNumber);
+// Get font's name, if it's available, otherwise returns empty string
+const char *get_font_name(size_t fontNumber);
// TODO: with changes to WFN font renderer that implemented safe rendering of
// strings containing invalid chars (since 3.3.1) this function is not
// important, except for (maybe) few particular cases.
diff --git a/engines/ags/shared/font/ttf_font_renderer.cpp b/engines/ags/shared/font/ttf_font_renderer.cpp
index a82c798a1e6..982af7e67fa 100644
--- a/engines/ags/shared/font/ttf_font_renderer.cpp
+++ b/engines/ags/shared/font/ttf_font_renderer.cpp
@@ -22,17 +22,11 @@
#include "ags/lib/alfont/alfont.h"
#include "ags/shared/core/platform.h"
#include "ags/globals.h"
-
-#define AGS_OUTLINE_FONT_FIX (!AGS_PLATFORM_OS_WINDOWS)
-
#include "ags/shared/core/asset_manager.h"
#include "ags/shared/font/ttf_font_renderer.h"
#include "ags/shared/util/stream.h"
-
-#if AGS_OUTLINE_FONT_FIX // TODO: factor out the hack in LoadFromDiskEx
#include "ags/shared/ac/game_struct_defines.h"
#include "ags/shared/font/fonts.h"
-#endif
namespace AGS3 {
@@ -143,6 +137,10 @@ bool TTFFontRenderer::LoadFromDiskEx(int fontNumber, int fontSize,
return true;
}
+const char *TTFFontRenderer::GetName(int fontNumber) {
+ return alfont_get_name(_fontData[fontNumber].AlFont);
+}
+
void TTFFontRenderer::FreeMemory(int fontNumber) {
alfont_destroy_font(_fontData[fontNumber].AlFont);
_fontData.erase(fontNumber);
diff --git a/engines/ags/shared/font/ttf_font_renderer.h b/engines/ags/shared/font/ttf_font_renderer.h
index c8afd6c896b..80a30b492dc 100644
--- a/engines/ags/shared/font/ttf_font_renderer.h
+++ b/engines/ags/shared/font/ttf_font_renderer.h
@@ -49,6 +49,7 @@ public:
bool IsBitmapFont() override;
bool LoadFromDiskEx(int fontNumber, int fontSize, const FontRenderParams *params,
FontMetrics *metrics) override;
+ const char *GetName(int fontNumber) override;
private:
struct FontData {
diff --git a/engines/ags/shared/font/wfn_font_renderer.h b/engines/ags/shared/font/wfn_font_renderer.h
index a0d87a7c5cf..13600faf736 100644
--- a/engines/ags/shared/font/wfn_font_renderer.h
+++ b/engines/ags/shared/font/wfn_font_renderer.h
@@ -47,6 +47,7 @@ public:
bool IsBitmapFont() override;
bool LoadFromDiskEx(int fontNumber, int fontSize,
const FontRenderParams *params, FontMetrics *metrics) override;
+ const char *GetName(int fontNumber) override { return ""; }
private:
struct FontData {
More information about the Scummvm-git-logs
mailing list