CBSurface* CBSurfaceStorage::AddSurface(char * Filename, bool default_ck, BYTE ck_red, BYTE ck_green, BYTE ck_blue, int LifeTime, bool KeepLoaded, bool KeepSurfaceCached)
{
	for(int i=0; i<m_Surfaces.GetSize(); i++)
	{
		if(CBPlatform::stricmp(m_Surfaces[i]->m_Filename, Filename)==0)
		{
			m_Surfaces[i]->m_ReferenceCount++;
			return m_Surfaces[i];
		}
	}

	CBFile* File = Game->m_FileManager->OpenFile(Filename);
	if(!File)
	{
		if(Filename) Game->LOG(0, "Missing image: '%s'", Filename);
		if(Game->m_DEBUG_DebugMode)
			return AddSurface("invalid_debug.bmp", default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded);
		else
			return AddSurface("invalid.bmp", default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded);
	}
	else Game->m_FileManager->CloseFile(File);


	CBSurface* surface;
	surface = new CBSurfaceSDL(Game);


	if(!surface) return NULL;

	if(FAILED(surface->Create(Filename, default_ck, ck_red, ck_green, ck_blue, LifeTime, KeepLoaded,KeepSurfaceCached)))
	{
		delete surface;
		return NULL;
	}
	else
	{
		surface->m_ReferenceCount = 1;
		m_Surfaces.Add(surface);
		return surface;
	}
}
Esempio n. 2
0
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;
		}
	}
}