view GUI/GUIFont.cpp @ 2514:16bae6fd06e1

.
author Ritor1
date Thu, 02 Oct 2014 19:40:13 +0600
parents a77c34acdbc9
children a902abdfc7f2
line wrap: on
line source

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#define _CRT_SECURE_NO_WARNINGS
#include <string>
#include "Engine/ErrorHandling.h"

#include "Engine/LOD.h"
#include "GUIFont.h"
#include "GUIWindow.h"
#include "Engine/Graphics/Render.h"

#include "Engine/mm7_data.h"


extern LODFile_IconsBitmaps *pIcons_LOD;


struct GUIFont *pAutonoteFont;
struct GUIFont *pSpellFont;
struct GUIFont *pFontArrus;
struct GUIFont *pFontLucida;
struct GUIFont *pBook2Font;
struct GUIFont *pBookFont;
struct GUIFont *pFontCreate;
struct GUIFont *pFontCChar;
struct GUIFont *pFontComic;
struct GUIFont *pFontSmallnum;

char temp_string[2048];

std::array<char, 10000> pTmpBuf3;

void DrawCharToBuff(unsigned short* uXpos,unsigned char* pCharPixels, int uCharWidth, int uCharHeight, unsigned __int16* pFontPalette, __int16 draw_color, int line_width);


//----- (0044C448) --------------------------------------------------------
GUIFont *LoadFont(const char *pFontFile, const char *pFontPalette, ...)
{	
    int pallete_index; // eax@3
    GUIFont *pFont;
    unsigned int palletes_count =0;
    va_list palettes_ptr;

    pFont = (GUIFont *)pIcons_LOD->LoadRaw(pFontFile, 0);
    va_start(palettes_ptr, pFontFile);

    while  (NULL!=(pFontPalette=va_arg(palettes_ptr, const char *)))
        {
        pallete_index =pIcons_LOD->LoadTexture(pFontPalette, TEXTURE_16BIT_PALETTE);
        if (pallete_index == -1)
            Error("Unable to open %s", pFontPalette);

        pFont->pFontPalettes[palletes_count] = pIcons_LOD->pTextures[pallete_index].pPalette16;
        ++palletes_count;
        }
    va_end(palettes_ptr);
    pFont->palletes_count = palletes_count;
    return pFont;
}

//----- (0044D2FD) --------------------------------------------------------
void GUIFont::_44D2FD_prolly_draw_credits_entry( GUIFont *pSecondFont, int uFrameX, int uFrameY, unsigned int w, unsigned int h, 
                                                 unsigned __int16 firstColor, unsigned __int16 secondColor, const char *pString, 
                                                 unsigned __int16 *pPixels, unsigned int uPixelsWidth )
    {
  char *work_string; // eax@1
  unsigned __int16 *curr_pixel_pos; // esi@1
  GUIFont *currentFont; // edi@4
  signed int start_str_pos; // ecx@4
  signed int line_w; // eax@6
  GUIWindow draw_window; // [sp+Ch] [bp-5Ch]@
  int currentColor; // [sp+74h] [bp+Ch]@4
  int half_frameX; // [sp+80h] [bp+18h]@2

  draw_window.uFrameHeight = h;
  draw_window.uFrameW = uFrameY + h - 1;
  draw_window.uFrameWidth = w;
  draw_window.uFrameZ = uFrameX + w - 1;
  ui_current_text_color = firstColor;
  draw_window.uFrameX = uFrameX;
  draw_window.uFrameY = uFrameY;

  work_string = GUIFont::FitTwoFontStringINWindow(pString, this, pSecondFont, &draw_window, 0, 1);
  work_string = strtok(work_string, "\n");
  curr_pixel_pos = &pPixels[uPixelsWidth * uFrameY];
  if ( work_string )
  {
    half_frameX = uFrameX >> 1;
    while ( 1 )
    {
      currentFont = this;
      ui_current_text_color = firstColor;
      start_str_pos = 0;
      currentColor = firstColor;
      if ( *work_string == '_' )
      {
        currentFont = pSecondFont;
        currentColor = secondColor;
        ui_current_text_color = secondColor;
        start_str_pos = 1;
      }
      line_w = (signed int)(w - currentFont->GetLineWidth(&work_string[start_str_pos]))/2;
      if ( line_w < 0 )
        line_w = 0;
      currentFont->DrawTextLineToBuff(currentColor, secondColor, &curr_pixel_pos[line_w + half_frameX], work_string, uPixelsWidth);
      curr_pixel_pos += uPixelsWidth * (currentFont->uFontHeight - 3);
      work_string = strtok(0, "\n");
      if ( !work_string )
        break;
    }
  }
}

