void CBFontTT::DrawText(byte *Text, int X, int Y, int Width, TTextAlign Align, int MaxHeight, int MaxLength) { if (Text == NULL || strcmp((char *)Text, "") == 0) return; WideString text; if (Game->m_TextEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text); else text = StringUtil::AnsiToWide((char *)Text); if (MaxLength >= 0 && text.length() > MaxLength) text = text.substr(0, MaxLength); CBRenderSDL *m_Renderer = (CBRenderSDL *)Game->m_Renderer; // find cached surface, if exists int MinPriority = INT_MAX; int MinIndex = -1; CBSurface *Surface = NULL; int textOffset = 0; for (int i = 0; i < NUM_CACHED_TEXTS; i++) { if (m_CachedTexts[i] == NULL) { MinPriority = 0; MinIndex = i; } else { if (m_CachedTexts[i]->m_Text == text && m_CachedTexts[i]->m_Align == Align && m_CachedTexts[i]->m_Width == Width && m_CachedTexts[i]->m_MaxHeight == MaxHeight && m_CachedTexts[i]->m_MaxLength == MaxLength) { Surface = m_CachedTexts[i]->m_Surface; textOffset = m_CachedTexts[i]->m_TextOffset; m_CachedTexts[i]->m_Priority++; m_CachedTexts[i]->m_Marked = true; break; } else { if (m_CachedTexts[i]->m_Priority < MinPriority) { MinPriority = m_CachedTexts[i]->m_Priority; MinIndex = i; } } } } // not found, create one if (!Surface) { Surface = RenderTextToTexture(text, Width, Align, MaxHeight, textOffset); if (Surface) { // write surface to cache if (m_CachedTexts[MinIndex] != NULL) delete m_CachedTexts[MinIndex]; m_CachedTexts[MinIndex] = new CBCachedTTFontText; m_CachedTexts[MinIndex]->m_Surface = Surface; m_CachedTexts[MinIndex]->m_Align = Align; m_CachedTexts[MinIndex]->m_Width = Width; m_CachedTexts[MinIndex]->m_MaxHeight = MaxHeight; m_CachedTexts[MinIndex]->m_MaxLength = MaxLength; m_CachedTexts[MinIndex]->m_Priority = 1; m_CachedTexts[MinIndex]->m_Text = text; m_CachedTexts[MinIndex]->m_TextOffset = textOffset; m_CachedTexts[MinIndex]->m_Marked = true; } } // and paint it if (Surface) { RECT rc; CBPlatform::SetRect(&rc, 0, 0, Surface->GetWidth(), Surface->GetHeight()); for (int i = 0; i < m_Layers.GetSize(); i++) { uint32 Color = m_Layers[i]->m_Color; uint32 OrigForceAlpha = m_Renderer->m_ForceAlphaColor; if (m_Renderer->m_ForceAlphaColor != 0) { Color = DRGBA(D3DCOLGetR(Color), D3DCOLGetG(Color), D3DCOLGetB(Color), D3DCOLGetA(m_Renderer->m_ForceAlphaColor)); m_Renderer->m_ForceAlphaColor = 0; } Surface->DisplayTransOffset(X, Y - textOffset, rc, Color, BLEND_NORMAL, false, false, m_Layers[i]->m_OffsetX, m_Layers[i]->m_OffsetY); m_Renderer->m_ForceAlphaColor = OrigForceAlpha; } } }
void CBFontTT::DrawTextD3D(BYTE* Text, int X, int Y, int Width, TTextAlign Align, int MaxHeight, int MaxLength) { CBRenderD3D* m_Renderer = (CBRenderD3D*)Game->m_Renderer; // find cached surface, if exists int MinPriority = INT_MAX; int MaxPriority = 0; int MinIndex = -1; CBSurface* Surface = NULL; for(int i=0; i<NUM_CACHED_TEXTS; i++) { if(m_CachedTexts[i]==NULL) { MinPriority = 0; MinIndex = i; } else { MaxPriority = max(MaxPriority, m_CachedTexts[i]->m_Priority); if(strcmp(m_CachedTexts[i]->m_Text, (char*)Text)==0 && m_CachedTexts[i]->m_Align==Align && m_CachedTexts[i]->m_Width==Width && m_CachedTexts[i]->m_MaxHeight==MaxHeight && m_CachedTexts[i]->m_MaxLength==MaxLength) { Surface = m_CachedTexts[i]->m_Surface; m_CachedTexts[i]->m_Priority++; break; } else { if(m_CachedTexts[i]->m_Priority < MinPriority) { MinPriority = m_CachedTexts[i]->m_Priority; MinIndex = i; } } } } // not found, create one if(!Surface) { if(FAILED(CreateWinFont())) return; HDC hDC = ::CreateCompatibleDC(NULL); ::SetMapMode(hDC, MM_TEXT); HFONT OldFont = (HFONT)::SelectObject(hDC, m_HFont); ::SetTextColor(hDC, RGB(255,255,255)); ::SetBkColor(hDC, 0x00000000); int TextX = 0; SetTextAlign(hDC, Align, Width, &TextX); BYTE* ConvertedText = CBTextUtils::ConvertToNative(Game->m_TextEncoding, Text, MaxLength); //ExtTextOut(hDC, 0, 0, ETO_OPAQUE, NULL, (char*)Text, strlen((char*)Text), NULL); int Height = FormatText(TextX, 0, ConvertedText, hDC, Width, MaxHeight); Height = max(Height, 1); DWORD* BitmapBits; BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = (int)Width; bmi.bmiHeader.biHeight = -(int)Height; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biBitCount = 32; HBITMAP hbmBitmap = ::CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (VOID**)&BitmapBits, NULL, 0); HBITMAP OldBitmap = (HBITMAP)::SelectObject(hDC, hbmBitmap); FormatText(TextX, 0, ConvertedText, hDC, Width, MaxHeight); CBImage* Image = new CBImage(Game); Image->CreateFromRaw(BitmapBits, Width, Height); Surface = Image->CreateSurface(); delete Image; ::SelectObject(hDC, OldBitmap); ::SelectObject(hDC, OldFont); ::DeleteObject(hbmBitmap); ::DeleteDC(hDC); DeleteWinFont(); delete [] ConvertedText; // write surface to cache if(m_CachedTexts[MinIndex]!=NULL) delete m_CachedTexts[MinIndex]; m_CachedTexts[MinIndex] = new CBCachedTTFontText; m_CachedTexts[MinIndex]->m_Surface = Surface; m_CachedTexts[MinIndex]->m_Align = Align; m_CachedTexts[MinIndex]->m_Width = Width; m_CachedTexts[MinIndex]->m_MaxHeight = MaxHeight; m_CachedTexts[MinIndex]->m_MaxLength = MaxLength; m_CachedTexts[MinIndex]->m_Priority = MaxPriority + 1; CBUtils::SetString(&m_CachedTexts[MinIndex]->m_Text, (char*)Text); } // and paint it if(Surface) { RECT rc; SetRect(&rc, 0, 0, Surface->GetWidth(), Surface->GetHeight()); for(int i=0; i<m_Layers.GetSize(); i++) { DWORD Color = m_Layers[i]->m_Color; DWORD OrigForceAlpha = m_Renderer->m_ForceAlphaColor; if(m_Renderer->m_ForceAlphaColor!=0) { Color = DRGBA(D3DCOLGetR(Color), D3DCOLGetG(Color), D3DCOLGetB(Color), D3DCOLGetA(m_Renderer->m_ForceAlphaColor)); m_Renderer->m_ForceAlphaColor = 0; } Surface->DisplayTrans(X+m_Layers[i]->m_OffsetX, Y+m_Layers[i]->m_OffsetY, rc, Color); m_Renderer->m_ForceAlphaColor = OrigForceAlpha; } } }