Skip to content

Commit

Permalink
- implemented better aspect ratio control for fullscreen images.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
coelckers committed Mar 15, 2020
1 parent 2edbbac commit db5efdd
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 76 deletions.
2 changes: 2 additions & 0 deletions src/gamedata/gi.cpp
Expand Up @@ -116,6 +116,7 @@ const char* GameInfoBorders[] =
NULL
};


#define GAMEINFOKEY_CSTRING(key, variable, length) \
else if(nextKey.CompareNoCase(variable) == 0) \
{ \
Expand Down Expand Up @@ -382,6 +383,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")
Expand Down
1 change: 1 addition & 0 deletions src/gamedata/gi.h
Expand Up @@ -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;
};
Expand Down
58 changes: 57 additions & 1 deletion src/rendering/2d/v_draw.cpp
Expand Up @@ -375,8 +375,48 @@ bool DFrameBuffer::SetTextureParms(DrawParms *parms, FTexture *img, double xx, d
break;

case DTA_Fullscreen:
case DTA_FullscreenEx:
{
double aspect;
double srcwidth = img->GetDisplayWidthDouble();
double srcheight = img->GetDisplayHeightDouble();
int autoaspect = parms->fsscalemode;
aspect = autoaspect == 0 || (srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 200)? 1.333 : srcwidth / srcheight;

This comment has been minimized.

Copy link
@Gaerzi

Gaerzi Mar 15, 2020

Collaborator

(srcwidth == 320 && srcheight == 200) || (srcwidth == 640 && srcheight == 200)

Shouldn't it be 640x400 here, if it's the same ratio as 320x200?

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:
Expand Down Expand Up @@ -667,12 +707,28 @@ bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint3
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->GetDisplayWidthDouble();
parms->virtHeight = img->GetDisplayHeightDouble();
}
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->GetDisplayWidthDouble();
parms->virtHeight = img->GetDisplayHeightDouble();
}
Expand Down
71 changes: 0 additions & 71 deletions src/rendering/v_video.cpp
Expand Up @@ -702,51 +702,6 @@ DEFINE_ACTION_FUNCTION(_Screen, GetAspectRatio)
ACTION_RETURN_FLOAT(ActiveRatio(screen->GetWidth(), screen->GetHeight(), nullptr));
}

// Tries to guess the physical dimensions of the screen based on the
// screen's pixel dimensions. Can return:
// 0: 4:3
// 1: 16:9
// 2: 16:10
// 3: 17:10
// 4: 5:4
// 5: 17:10 (redundant, never returned)
// 6: 21:9
int CheckRatio (int width, int height, int *trueratio)
{
float aspect = width / (float)height;

static std::pair<float, int> ratioTypes[] =
{
{ 21 / 9.0f , 6 },
{ 16 / 9.0f , 1 },
{ 17 / 10.0f , 3 },
{ 16 / 10.0f , 2 },
{ 4 / 3.0f , 0 },
{ 5 / 4.0f , 4 },
{ 0.0f, 0 }
};

int ratio = ratioTypes[0].second;
float distance = fabs(ratioTypes[0].first - aspect);
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
{
float d = fabs(ratioTypes[i].first - aspect);
if (d < distance)
{
ratio = ratioTypes[i].second;
distance = d;
}
}

int fakeratio = ActiveFakeRatio(width, height);
if (fakeratio == -1)
fakeratio = ratio;

if (trueratio)
*trueratio = ratio;
return fakeratio;
}

int AspectBaseWidth(float aspect)
{
return (int)round(240.0f * aspect * 3.0f);
Expand Down Expand Up @@ -781,32 +736,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);
}

CCMD(vid_setsize)
{
if (argv.argc() < 3)
Expand Down
8 changes: 4 additions & 4 deletions src/rendering/v_video.h
Expand Up @@ -240,6 +240,8 @@ enum
DTA_Burn, // activates the burn shader for this element
DTA_Spacing, // Strings only: Additional spacing between characters
DTA_Monospace, // Fonts only: Use a fixed distance between characters.

DTA_FullscreenEx,
};

enum EMonospacing : int
Expand Down Expand Up @@ -303,9 +305,10 @@ struct DrawParms
int maxstrlen;
bool fortext;
bool virtBottom;
bool burn;
uint8_t fsscalemode;
double srcx, srcy;
double srcwidth, srcheight;
bool burn;
};

struct Va_List
Expand Down Expand Up @@ -621,8 +624,6 @@ FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr)
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc = nullptr);
int V_GetColor(const uint32_t *palette, FScanner &sc);

int CheckRatio (int width, int height, int *trueratio=NULL);
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }

float ActiveRatio (int width, int height, float *trueratio = NULL);
Expand All @@ -633,7 +634,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);
int GetConScale(int altval);
Expand Down

0 comments on commit db5efdd

Please sign in to comment.