| 
									
										
										
										
											2017-07-13 11:26:03 +03:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2023-02-01 16:42:03 +02:00
										 |  |  |  * CBitmapFont.cpp, part of VCMI engine | 
					
						
							| 
									
										
										
										
											2017-07-13 11:26:03 +03:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Authors: listed in file AUTHORS in main folder | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * License: GNU General Public License v2.0 or later | 
					
						
							|  |  |  |  * Full text of license available in license.txt file, in main folder | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | #include "StdInc.h"
 | 
					
						
							| 
									
										
										
										
											2023-02-01 20:42:06 +02:00
										 |  |  | #include "CBitmapFont.h"
 | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 20:06:08 +02:00
										 |  |  | #include "SDL_Extensions.h"
 | 
					
						
							| 
									
										
										
										
											2023-02-01 20:42:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | #include "../../lib/vcmi_endian.h"
 | 
					
						
							| 
									
										
										
										
											2013-07-28 14:49:50 +00:00
										 |  |  | #include "../../lib/filesystem/Filesystem.h"
 | 
					
						
							| 
									
										
										
										
											2023-02-12 23:00:56 +02:00
										 |  |  | #include "../../lib/TextOperations.h"
 | 
					
						
							| 
									
										
										
										
											2023-02-01 20:42:06 +02:00
										 |  |  | #include "../../lib/Rect.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <SDL_surface.h>
 | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-25 21:45:14 +00:00
										 |  |  | std::array<CBitmapFont::BitmapChar, CBitmapFont::totalChars> CBitmapFont::loadChars() const | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-10-25 21:45:14 +00:00
										 |  |  | 	std::array<BitmapChar, totalChars> ret; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	size_t offset = 32; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 13:05:48 +00:00
										 |  |  | 	for (auto & elem : ret) | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2013-06-29 13:05:48 +00:00
										 |  |  | 		elem.leftOffset =  read_le_u32(data.first.get() + offset); offset+=4; | 
					
						
							|  |  |  | 		elem.width =       read_le_u32(data.first.get() + offset); offset+=4; | 
					
						
							|  |  |  | 		elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-29 13:05:48 +00:00
										 |  |  | 	for (auto & elem : ret) | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		int pixelOffset =  read_le_u32(data.first.get() + offset); offset+=4; | 
					
						
							| 
									
										
										
										
											2013-06-29 13:05:48 +00:00
										 |  |  | 		elem.pixels = data.first.get() + 4128 + pixelOffset; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		assert(pixelOffset + 4128 < data.second); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ret; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CBitmapFont::CBitmapFont(const std::string & filename): | 
					
						
							| 
									
										
										
										
											2020-10-05 16:27:04 -07:00
										 |  |  | 	data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()), | 
					
						
							|  |  |  | 	chars(loadChars()), | 
					
						
							|  |  |  | 	height(data.first.get()[5]) | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | size_t CBitmapFont::getLineHeight() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return height; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-08 16:49:23 +00:00
										 |  |  | size_t CBitmapFont::getGlyphWidth(const char * data) const | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2023-02-12 23:52:35 +02:00
										 |  |  | 	std::string localChar = TextOperations::fromUnicode(std::string(data, TextOperations::getUnicodeCharacterSize(data[0]))); | 
					
						
							| 
									
										
										
										
											2013-10-25 21:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (localChar.size() == 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		const BitmapChar & ch = chars[ui8(localChar[0])]; | 
					
						
							|  |  |  | 		return ch.leftOffset + ch.width + ch.rightOffset; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-25 21:45:14 +00:00
										 |  |  | void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	Rect clipRect; | 
					
						
							| 
									
										
										
										
											2023-01-17 22:01:35 +02:00
										 |  |  | 	CSDL_Ext::getClipRect(surface, clipRect); | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	posX += character.leftOffset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-17 22:01:35 +02:00
										 |  |  | 	CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0); | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-30 19:55:32 +02:00
										 |  |  | 	uint8_t bpp = surface->format->BytesPerPixel; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// start of line, may differ from 0 due to end of surface or clipped surface
 | 
					
						
							|  |  |  | 	int lineBegin = std::max<int>(0, clipRect.y - posY); | 
					
						
							|  |  |  | 	int lineEnd   = std::min<int>(height, clipRect.y + clipRect.h - posY - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// start end end of each row, may differ from 0
 | 
					
						
							|  |  |  | 	int rowBegin = std::max<int>(0, clipRect.x - posX); | 
					
						
							|  |  |  | 	int rowEnd   = std::min<int>(character.width, clipRect.x + clipRect.w - posX - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//for each line in symbol
 | 
					
						
							|  |  |  | 	for(int dy = lineBegin; dy <lineEnd; dy++) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-01-30 19:55:32 +02:00
										 |  |  | 		uint8_t *dstLine = (uint8_t*)surface->pixels; | 
					
						
							|  |  |  | 		uint8_t *srcLine = character.pixels; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// shift source\destination pixels to current position
 | 
					
						
							|  |  |  | 		dstLine += (posY+dy) * surface->pitch + posX * bpp; | 
					
						
							|  |  |  | 		srcLine += dy * character.width; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		//for each column in line
 | 
					
						
							|  |  |  | 		for(int dx = rowBegin; dx < rowEnd; dx++) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2023-01-30 19:55:32 +02:00
										 |  |  | 			uint8_t* dstPixel = dstLine + dx*bpp; | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 			switch(srcLine[dx]) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 			case 1: //black "shadow"
 | 
					
						
							| 
									
										
										
										
											2014-08-05 18:17:57 +03:00
										 |  |  | 				colorPutter(dstPixel, 0, 0, 0); | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			case 255: //text colour
 | 
					
						
							|  |  |  | 				colorPutter(dstPixel, color.r, color.g, color.b); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			default : | 
					
						
							|  |  |  | 				break; //transparency
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	posX += character.width; | 
					
						
							|  |  |  | 	posX += character.rightOffset; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (data.empty()) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert(surface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int posX = pos.x; | 
					
						
							|  |  |  | 	int posY = pos.y; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-20 22:49:34 +00:00
										 |  |  | 	// Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles)
 | 
					
						
							|  |  |  | 	//assert(data[0] != '{');
 | 
					
						
							|  |  |  | 	//assert(data[data.size()-1] != '}');
 | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	SDL_LockSurface(surface); | 
					
						
							| 
									
										
										
										
											2013-10-25 21:45:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-12 23:52:35 +02:00
										 |  |  | 	for(size_t i=0; i<data.size(); i += TextOperations::getUnicodeCharacterSize(data[i])) | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2023-02-12 23:52:35 +02:00
										 |  |  | 		std::string localChar = TextOperations::fromUnicode(data.substr(i, TextOperations::getUnicodeCharacterSize(data[i]))); | 
					
						
							| 
									
										
										
										
											2013-10-25 21:45:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (localChar.size() == 1) | 
					
						
							|  |  |  | 			renderCharacter(surface, chars[ui8(localChar[0])], color, posX, posY); | 
					
						
							| 
									
										
										
										
											2012-12-19 17:24:53 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	SDL_UnlockSurface(surface); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 |