//----- (0044D1E7) --------------------------------------------------------
void GUIFont::DrawTextLine( unsigned int uDefaultColor, signed int uX, signed int uY, 
                            const char *text, int max_len_pix )
{
    signed int uX_pos; // edi@3
    unsigned char c; // cl@4
    unsigned __int16 draw_color; // cx@12
    unsigned __int8 *pCharPixels; // eax@12
    char color_code[20]; // [sp+Ch] [bp-1Ch]@16
    int text_length; // [sp+20h] [bp-8h]@2
    int text_color; // [sp+24h] [bp-4h]@1
    int uCharWidth; // [sp+30h] [bp+8h]@9

    if ( !text )
        return;
    text_color = ui_current_text_color;
    text_length = strlen(text);
    uX_pos=uX;
    for (int i=0; i<text_length; ++i )
        {
        c = text[i];
        if ( IsCharValid(c) )
            {
            switch (c)
                {
            case '\n':	//Line Feed 0A 10:
                return;
                break;
            case '\f':  //Form Feed, page eject  0C 12 
                strncpy(color_code, &text[i + 1], 5);
                color_code[5] = 0;
                text_color = atoi(color_code);
                ui_current_text_color = text_color;
                i += 5;	  
                break;
            case '\t':	// Horizontal tab 09
            case '\r':   //Carriage Return 0D 13                 
                break;
            default:
                uCharWidth = pMetrics[c].uWidth;
                if ( uCharWidth )
                    {
                    if ( i > 0 )
                        uX_pos += pMetrics[c].uLeftSpacing;
                    draw_color = text_color;
                    pCharPixels = &pFontData[font_pixels_offset[c]];
                    if ( !text_color )
                        draw_color = -1;
                    pRenderer->DrawText(uX_pos, uY, pCharPixels, uCharWidth, uFontHeight, pFontPalettes[0], draw_color, 0);
                    uX_pos += uCharWidth;
                    if ( i < text_length )
                        uX_pos += pMetrics[c].uRightSpacing;
                    }
                }
            }
        }
    
}

//----- (0040F845) --------------------------------------------------------
void DrawCharToBuff( unsigned short* uXpos,unsigned char* pCharPixels, int uCharWidth, int uCharHeight, 
                            unsigned __int16* pFontPalette, __int16 draw_color, int line_width )
    {
    unsigned __int16* draw_buff; // edi@1
    unsigned char* pPixels; // esi@1
    unsigned char char_pxl; // eax@3

    draw_buff = uXpos;
    pPixels = pCharPixels;
    for(int i=0; i<uCharHeight; ++i)
        {
        for(int j=0; j<uCharWidth; ++j)
            {
            char_pxl = *pPixels++;
            if ( char_pxl )
                {
                if ( char_pxl == 1 )
                    *draw_buff = pFontPalette[1];     
                else         
                    *draw_buff = draw_color;         
                }
            ++draw_buff;
            }
        draw_buff+=line_width-uCharWidth;
        }

}

