HSURFACE CInterfaceResMgr::CreateSurfaceFromString(CLTGUIFont *pFont, char *lpszString, HLTCOLOR hBackColor, int extraPixelsX, int extraPixelsY, int nWidth) { HSTRING hString = g_pLTClient->CreateString(lpszString); return CreateSurfaceFromString(pFont, hString, hBackColor, extraPixelsX, extraPixelsY, nWidth); g_pLTClient->FreeString(hString); }
HSURFACE CTextHelper::CreateSurfaceFromString (ILTClient* pClientDE, CBitmapFont* pFont, int strID, int nReplacementFont) { if (!pClientDE) return LTNULL; HSTRING hStr = pClientDE->FormatString (strID); if (!hStr) return LTNULL; HSURFACE hSurf = CreateSurfaceFromString (pClientDE, pFont, pClientDE->GetStringData (hStr), nReplacementFont); pClientDE->FreeString (hStr); return hSurf; }
HSURFACE CTextHelper::CreateSurfaceFromString (ILTClient* pClientDE, CBitmapFont* pFont, char* str, int nReplacementFont) { if (!pClientDE || !pFont || !str) return LTNULL; if (nReplacementFont == 0) nReplacementFont = IDS_REPLACEMENTFONT; // If the font is not initialized, call a different function using the system font... if (!pFont->IsValid()) { // hack to help localization - we need to know if this is a "selected" font or a "normal" font // this assumes font names that are selected end in an "s" identifier and the extension ".pcx"... LTBOOL bSelected = (pFont->GetImageName()[strlen (pFont->GetImageName()) - 5] == 's'); // determine the font height LTFLOAT nFontHeight = 0.0f; if (strcmp (pFont->GetClassName(), "CFont08") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT08, 8.0f); } else if (strcmp (pFont->GetClassName(), "CFont12") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT12, 12.0f); } else if (strcmp (pFont->GetClassName(), "CFont18") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT18, 18.0f); } else if (strcmp (pFont->GetClassName(), "CFont28") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT28, 28.0f); } // determine the preferred font width LTFLOAT nRatio = 0.5f; HCONSOLEVAR hVar = pClientDE->GetConsoleVar ("FontWidthHeightRatio"); if (hVar) { nRatio = pClientDE->GetVarValueFloat (hVar); } LTFLOAT nFontWidth = nFontHeight * nRatio; // create the font definition HSTRING hstrFont = pClientDE->FormatString (nReplacementFont); if (hstrFont == NULL) hstrFont = pClientDE->FormatString (IDS_REPLACEMENTFONT); FONT fontdef (const_cast<char *>(pClientDE->GetStringData(hstrFont)), (int)nFontWidth, (int)nFontHeight); pClientDE->FreeString (hstrFont); // create the font color HLTCOLOR hFontColor = LTNULL; if (bSelected) { hFontColor = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, LTFALSE); } else { hFontColor = pClientDE->SetupColor1 (1.0f, 0.4196f, 0.0f, LTFALSE); } // now call the actual function return CreateSurfaceFromString (pClientDE, &fontdef, str, hFontColor, LTNULL, LTTRUE); } // Determine the size of the surface needed int nLength = strlen (str); int nWidth = 0; for (int i = 0; i < nLength; i++) { nWidth += pFont->GetCharWidth (str[i]); } int nHeight = pFont->GetFontHeight(); // create the surface HSURFACE hSurf = pClientDE->CreateSurface (nWidth, nHeight); if (!hSurf) return LTNULL; // go through string and copy characters from font to new surface LTRect rcSrc; rcSrc.top = 0; rcSrc.bottom = nHeight; int nDstPos = 0; for (int i = 0; i < nLength; i++) { rcSrc.left = pFont->GetCharPos (str[i]); rcSrc.right = rcSrc.left + pFont->GetCharWidth (str[i]); pClientDE->DrawSurfaceToSurface (hSurf, pFont->GetFontSurface(), &rcSrc, nDstPos, 0); nDstPos += rcSrc.right - rcSrc.left; } return hSurf; }
HSURFACE CTextHelper::CreateWrappedStringSurface (ILTClient* pClientDE, int nWidth, CBitmapFont* pFont, char* str, int nAlignment, LTBOOL bCrop) { if (!str || !pClientDE) return LTNULL; // If the font is not initialized, call a different function using the system font... if (!pFont->IsValid()) { // hack to help localization - we need to know if this is a "selected" font or a "normal" font // this assumes font names that are selected end in an "s" identifier and the extension ".pcx"... LTBOOL bSelected = (pFont->GetImageName()[strlen (pFont->GetImageName()) - 5] == 's'); // determine the font height LTFLOAT nFontHeight = 0.0f; if (strcmp (pFont->GetClassName(), "CFont08") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT08, 8.0f); } else if (strcmp (pFont->GetClassName(), "CFont12") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT12, 12.0f); } else if (strcmp (pFont->GetClassName(), "CFont18") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT18, 18.0f); } else if (strcmp (pFont->GetClassName(), "CFont28") == 0) { nFontHeight = TextHelperGetLTFLOATValFromStringID(pClientDE, IDS_HEIGHTCFONT28, 28.0f); } // determine the preferred font width LTFLOAT nRatio = 0.5f; HCONSOLEVAR hVar = pClientDE->GetConsoleVar ("FontWidthHeightRatio"); if (hVar) { nRatio = pClientDE->GetVarValueFloat (hVar); } LTFLOAT nFontWidth = nFontHeight * nRatio; // create the font definition HSTRING hstrFont = pClientDE->FormatString (IDS_REPLACEMENTFONT); FONT fontdef (const_cast<char *>(pClientDE->GetStringData(hstrFont)), (int)nFontWidth, (int)nFontHeight); pClientDE->FreeString (hstrFont); // create the font color HLTCOLOR hFontColor = LTNULL; if (bSelected) { hFontColor = pClientDE->SetupColor1 (1.0f, 1.0f, 1.0f, LTFALSE); } else { hFontColor = pClientDE->SetupColor1 (1.0f, 0.4196f, 0.0f, LTFALSE); } // now call the actual function return CreateWrappedStringSurface (pClientDE, nWidth, &fontdef, str, hFontColor, LTNULL, nAlignment, LTTRUE); } CDynArray<uint32> surfaces (1, 2); // cannot create a dynarray of HSURFACES - compiler error C2926 uint32 nSurfaces = 0; char* ptr = str; char* ptrStart = ptr; char* ptrEnd = LTNULL; do { ptrEnd = ptr + strlen (ptr); LTBOOL bShortened = LTFALSE; while (ptrEnd > ptrStart) { int nChars = ptrEnd - ptrStart; int nTestWidth = 0; for (int i = 0; i < nChars; i++) { nTestWidth += pFont->GetCharWidth (ptrStart[i]); } if (nTestWidth <= nWidth) { bShortened = LTTRUE; break; } else { // find the previous space back from ptrEnd ptrEnd--; while (ptrEnd > ptrStart && *ptrEnd != ' ') ptrEnd--; } } // see if we were successful in coming up with a shortened version if (!bShortened) { // couldn't shorten the remaining string - just create a surface // from it and add it to the array surfaces[nSurfaces] = (uint32) CreateSurfaceFromString (pClientDE, pFont, ptrStart); } else { // we shortened it - create a surface and add it to the array char temp = *ptrEnd; *ptrEnd = '\0'; surfaces[nSurfaces] = (uint32) CreateSurfaceFromString (pClientDE, pFont, ptrStart); *ptrEnd = temp; } // see if we could create the surface if (!surfaces[nSurfaces]) { for (uint32 i = 0; i < nSurfaces; i++) { pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } return LTNULL; } nSurfaces++; if (!bShortened) { break; } else { ptrStart = ptrEnd + 1; } } while (*ptrEnd != '\0'); // ok, now we should have an array of surfaces that we can combine into one large one... if (!nSurfaces) return LTNULL; // get the final surface height and potential (shortened) width uint32 nTotalHeight = 0; uint32 nCroppedWidth = 0; for (uint32 i = 0; i < nSurfaces; i++) { uint32 nSurfWidth = 0; uint32 nSurfHeight = 0; pClientDE->GetSurfaceDims ((HSURFACE)surfaces[i], &nSurfWidth, &nSurfHeight); nTotalHeight += nSurfHeight; if (nSurfWidth > nCroppedWidth) nCroppedWidth = nSurfWidth; } // create the final surface uint32 nFinalWidth = bCrop ? nCroppedWidth : nWidth; HSURFACE hFinalSurface = pClientDE->CreateSurface (nFinalWidth, nTotalHeight); if (!hFinalSurface) { for (uint32 i = 0; i < nSurfaces; i++) { pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } return LTNULL; } pClientDE->FillRect ((HSURFACE)hFinalSurface, LTNULL, LTNULL); // draw the string surfaces onto final one int y = 0; for (int i = 0; i < nSurfaces; i++) { uint32 nSurfWidth = 0; uint32 nSurfHeight = 0; pClientDE->GetSurfaceDims ((HSURFACE)surfaces[i], &nSurfWidth, &nSurfHeight); int x = 0; switch (nAlignment) { case TH_ALIGN_CENTER: x = ((int)nFinalWidth - (int)nSurfWidth) / 2; break; case TH_ALIGN_RIGHT: x = (int)nFinalWidth - (int)nSurfWidth; break; } pClientDE->DrawSurfaceToSurface (hFinalSurface, (HSURFACE)surfaces[i], LTNULL, x, y); y += nSurfHeight; // delete this surface since we don't need it anymore pClientDE->DeleteSurface ((HSURFACE)surfaces[i]); } return hFinalSurface; }