- implemented better aspect ratio control for fullscreen images.

Due to backwards compatibility needs and for flexibility this needs to be controlled by a gameinfo setting (fullscreenautoaspect):

0: Treat all images as having an aspect ratio of 4:3, this is the default for compatibility reasons
1: Scale all images to fit the screen, i.e. either pillarbox or letterbox them.
2: Scale all images to fill the screen.
3: Scale all images so that the center 4:3 area is always fully visible. This is the recommended mode for 16:9 images designed to be shown with the sides being cropped on narrower displays.

A new DTA_ tag - DTA_FullscreenEx also exists which allows specifying the scale mode directly

# Conflicts:
#	src/rendering/v_video.cpp
#	src/v_draw.cpp

# Conflicts:
#	src/v_video.h
This commit is contained in:
Christoph Oelckers 2020-03-15 09:27:02 +01:00 committed by drfrag
parent b131230fe3
commit accd7d8c8a
5 changed files with 64 additions and 28 deletions

View file

@ -119,6 +119,7 @@ const char* GameInfoBorders[] =
NULL
};
#define GAMEINFOKEY_CSTRING(key, variable, length) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
@ -385,6 +386,7 @@ void FMapInfoParser::ParseGameInfo()
GAMEINFOKEY_DOUBLE(telefogheight, "telefogheight")
GAMEINFOKEY_DOUBLE(gibfactor, "gibfactor")
GAMEINFOKEY_INT(defKickback, "defKickback")
GAMEINFOKEY_INT(fullscreenautoaspect, "fullscreenautoaspect")
GAMEINFOKEY_STRING(SkyFlatName, "SkyFlatName")
GAMEINFOKEY_STRING(translator, "translator")
GAMEINFOKEY_COLOR(pickupcolor, "pickupcolor")

View file

@ -204,6 +204,7 @@ struct gameinfo_t
int berserkpic;
double normforwardmove[2];
double normsidemove[2];
int fullscreenautoaspect = 3;
const char *GetFinalePage(unsigned int num) const;
};

View file

@ -404,8 +404,48 @@ bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double
break;
case DTA_Fullscreen:
case DTA_FullscreenEx:
{
double aspect;
double srcwidth = img->GetScaledWidthDouble();
double srcheight = img->GetScaledHeightDouble();
int autoaspect = parms->fsscalemode;
aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 200)? 1.333 : srcwidth / srcheight;
parms->x = parms->y = 0;
break;
parms->keepratio = true;
auto screenratio = ActiveRatio(GetWidth(), GetHeight());
if (autoaspect == 3)
{
if (screenratio >= aspect || aspect < 1.4) autoaspect = 1; // screen is wider than the image -> pillarbox it. 4:3 images must also be pillarboxes if the screen is taller than the image
else if (screenratio > 1.32) autoaspect = 2; // on anything 4:3 and wider crop the sides of the image.
else
{
// special case: Crop image to 4:3 and then letterbox this. This avoids too much cropping on narrow windows.
double width4_3 = srcheight * (4. / 3.);
parms->destwidth = (double)GetWidth() * srcwidth / width4_3;
parms->destheight = GetHeight() * screenratio * (3. / 4.); // use 4:3 for the image
parms->y = (GetHeight() - parms->destheight) / 2;
parms->x = -(srcwidth - width4_3) / 2;
return false; // Do not call VirtualToRealCoords for this!
}
}
if ((screenratio > aspect) ^ (autoaspect == 2))
{
// pillarboxed or vertically cropped (i.e. scale to height)
parms->destheight = GetHeight();
parms->destwidth =GetWidth() * aspect / screenratio;
parms->x = (GetWidth() - parms->destwidth) / 2;
}
else
{
// letterboxed or horizontally cropped (i.e. scale to width)
parms->destwidth = GetWidth();
parms->destheight = GetHeight() * screenratio / aspect;
parms->y = (GetHeight() - parms->destheight) / 2;
}
return false; // Do not call VirtualToRealCoords for this!
}
case DTA_HUDRules:
case DTA_HUDRulesC:
@ -690,12 +730,28 @@ bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t t
break;
case DTA_Fullscreen:
boolval = ListGetInt(tags);
if (boolval)
{
assert(fortext == false);
if (img == NULL) return false;
parms->cleanmode = DTA_Fullscreen;
parms->fsscalemode = (uint8_t)gameinfo.fullscreenautoaspect;
parms->virtWidth = img->GetScaledWidthDouble();
parms->virtHeight = img->GetScaledHeightDouble();
}
break;
case DTA_FullscreenEx:
intval = ListGetInt(tags);
if (intval >= 0 && intval <= 3)
{
assert(fortext == false);
if (img == NULL) return false;
parms->cleanmode = DTA_Fullscreen;
parms->fsscalemode = (uint8_t)intval;
parms->virtWidth = img->GetScaledWidthDouble();
parms->virtHeight = img->GetScaledHeightDouble();
}

View file

@ -1719,32 +1719,6 @@ bool AspectTallerThanWide(float aspect)
return aspect < 1.333f;
}
void ScaleWithAspect (int &w, int &h, int Width, int Height)
{
int resRatio = CheckRatio (Width, Height);
int screenRatio;
CheckRatio (w, h, &screenRatio);
if (resRatio == screenRatio)
return;
double yratio;
switch(resRatio)
{
case 0: yratio = 4./3.; break;
case 1: yratio = 16./9.; break;
case 2: yratio = 16./10.; break;
case 3: yratio = 17./10.; break;
case 4: yratio = 5./4.; break;
case 6: yratio = 21./9.; break;
default: return;
}
double y = w/yratio;
if (y > h)
w = static_cast<int>(h * yratio);
else
h = static_cast<int>(y);
}
void IVideo::DumpAdapters ()
{
Printf("Multi-monitor support unavailable.\n");

View file

@ -132,6 +132,8 @@ enum
DTA_LegacyRenderStyle, // takes an old-style STYLE_* constant instead of an FRenderStyle
DTA_Spacing, // Strings only: Additional spacing between characters
DTA_Monospace, // Fonts only: Use a fixed distance between characters.
DTA_FullscreenEx,
};
enum EMonospacing : int
@ -194,6 +196,8 @@ struct DrawParms
int maxstrlen;
bool fortext;
bool virtBottom;
bool burn;
uint8_t fsscalemode;
};
struct Va_List
@ -624,7 +628,6 @@ int AspectBaseHeight(float aspect);
double AspectPspriteOffset(float aspect);
int AspectMultiplier(float aspect);
bool AspectTallerThanWide(float aspect);
void ScaleWithAspect(int &w, int &h, int Width, int Height);
int GetUIScale(int altval);