//----- (0044D0B5) --------------------------------------------------------
void GUIFont::DrawTextLineToBuff( int uColor, int a3, unsigned short* uX_buff_pos, const char *text, int line_width )
    {
  
  unsigned short* uX_pos; // edi@3
  unsigned char c; // cl@4
  unsigned __int16 draw_color; // cx@12
  unsigned __int8 *pCharPixels; // eax@12
  char color_code[20]; // [sp+Ch] [bp-1Ch]@16
  int text_length; // [sp+20h] [bp-8h]@2
  int text_color; // [sp+24h] [bp-4h]@1
  int uCharWidth; // [sp+30h] [bp+8h]@9

  if ( !text )
      return;
  text_color = ui_current_text_color;
  text_length = strlen(text);
  uX_pos=uX_buff_pos;
  for (int i=0; i<text_length; ++i )
      {
      c = text[i];
      if ( IsCharValid(c) )
          {
          switch (c)
              {
          case '\n':	//Line Feed 0A 10:
              return;
              break;
          case '\f':  //Form Feed, page eject  0C 12 
              strncpy(color_code, &text[i + 1], 5);
              color_code[5] = 0;
              text_color = atoi(color_code);
              ui_current_text_color = text_color;
              i += 5;	  
              break;
          case '\t':	// Horizontal tab 09
          case '_':                   
              break;
          default:
              uCharWidth = pMetrics[c].uWidth;
              if ( uCharWidth )
                  {
                  if ( i > 0 )
                      uX_pos += pMetrics[c].uLeftSpacing;
                  draw_color = text_color;
                  pCharPixels = &pFontData[font_pixels_offset[c]];
                  if ( !text_color )
                      draw_color = -1;
                  DrawCharToBuff(uX_pos, pCharPixels, uCharWidth, uFontHeight, pFontPalettes[0], draw_color, line_width);
                  uX_pos += uCharWidth;
                  if ( i < text_length )
                      uX_pos += pMetrics[c].uRightSpacing;
                  }
              }
          }
      }
}



