diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 80a080a441..3897cd9b4a 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -112,7 +112,9 @@ void STACK_ARGS DCanvas::DrawTexture (FTexture *img, double x, double y, int tag va_start(tags, tags_first); DrawParms parms; - if (!ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, false)) + bool res = ParseDrawTextureTags(img, x, y, tags_first, tags, &parms, false); + va_end(tags); + if (!res) { return; } @@ -249,10 +251,11 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { + double wi = MIN(parms.windowright, parms.texwidth); double xscale = parms.destwidth / parms.texwidth; x0 += parms.windowleft * xscale; frac += FLOAT2FIXED(parms.windowleft); - x2 -= (parms.texwidth - parms.windowright) * xscale; + x2 -= (parms.texwidth - wi) * xscale; } if (x0 < parms.lclip) { @@ -330,18 +333,111 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) #endif } +bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const +{ + if (img != NULL) + { + parms->x = xx; + parms->y = yy; + parms->texwidth = img->GetScaledWidthDouble(); + parms->texheight = img->GetScaledHeightDouble(); + if (parms->top == INT_MAX || parms->fortext) + { + parms->top = img->GetScaledTopOffset(); + } + if (parms->left == INT_MAX || parms->fortext) + { + parms->left = img->GetScaledLeftOffset(); + } + if (parms->destwidth == INT_MAX || parms->fortext) + { + parms->destwidth = img->GetScaledWidthDouble(); + } + if (parms->destheight == INT_MAX || parms->fortext) + { + parms->destheight = img->GetScaledHeightDouble(); + } + + switch (parms->cleanmode) + { + default: + break; + + case DTA_Clean: + parms->x = (parms->x - 160.0) * CleanXfac + (Width * 0.5); + parms->y = (parms->y - 100.0) * CleanYfac + (Height * 0.5); + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; + break; + + case DTA_CleanNoMove: + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; + break; + + case DTA_CleanNoMove_1: + parms->destwidth = parms->texwidth * CleanXfac_1; + parms->destheight = parms->texheight * CleanYfac_1; + break; + + case DTA_Fullscreen: + parms->x = parms->y = 0; + break; + + case DTA_HUDRules: + case DTA_HUDRulesC: + { + bool xright = parms->x < 0; + bool ybot = parms->y < 0; + + if (hud_scale) + { + parms->x *= CleanXfac; + if (parms->cleanmode == DTA_HUDRulesC) + parms->x += Width * 0.5; + else if (xright) + parms->x = Width + parms->x; + parms->y *= CleanYfac; + if (ybot) + parms->y = Height + parms->y; + parms->destwidth = parms->texwidth * CleanXfac; + parms->destheight = parms->texheight * CleanYfac; + } + else + { + if (parms->cleanmode == DTA_HUDRulesC) + parms->x += Width * 0.5; + else if (xright) + parms->x = Width + parms->x; + if (ybot) + parms->y = Height + parms->y; + } + break; + } + } + if (parms->virtWidth != Width || parms->virtHeight != Height) + { + VirtualToRealCoords(parms->x, parms->y, parms->destwidth, parms->destheight, + parms->virtWidth, parms->virtHeight, parms->virtBottom, !parms->keepratio); + } + } + return false; +} + bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag, va_list tags, DrawParms *parms, bool fortext) const { INTBOOL boolval; int intval; bool translationset = false; - bool virtBottom; bool fillcolorset = false; - if (img == NULL || img->UseType == FTexture::TEX_Null) + if (!fortext) { - va_end(tags); - return false; + if (img == NULL || img->UseType == FTexture::TEX_Null) + { + va_end(tags); + return false; + } } // Do some sanity checks on the coordinates. @@ -351,21 +447,17 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag return false; } - virtBottom = false; - - parms->texwidth = img->GetScaledWidthDouble(); - parms->texheight = img->GetScaledHeightDouble(); - + parms->fortext = fortext; parms->windowleft = 0; - parms->windowright = parms->texwidth; + parms->windowright = INT_MAX; parms->dclip = this->GetHeight(); parms->uclip = 0; parms->lclip = 0; parms->rclip = this->GetWidth(); - parms->destwidth = parms->windowright; - parms->destheight = parms->texheight; - parms->top = img->GetScaledTopOffset(); - parms->left = img->GetScaledLeftOffset(); + parms->left = INT_MAX; + parms->top = INT_MAX; + parms->destwidth = INT_MAX; + parms->destheight = INT_MAX; parms->Alpha = 1.f; parms->fillcolor = -1; parms->remap = NULL; @@ -383,48 +475,50 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag parms->bilinear = false; parms->specialcolormap = NULL; parms->colormapstyle = NULL; - - parms->x = x; - parms->y = y; + parms->cleanmode = DTA_Base; + parms->scalex = parms->scaley = 1; + parms->cellx = parms->celly = 0; + parms->maxstrlen = INT_MAX; + parms->virtBottom = false; // Parse the tag list for attributes. (For floating point attributes, // consider that the C ABI dictates that all floats be promoted to // doubles when passed as function arguments.) while (tag != TAG_DONE) { - va_list *more_p; DWORD data; switch (tag) { - case TAG_IGNORE: default: data = va_arg(tags, DWORD); break; - case TAG_MORE: - more_p = va_arg(tags, va_list *); - va_end (tags); -#ifndef NO_VA_COPY - va_copy (tags, *more_p); -#else - tags = *more_p; -#endif - break; - case DTA_DestWidth: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; parms->destwidth = va_arg(tags, int); break; case DTA_DestWidthF: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; parms->destwidth = va_arg(tags, double); break; case DTA_DestHeight: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; parms->destheight = va_arg(tags, int); break; case DTA_DestHeightF: + assert(fortext == false); + if (fortext) return false; + parms->cleanmode = DTA_Base; parms->destheight = va_arg(tags, double); break; @@ -432,10 +526,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->x = (parms->x - 160.0) * CleanXfac + (Width * 0.5); - parms->y = (parms->y - 100.0) * CleanYfac + (Height * 0.5); - parms->destwidth = parms->texwidth * CleanXfac; - parms->destheight = parms->texheight * CleanYfac; + parms->scalex = 1; + parms->scaley = 1; + parms->cleanmode = tag; } break; @@ -443,8 +536,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->destwidth = parms->texwidth * CleanXfac; - parms->destheight = parms->texheight * CleanYfac; + parms->scalex = CleanXfac; + parms->scaley = CleanYfac; + parms->cleanmode = tag; } break; @@ -452,8 +546,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->destwidth = parms->texwidth * CleanXfac_1; - parms->destheight = parms->texheight * CleanYfac_1; + parms->scalex = CleanXfac_1; + parms->scaley = CleanYfac_1; + parms->cleanmode = tag; } break; @@ -461,6 +556,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag boolval = va_arg(tags, INTBOOL); if (boolval) { + parms->cleanmode = DTA_Base; + parms->scalex = 1; + parms->scaley = 1; parms->virtWidth = 320; parms->virtHeight = 200; } @@ -470,56 +568,37 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag boolval = va_arg(tags, INTBOOL); if (boolval) { + parms->cleanmode = DTA_Base; + parms->scalex = 1; + parms->scaley = 1; parms->virtWidth = 320; parms->virtHeight = 200; } - virtBottom = true; + parms->virtBottom = true; break; case DTA_HUDRules: - { - bool xright = parms->x < 0; - bool ybot = parms->y < 0; - intval = va_arg(tags, int); - - if (hud_scale) - { - parms->x *= CleanXfac; - if (intval == HUD_HorizCenter) - parms->x += Width * 0.5; - else if (xright) - parms->x = Width + parms->x; - parms->y *= CleanYfac; - if (ybot) - parms->y = Height + parms->y; - parms->destwidth = parms->texwidth * CleanXfac; - parms->destheight = parms->texheight * CleanYfac; - } - else - { - if (intval == HUD_HorizCenter) - parms->x += Width * 0.5; - else if (xright) - parms->x = Width + parms->x; - if (ybot) - parms->y = Height + parms->y; - } - } + intval = va_arg(tags, int); + parms->cleanmode = intval == HUD_HorizCenter ? DTA_HUDRulesC : DTA_HUDRules; break; case DTA_VirtualWidth: + parms->cleanmode = DTA_Base; parms->virtWidth = va_arg(tags, int); break; case DTA_VirtualWidthF: + parms->cleanmode = DTA_Base; parms->virtWidth = va_arg(tags, double); break; case DTA_VirtualHeight: + parms->cleanmode = DTA_Base; parms->virtHeight = va_arg(tags, int); break; case DTA_VirtualHeightF: + parms->cleanmode = DTA_Base; parms->virtHeight = va_arg(tags, double); break; @@ -527,7 +606,9 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag boolval = va_arg(tags, INTBOOL); if (boolval) { - parms->x = parms->y = 0; + assert(fortext == false); + if (img == NULL) return false; + parms->cleanmode = DTA_Fullscreen; parms->virtWidth = img->GetScaledWidthDouble(); parms->virtHeight = img->GetScaledHeightDouble(); } @@ -567,50 +648,70 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag break; case DTA_TopOffset: + assert(fortext == false); + if (fortext) return false; parms->top = va_arg(tags, int); break; case DTA_TopOffsetF: + assert(fortext == false); + if (fortext) return false; parms->top = va_arg(tags, double); break; case DTA_LeftOffset: + assert(fortext == false); + if (fortext) return false; parms->left = va_arg(tags, int); break; case DTA_LeftOffsetF: + assert(fortext == false); + if (fortext) return false; parms->left = va_arg(tags, double); break; case DTA_CenterOffset: + assert(fortext == false); + if (fortext) return false; if (va_arg(tags, int)) { - parms->left = parms->texwidth * 0.5; - parms->top = parms->texheight * 0.5; + parms->left = img->GetScaledWidthDouble() * 0.5; + parms->top = img->GetScaledHeightDouble() * 0.5; } break; case DTA_CenterBottomOffset: + assert(fortext == false); + if (fortext) return false; if (va_arg(tags, int)) { - parms->left = parms->texwidth * 0.5; - parms->top = parms->texheight; + parms->left = img->GetScaledWidthDouble() * 0.5; + parms->top = img->GetScaledHeightDouble(); } break; case DTA_WindowLeft: + assert(fortext == false); + if (fortext) return false; parms->windowleft = va_arg(tags, int); break; case DTA_WindowLeftF: + assert(fortext == false); + if (fortext) return false; parms->windowleft = va_arg(tags, double); break; case DTA_WindowRight: + assert(fortext == false); + if (fortext) return false; parms->windowright = va_arg(tags, int); break; case DTA_WindowRightF: + assert(fortext == false); + if (fortext) return false; parms->windowright = va_arg(tags, double); break; @@ -692,6 +793,19 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag case DTA_ColormapStyle: parms->colormapstyle = va_arg(tags, FColormapStyle *); break; + + case DTA_TextLen: + parms->maxstrlen = va_arg(tags, int); + break; + + case DTA_CellX: + parms->cellx = va_arg(tags, int); + break; + + case DTA_CellY: + parms->celly = va_arg(tags, int); + break; + } tag = va_arg(tags, DWORD); } @@ -702,15 +816,14 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, double x, double y, DWORD tag return false; } - if (parms->virtWidth != Width || parms->virtHeight != Height) + if (img != NULL) { - VirtualToRealCoords(parms->x, parms->y, parms->destwidth, parms->destheight, - parms->virtWidth, parms->virtHeight, virtBottom, !parms->keepratio); - } + SetTextureParms(parms, img, x, y); - if (parms->destwidth <= 0 || parms->destheight <= 0) - { - return false; + if (parms->destwidth <= 0 || parms->destheight <= 0) + { + return false; + } } if (parms->remap != NULL) diff --git a/src/v_text.cpp b/src/v_text.cpp index f8e89b566b..7c97b0e6a6 100644 --- a/src/v_text.cpp +++ b/src/v_text.cpp @@ -52,7 +52,7 @@ // // Write a single character using the given font // -void STACK_ARGS DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, ...) +void STACK_ARGS DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, int tag_first, ...) { if (font == NULL) return; @@ -65,11 +65,17 @@ void STACK_ARGS DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, B if (NULL != (pic = font->GetChar (character, &dummy))) { - const FRemapTable *range = font->GetColorTranslation ((EColorRange)normalcolor); - va_list taglist; - va_start (taglist, character); - DrawTexture (pic, x, y, DTA_Translation, range, TAG_MORE, &taglist); - va_end (taglist); + DrawParms parms; + va_list tags; + va_start(tags, tag_first); + bool res = ParseDrawTextureTags(pic, x, y, tag_first, tags, &parms, false); + va_end(tags); + if (!res) + { + return; + } + parms.remap = font->GetColorTranslation((EColorRange)normalcolor); + DrawTextureParms(pic, parms); } } @@ -78,135 +84,53 @@ void STACK_ARGS DCanvas::DrawChar (FFont *font, int normalcolor, int x, int y, B // // Write a string using the given font // -void DCanvas::DrawTextV(FFont *font, int normalcolor, int x, int y, const char *string, va_list taglist) +void STACK_ARGS DCanvas::DrawText(FFont *font, int normalcolor, int x, int y, const char *string, int tag_first, ...) { INTBOOL boolval; - va_list tags; uint32 tag; - int maxstrlen = INT_MAX; - int w, maxwidth; + int w; const BYTE *ch; int c; int cx; int cy; int boldcolor; - const FRemapTable *range; - int height; - int forcedwidth = 0; - int scalex, scaley; + FRemapTable *range; int kerning; FTexture *pic; + DrawParms parms; + + va_list tags; if (font == NULL || string == NULL) return; + va_start(tags, tag_first); + bool res = ParseDrawTextureTags(nullptr, 0, 0, tag_first, tags, &parms, true); + va_end(tags); + if (!res) + { + return; + } + + + if (parms.celly == 0) parms.celly = font->GetHeight() + 1; + parms.celly *= parms.scaley; + if (normalcolor >= NumTextColors) normalcolor = CR_UNTRANSLATED; boldcolor = normalcolor ? normalcolor - 1 : NumTextColors - 1; range = font->GetColorTranslation ((EColorRange)normalcolor); - height = font->GetHeight () + 1; + kerning = font->GetDefaultKerning (); ch = (const BYTE *)string; cx = x; cy = y; - // Parse the tag list to see if we need to adjust for scaling. - maxwidth = Width; - scalex = scaley = 1; - -#ifndef NO_VA_COPY - va_copy(tags, taglist); -#else - tags = taglist; -#endif - tag = va_arg(tags, uint32); - - while (tag != TAG_DONE) - { - va_list *more_p; - DWORD data; - - switch (tag) - { - case TAG_IGNORE: - default: - data = va_arg (tags, DWORD); - break; - - case TAG_MORE: - more_p = va_arg (tags, va_list*); - va_end (tags); -#ifndef NO_VA_COPY - va_copy (tags, *more_p); -#else - tags = *more_p; -#endif - break; - - // We don't handle these. :( - case DTA_DestWidth: - case DTA_DestHeight: - case DTA_Translation: - assert("Bad parameter for DrawText" && false); - return; - - case DTA_CleanNoMove_1: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - scalex = CleanXfac_1; - scaley = CleanYfac_1; - maxwidth = Width - (Width % scalex); - } - break; - - case DTA_CleanNoMove: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - scalex = CleanXfac; - scaley = CleanYfac; - maxwidth = Width - (Width % scalex); - } - break; - - case DTA_Clean: - case DTA_320x200: - boolval = va_arg (tags, INTBOOL); - if (boolval) - { - scalex = scaley = 1; - maxwidth = 320; - } - break; - - case DTA_VirtualWidth: - maxwidth = va_arg (tags, int); - scalex = scaley = 1; - break; - - case DTA_TextLen: - maxstrlen = va_arg (tags, int); - break; - - case DTA_CellX: - forcedwidth = va_arg (tags, int); - break; - - case DTA_CellY: - height = va_arg (tags, int); - break; - } - tag = va_arg (tags, uint32); - } - va_end(tags); - - height *= scaley; - while ((const char *)ch - string < maxstrlen) + while ((const char *)ch - string < parms.maxstrlen) { c = *ch++; if (!c) @@ -225,53 +149,26 @@ void DCanvas::DrawTextV(FFont *font, int normalcolor, int x, int y, const char * if (c == '\n') { cx = x; - cy += height; + cy += parms.celly; continue; } if (NULL != (pic = font->GetChar (c, &w))) { -#ifndef NO_VA_COPY - va_copy(tags, taglist); -#else - tags = taglist; -#endif - if (forcedwidth) + parms.remap = range; + SetTextureParms(&parms, pic, cx, cy); + if (parms.cellx) { - w = forcedwidth; - DrawTexture (pic, cx, cy, - DTA_Translation, range, - DTA_DestWidth, forcedwidth, - DTA_DestHeight, height, - TAG_MORE, &tags); + w = parms.cellx; + parms.destwidth = parms.cellx; + parms.destheight = parms.celly; } - else - { - DrawTexture (pic, cx, cy, - DTA_Translation, range, - TAG_MORE, &tags); - } - va_end (tags); + DrawTextureParms(pic, parms); } - cx += (w + kerning) * scalex; + cx += (w + kerning) * parms.scalex; } - va_end(taglist); } -void STACK_ARGS DCanvas::DrawText (FFont *font, int normalcolor, int x, int y, const char *string, ...) -{ - va_list tags; - va_start(tags, string); - DrawTextV(font, normalcolor, x, y, string, tags); -} - -// A synonym so that this can still be used in files that #include Windows headers -void STACK_ARGS DCanvas::DrawTextA (FFont *font, int normalcolor, int x, int y, const char *string, ...) -{ - va_list tags; - va_start(tags, string); - DrawTextV(font, normalcolor, x, y, string, tags); -} // // Find string width using this font diff --git a/src/v_video.h b/src/v_video.h index 6d3c9c226d..ef6efc2187 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -63,8 +63,6 @@ class FTexture; #define TAG_DONE (0) /* Used to indicate the end of the Tag list */ #define TAG_END (0) /* Ditto */ -#define TAG_IGNORE (1) /* Ignore this Tag */ -#define TAG_MORE (2) /* Ends this list and continues with the */ /* list pointed to in ti_Data */ #define TAG_USER ((DWORD)(1u<<30)) @@ -102,6 +100,7 @@ enum DTA_ClipRight, // don't draw anything at or to the right of this column (on dest, not source) DTA_Masked, // true(default)=use masks from texture, false=ignore masks DTA_HUDRules, // use fullscreen HUD rules to position and size textures + DTA_HUDRulesC, // only used internally for marking HUD_HorizCenter DTA_KeepRatio, // doesn't adjust screen size for DTA_Virtual* if the aspect ratio is not 4:3 DTA_RenderStyle, // same as render style for actors DTA_ColorOverlay, // DWORD: ARGB to overlay on top of image; limited to black for software @@ -149,6 +148,7 @@ struct DrawParms double virtHeight; double windowleft; double windowright; + int cleanmode; int dclip; int uclip; int lclip; @@ -170,6 +170,11 @@ struct DrawParms FRenderStyle style; struct FSpecialColormap *specialcolormap; struct FColormapStyle *colormapstyle; + int scalex, scaley; + int cellx, celly; + int maxstrlen; + bool fortext; + bool virtBottom; }; // @@ -241,6 +246,7 @@ public: // Text drawing functions ----------------------------------------------- // 2D Texture drawing + bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const; void STACK_ARGS DrawTexture (FTexture *img, double x, double y, int tags, ...); void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; @@ -249,13 +255,12 @@ public: void VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const; - // 2D Text drawing - void STACK_ARGS DrawText (FFont *font, int normalcolor, int x, int y, const char *string, ...); -#ifndef DrawText // See WinUser.h for the definition of DrawText as a macro - void STACK_ARGS DrawTextA (FFont *font, int normalcolor, int x, int y, const char *string, ...); +#ifdef DrawText +#undef DrawText // See WinUser.h for the definition of DrawText as a macro #endif - void DrawTextV (FFont *font, int normalcolor, int x, int y, const char *string, va_list tags); - void STACK_ARGS DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, ...); + // 2D Text drawing + void STACK_ARGS DrawText (FFont *font, int normalcolor, int x, int y, const char *string, int tag_first, ...); + void STACK_ARGS DrawChar (FFont *font, int normalcolor, int x, int y, BYTE character, int tag_first, ...); protected: BYTE *Buffer; diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 4ef6fa739a..efdced151c 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2805,10 +2805,11 @@ void D3DFB::DrawTextureParms (FTexture *img, DrawParms &parms) } if (parms.windowleft > 0 || parms.windowright < parms.texwidth) { + double wi = MIN(parms.windowright, parms.texwidth); x0 += parms.windowleft * xscale; u0 = float(u0 + parms.windowleft * uscale); - x1 -= (parms.texwidth - parms.windowright) * xscale; - u1 = float(u1 - (parms.texwidth - parms.windowright) * uscale); + x1 -= (parms.texwidth - wi) * xscale; + u1 = float(u1 - (parms.texwidth - wi) * uscale); } #if 0