//----- (0044C933) --------------------------------------------------------
char * GUIFont::FitTwoFontStringINWindow( const char *pString, GUIFont *pFontMain, GUIFont *pFontSecond, GUIWindow* pWindow, int startPixlOff, int a6 )
    {
 
  GUIFont *currentFont; // esi@3
  unsigned char c;
  int uInStrLen;
  char digits[4];
  int possible_transition_point;
  int string_pixel_Width;
  int start_pixel_offset;

  if (!pString)
      {
      MessageBoxW(nullptr, L"Invalid string passed !", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:445", 0);
      return 0;
      }
  currentFont=pFontMain; // esi@3
  uInStrLen = strlen(pString);
  Assert(uInStrLen < sizeof(pTmpBuf3));
  strcpy(pTmpBuf3.data(), pString);
  if (uInStrLen==0)
      return pTmpBuf3.data();

  start_pixel_offset=string_pixel_Width=startPixlOff;
  possible_transition_point=0;
  for(int i=0; i<uInStrLen; ++i) 
      {
      c=pTmpBuf3[i];
      if (pFontMain->IsCharValid(c))
          {
          switch (c)
              {
          case '\t':	// Horizontal tab 09
              {
              strncpy(digits, &pTmpBuf3[i+1],3);
              digits[3]=0;
              string_pixel_Width = atoi(digits)+startPixlOff;
              i+=3;
              break;
              }
          case  '\n':	//Line Feed 0A 10
              {
              string_pixel_Width=start_pixel_offset;
              possible_transition_point=i;
              currentFont=pFontMain;
              break;
              }
          case  '\f':   //Form Feed, page eject  0C 12
              {
              i+=5;  
              break;
              }
          case  '\r':   //Carriage Return 0D 13
              {
              if (!a6)
                  return (char*)pString;
              break;
              }
          case ' ' :
              {
              string_pixel_Width+=currentFont->pMetrics[c].uWidth;
              possible_transition_point=i;
              break;
              }
          case '_' :
              currentFont=pFontSecond;
              break;
          default:

              if ((string_pixel_Width+currentFont->pMetrics[c].uWidth+ currentFont->pMetrics[c].uLeftSpacing+
                  currentFont->pMetrics[c].uRightSpacing)<pWindow->uFrameWidth)
                  {
                  if(i>possible_transition_point)
                      string_pixel_Width+=currentFont->pMetrics[c].uLeftSpacing;
                  string_pixel_Width+=currentFont->pMetrics[c].uWidth;
                  if (i<uInStrLen)
                      string_pixel_Width+=currentFont->pMetrics[c].uRightSpacing;
                  }
              else
                  {
                  pTmpBuf3[possible_transition_point]='\n';
                      
                  if ( currentFont== pFontSecond)
                      {

                      for(int k=uInStrLen-1; k>=possible_transition_point+1; --k)
                          pTmpBuf3[k] = pTmpBuf3[k-1];

                      ++uInStrLen;
                      ++possible_transition_point;
                      pTmpBuf3[possible_transition_point] = '_';
                      
                      }
                     string_pixel_Width=start_pixel_offset;

                      for(int j=possible_transition_point;j<i; ++j ) 
                          {
                          c=pTmpBuf3[j];
                          if (pFontMain->IsCharValid(c))
                              {
                              if(j>possible_transition_point)
                                  string_pixel_Width+=pFontMain->pMetrics[c].uLeftSpacing;
                              string_pixel_Width+=pFontMain->pMetrics[c].uWidth;
                              if (j<i)
                                  string_pixel_Width+=pFontMain->pMetrics[c].uRightSpacing;

                              }
                          }                    
                  }
              }
          }
      }
  return pTmpBuf3.data();

}


//----- (0044C6C2) --------------------------------------------------------
char* GUIFont::GetPageTop( const char *pInString, GUIWindow *pWindow, unsigned int uX, int a5 )
{
  int text_height; // edi@1
  char *text_str; // ebx@3
  unsigned char c; // cl@4
  int text_length; 

  text_height = 0;

  if ( !pInString )
    return 0;
  text_str = FitTextInAWindow(pInString, this, pWindow, uX, 0);
  text_length = strlen(text_str);
  for ( int i = 0; i < text_length; ++i )
  {
    c = text_str[i];
    if ( IsCharValid(c) )
    {
      switch (c)
      {
        case '\n':	//Line Feed 0A 10:
          text_height = text_height + (uFontHeight - 3);
          if ( text_height >= (signed int)(a5 * (pWindow->uFrameHeight - (uFontHeight - 3))) )
            return &text_str[i];
          break;
        case '\f':  //Form Feed, page eject  0C 12
          i += 5;
          break;
        case '\t':	// Horizontal tab 09
        case '\r':   //Carriage Return 0D 13 
          i += 3;
          break;
      }
      if ( text_height >= (signed int)(a5 * pWindow->uFrameHeight) )
        break;
    }
  }
  return &text_str[0];
}

//----- (0044C62E) --------------------------------------------------------
int GUIFont::GetStringHeight2( GUIFont *secondFont, const char *text_str, GUIWindow* pWindow, int startX, int a6 )
    {
 
  int uAllHeght; 
  int uStringLen; 
  unsigned char c; 
  char *test_string; 

  if ( !text_str )
    return 0;
  uAllHeght = uFontHeight - 3;
  test_string = FitTwoFontStringINWindow(text_str, this, secondFont, pWindow, startX, 0);
  uStringLen = strlen(test_string);
  for (int i = 0; i < uStringLen; ++i)
      {
      c = test_string[i];
      if (IsCharValid(c))
          {
          switch (c)
              {
          case '\n':	//Line Feed 0A 10:
              uAllHeght+= uFontHeight - 3;
              break;
          case '\f':  //Form Feed, page eject  0C 12 
              i += 5;		  
              break;
          case '\t':	// Horizontal tab 09
          case '\r':   //Carriage Return 0D 13
              if (a6 != 1)
                  i += 3;
              break;
              }
          }
      }

  return uAllHeght;
}

//----- (0044C59D) --------------------------------------------------------
int GUIFont::CalcTextHeight( const char *pString, struct GUIWindow *pWindow, int uXOffset, int a5 )
{
  int uAllHeght; 
  int uStringLen; 
  unsigned char c; 
  char *test_string; 

  if (!pString)
    return 0;
  uAllHeght = uFontHeight - 6;
  test_string = FitTextInAWindow(pString, this, pWindow, uXOffset, 0);
  uStringLen = strlen(pString);
  for (int i = 0; i < uStringLen; ++i)
  {
    c = test_string[i];
    if (IsCharValid(c))
    {
      switch (c)
      {
        case '\n':	//Line Feed 0A 10:
          uAllHeght += uFontHeight - 3;
          break;
        case '\f':  //Form Feed, page eject  0C 12 
          i += 5;
          break;
        case '\t':	// Horizontal tab 09
        case '\r':   //Carriage Return 0D 13
          if (a5 != 1)
            i += 3;
          break;
      }
   }
  }
  return uAllHeght;
}

//----- (0044C51E) --------------------------------------------------------
int GUIFont::GetLineWidth(const char *pString)
	{
	int str_len; // ebp@3
	int string_line_width; // esi@3
	unsigned char c;

	if (!pString)
		return 0;
	str_len = strlen(pString);
	string_line_width = 0;
	for ( int i = 0; i < str_len; ++i )
		{
		c = pString[i];
		if (IsCharValid(c))
			{
			switch (c)
				{
			case '\t':
			case '\n':
			case '\r':
				return string_line_width;
			case '\f':
				i += 5;	  
				break;
			default:
				if (i > 0)
					string_line_width += pMetrics[c].uLeftSpacing;
				string_line_width += pMetrics[c].uWidth;
				if (i < str_len)
					string_line_width +=pMetrics[c].uRightSpacing;
				}
			}
		}
	return string_line_width;
	}


//----- (0044C502) --------------------------------------------------------
int GUIFont::AlignText_Center(unsigned int uCenterX, const char *pString)
{
  signed int position; // esi@1
 
  position = (signed int)(uCenterX - GetLineWidth(pString)) >> 1;
  if ( position >= 0 )
    return position;
  else
    return  0;
}

//----- (0044C768) --------------------------------------------------------
char * FitTextInAWindow( const char *pInString, GUIFont *pFont, GUIWindow *pWindow, signed int uX, int a5 )
{
  unsigned char c;
  int uInStrLen;
  char digits[4];
  int possible_transition_point;
  int string_pixel_Width;
  int start_pixel_offset;

  if (!pInString)
  {
    MessageBoxW(nullptr, L"Invalid string passed !", L"E:\\WORK\\MSDEV\\MM7\\MM7\\Code\\Font.cpp:445", 0);
    return 0;
  }
  uInStrLen = strlen(pInString);
  strcpy(&temp_string[0], pInString);
  if (uInStrLen == 0)
    return &temp_string[0];

  start_pixel_offset = string_pixel_Width=uX;
  possible_transition_point = 0;
  for ( int i = 0; i < uInStrLen; ++i )
  {
    c = temp_string[i];
    if (pFont->IsCharValid(c))
    {
      switch (c)
      {
        case '\t':	// Horizontal tab 09
        {
          strncpy(digits, &temp_string[i + 1],3);
          digits[3] = 0;
          string_pixel_Width = atoi(digits)+uX;
          i += 3;
          break;
        }
        case  '\n':	//Line Feed 0A 10 (конец строки)
        {
          string_pixel_Width = start_pixel_offset;
          possible_transition_point = i;
          break;
        }
        case  '\f':   //Form Feed, page eject  0C 12
        {
          i += 5;  
          break;
        }
        case  '\r':   //Carriage Return 0D 13
        {
          if ( !a5 )
            return (char*)pInString;
          break;
        }
        case ' '://пробел
        {
          string_pixel_Width += pFont->pMetrics[c].uWidth;
          possible_transition_point = i;
          break;
        }
        default:
          if ((string_pixel_Width + pFont->pMetrics[c].uWidth + pFont->pMetrics[c].uLeftSpacing +
               pFont->pMetrics[c].uRightSpacing) < pWindow->uFrameWidth )//наращивание длины строки или перенос
          {
            if ( i > possible_transition_point )
              string_pixel_Width += pFont->pMetrics[c].uLeftSpacing;
            string_pixel_Width += pFont->pMetrics[c].uWidth;
            if (i < uInStrLen)
              string_pixel_Width += pFont->pMetrics[c].uRightSpacing;
          }
          else//перенос строки и слова
          {
            temp_string[possible_transition_point] ='\n';
            string_pixel_Width = start_pixel_offset;
            if ( i > possible_transition_point )
            {
              for ( int j = possible_transition_point; j < i; ++j )
              {
                c = temp_string[j];
                if (pFont->IsCharValid(c))
                {
                  if ( j > possible_transition_point )
                    string_pixel_Width += pFont->pMetrics[c].uLeftSpacing;
                  string_pixel_Width += pFont->pMetrics[c].uWidth;
                  if ( j < i )
                    string_pixel_Width += pFont->pMetrics[c].uRightSpacing;
                }
              }
            }
          }
        }
    }
  }
  return &temp_string[0];
}
//----- (00414162) --------------------------------------------------------
void uGameUIFontMain_initialize()
{
  uGameUIFontMain = Color16(0xAu, 0, 0);
}

//----- (00414174) --------------------------------------------------------
void uGameUIFontShadow_initialize()
{
  uGameUIFontShadow = Color16(0xE6u, 214, 193);
}