git repos / blockattack-game

blame: source/code/sago/SagoTextField.cpp

normal view · raw

55ea55dd sago007 2018-03-24 16:07 1
/*
55ea55dd sago007 2018-03-24 16:07 2
Copyright (c) 2018 Poul Sander
55ea55dd sago007 2018-03-24 16:07 3
55ea55dd sago007 2018-03-24 16:07 4
Permission is hereby granted, free of charge, to any person
55ea55dd sago007 2018-03-24 16:07 5
obtaining a copy of this software and associated documentation files
55ea55dd sago007 2018-03-24 16:07 6
(the "Software"), to deal in the Software without restriction,
55ea55dd sago007 2018-03-24 16:07 7
including without limitation the rights to use, copy, modify, merge,
55ea55dd sago007 2018-03-24 16:07 8
publish, distribute, sublicense, and/or sell copies of the Software,
55ea55dd sago007 2018-03-24 16:07 9
and to permit persons to whom the Software is furnished to do so,
55ea55dd sago007 2018-03-24 16:07 10
subject to the following conditions:
55ea55dd sago007 2018-03-24 16:07 11
55ea55dd sago007 2018-03-24 16:07 12
The above copyright notice and this permission notice shall be
55ea55dd sago007 2018-03-24 16:07 13
included in all copies or substantial portions of the Software.
55ea55dd sago007 2018-03-24 16:07 14
55ea55dd sago007 2018-03-24 16:07 15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
55ea55dd sago007 2018-03-24 16:07 16
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
55ea55dd sago007 2018-03-24 16:07 17
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
55ea55dd sago007 2018-03-24 16:07 18
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
55ea55dd sago007 2018-03-24 16:07 19
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
55ea55dd sago007 2018-03-24 16:07 20
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
55ea55dd sago007 2018-03-24 16:07 21
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
55ea55dd sago007 2018-03-24 16:07 22
SOFTWARE.
55ea55dd sago007 2018-03-24 16:07 23
*/
55ea55dd sago007 2018-03-24 16:07 24
55ea55dd sago007 2018-03-24 16:07 25
#include "SagoTextField.hpp"
55ea55dd sago007 2018-03-24 16:07 26
#include <iostream>
55ea55dd sago007 2018-03-24 16:07 27
#include <SDL_ttf.h>
55ea55dd sago007 2018-03-24 16:07 28
55ea55dd sago007 2018-03-24 16:07 29
namespace sago {
55ea55dd sago007 2018-03-24 16:07 30
55ea55dd sago007 2018-03-24 16:07 31
	class OutlineHandler {
55ea55dd sago007 2018-03-24 16:07 32
		TTF_Font* font;
55ea55dd sago007 2018-03-24 16:07 33
		int originalOutline = 0;
55ea55dd sago007 2018-03-24 16:07 34
		int targetOutline;
55ea55dd sago007 2018-03-24 16:07 35
		bool doChange = false;
55ea55dd sago007 2018-03-24 16:07 36
	public:
55ea55dd sago007 2018-03-24 16:07 37
		OutlineHandler(TTF_Font* font, int outline) : font{font}, targetOutline{outline} {
55ea55dd sago007 2018-03-24 16:07 38
			originalOutline = TTF_GetFontOutline(font);
55ea55dd sago007 2018-03-24 16:07 39
			if (originalOutline == targetOutline) {
55ea55dd sago007 2018-03-24 16:07 40
				return;
55ea55dd sago007 2018-03-24 16:07 41
			}
55ea55dd sago007 2018-03-24 16:07 42
			doChange = true;
55ea55dd sago007 2018-03-24 16:07 43
			TTF_SetFontOutline(font, targetOutline);
55ea55dd sago007 2018-03-24 16:07 44
		};
55ea55dd sago007 2018-03-24 16:07 45
		
55ea55dd sago007 2018-03-24 16:07 46
		void reset() {
55ea55dd sago007 2018-03-24 16:07 47
			if (doChange) {
55ea55dd sago007 2018-03-24 16:07 48
				TTF_SetFontOutline(font,originalOutline);
55ea55dd sago007 2018-03-24 16:07 49
				doChange = false;
55ea55dd sago007 2018-03-24 16:07 50
			}
55ea55dd sago007 2018-03-24 16:07 51
		}
55ea55dd sago007 2018-03-24 16:07 52
		
55ea55dd sago007 2018-03-24 16:07 53
		~OutlineHandler() {
55ea55dd sago007 2018-03-24 16:07 54
			reset();
55ea55dd sago007 2018-03-24 16:07 55
		}
55ea55dd sago007 2018-03-24 16:07 56
	private:
55ea55dd sago007 2018-03-24 16:07 57
		OutlineHandler(const OutlineHandler& orig) = delete;
55ea55dd sago007 2018-03-24 16:07 58
		OutlineHandler& operator=(const OutlineHandler& base) = delete;
55ea55dd sago007 2018-03-24 16:07 59
	};
55ea55dd sago007 2018-03-24 16:07 60
	
55ea55dd sago007 2018-03-24 16:07 61
struct SagoTextField::SagoTextFieldData {
1a09fcd5 sago007 2018-03-25 13:32 62
	const sago::SagoDataHolder* tex = nullptr;
55ea55dd sago007 2018-03-24 16:07 63
	SDL_Surface* textSurface = nullptr;
55ea55dd sago007 2018-03-24 16:07 64
	SDL_Texture* texture = nullptr;
55ea55dd sago007 2018-03-24 16:07 65
	SDL_Surface* outlineTextSurface = nullptr;
55ea55dd sago007 2018-03-24 16:07 66
	SDL_Texture* outlineTexture = nullptr;
55ea55dd sago007 2018-03-24 16:07 67
	std::string fontName = "freeserif";
55ea55dd sago007 2018-03-24 16:07 68
	SDL_Color color = { 255, 255, 255, 0 };
55ea55dd sago007 2018-03-24 16:07 69
	SDL_Color outlineColor = { 255, 255, 0, 0 };
55ea55dd sago007 2018-03-24 16:07 70
	int fontSize = 16;
55ea55dd sago007 2018-03-24 16:07 71
	int outline = 0;
55ea55dd sago007 2018-03-24 16:07 72
	std::string text = "";
55ea55dd sago007 2018-03-24 16:07 73
	std::string renderedText = "";
55ea55dd sago007 2018-03-24 16:07 74
	Uint64 renderedVersion = 0;
55ea55dd sago007 2018-03-24 16:07 75
};
55ea55dd sago007 2018-03-24 16:07 76
	
55ea55dd sago007 2018-03-24 16:07 77
SagoTextField::SagoTextField() {
55ea55dd sago007 2018-03-24 16:07 78
	data = new SagoTextFieldData();
55ea55dd sago007 2018-03-24 16:07 79
}
55ea55dd sago007 2018-03-24 16:07 80
55ea55dd sago007 2018-03-24 16:07 81
SagoTextField::SagoTextField(SagoTextField&& o) noexcept {
55ea55dd sago007 2018-03-24 16:07 82
	data = o.data;
55ea55dd sago007 2018-03-24 16:07 83
	o.data = nullptr;
55ea55dd sago007 2018-03-24 16:07 84
}
55ea55dd sago007 2018-03-24 16:07 85
eb0258c8 sago007 2018-04-02 13:23 86
SagoTextField& SagoTextField::CopyFrom(const SagoTextField& base) {
ff33341c sago007 2018-03-26 16:03 87
	ClearCache();
906183f8 sago007 2018-03-26 13:14 88
	try {
906183f8 sago007 2018-03-26 13:14 89
		*data = *(base.data);
906183f8 sago007 2018-03-26 13:14 90
		//Copy all data but do not reuse the cache as it would result in a double free
906183f8 sago007 2018-03-26 13:14 91
		data->outlineTextSurface = nullptr;
906183f8 sago007 2018-03-26 13:14 92
		data->outlineTexture = nullptr;
906183f8 sago007 2018-03-26 13:14 93
		data->textSurface = nullptr;
906183f8 sago007 2018-03-26 13:14 94
		data->texture = nullptr;
906183f8 sago007 2018-03-26 13:14 95
		return *this;
906183f8 sago007 2018-03-26 13:14 96
	} catch (...) {
906183f8 sago007 2018-03-26 13:14 97
		delete data;
906183f8 sago007 2018-03-26 13:14 98
		throw;
906183f8 sago007 2018-03-26 13:14 99
	}
d91e7363 sago007 2018-03-26 13:09 100
}
d91e7363 sago007 2018-03-26 13:09 101
55ea55dd sago007 2018-03-24 16:07 102
SagoTextField::~SagoTextField() {
55ea55dd sago007 2018-03-24 16:07 103
	if(!data) {
55ea55dd sago007 2018-03-24 16:07 104
		return;
55ea55dd sago007 2018-03-24 16:07 105
	}
55ea55dd sago007 2018-03-24 16:07 106
	ClearCache();
55ea55dd sago007 2018-03-24 16:07 107
	delete data;
55ea55dd sago007 2018-03-24 16:07 108
}
55ea55dd sago007 2018-03-24 16:07 109
1a09fcd5 sago007 2018-03-25 13:32 110
void SagoTextField::SetHolder(const SagoDataHolder* holder) {
55ea55dd sago007 2018-03-24 16:07 111
	data->tex = holder;
55ea55dd sago007 2018-03-24 16:07 112
}
55ea55dd sago007 2018-03-24 16:07 113
55ea55dd sago007 2018-03-24 16:07 114
void SagoTextField::SetText(const char* text) {
0b8fb137 sago007 2018-03-31 19:53 115
	data->text = text;
0b8fb137 sago007 2018-03-31 19:53 116
}
0b8fb137 sago007 2018-03-31 19:53 117
0b8fb137 sago007 2018-03-31 19:53 118
void SagoTextField::SetText(const std::string& text) {
55ea55dd sago007 2018-03-24 16:07 119
	data->text = text;
55ea55dd sago007 2018-03-24 16:07 120
}
55ea55dd sago007 2018-03-24 16:07 121
55ea55dd sago007 2018-03-24 16:07 122
void SagoTextField::SetColor(const SDL_Color& color) {
55ea55dd sago007 2018-03-24 16:07 123
	data->color = color;
55ea55dd sago007 2018-03-24 16:07 124
}
55ea55dd sago007 2018-03-24 16:07 125
55ea55dd sago007 2018-03-24 16:07 126
void SagoTextField::SetFont(const char* fontName) {
55ea55dd sago007 2018-03-24 16:07 127
	data->fontName = fontName;
55ea55dd sago007 2018-03-24 16:07 128
}
55ea55dd sago007 2018-03-24 16:07 129
55ea55dd sago007 2018-03-24 16:07 130
void SagoTextField::SetFontSize(int fontSize) {
55ea55dd sago007 2018-03-24 16:07 131
	data->fontSize = fontSize;
55ea55dd sago007 2018-03-24 16:07 132
}
55ea55dd sago007 2018-03-24 16:07 133
55ea55dd sago007 2018-03-24 16:07 134
void SagoTextField::SetOutline(int outlineSize, const SDL_Color& color) {
55ea55dd sago007 2018-03-24 16:07 135
	data->outline = outlineSize;
55ea55dd sago007 2018-03-24 16:07 136
	data->outlineColor = color;
55ea55dd sago007 2018-03-24 16:07 137
}
55ea55dd sago007 2018-03-24 16:07 138
55ea55dd sago007 2018-03-24 16:07 139
const std::string& SagoTextField::GetText() const {
55ea55dd sago007 2018-03-24 16:07 140
	return data->text;
55ea55dd sago007 2018-03-24 16:07 141
}
55ea55dd sago007 2018-03-24 16:07 142
55ea55dd sago007 2018-03-24 16:07 143
void SagoTextField::ClearCache() {
55ea55dd sago007 2018-03-24 16:07 144
	if (data->texture) {
55ea55dd sago007 2018-03-24 16:07 145
		SDL_DestroyTexture(data->texture);
55ea55dd sago007 2018-03-24 16:07 146
		data->texture = nullptr;
55ea55dd sago007 2018-03-24 16:07 147
	}
55ea55dd sago007 2018-03-24 16:07 148
	if (data->textSurface) {
55ea55dd sago007 2018-03-24 16:07 149
		SDL_FreeSurface(data->textSurface);
55ea55dd sago007 2018-03-24 16:07 150
		data->textSurface = nullptr;
55ea55dd sago007 2018-03-24 16:07 151
	}
55ea55dd sago007 2018-03-24 16:07 152
	if (data->outlineTexture) {
55ea55dd sago007 2018-03-24 16:07 153
		SDL_DestroyTexture(data->outlineTexture);
55ea55dd sago007 2018-03-24 16:07 154
		data->outlineTexture = nullptr;
55ea55dd sago007 2018-03-24 16:07 155
	}
55ea55dd sago007 2018-03-24 16:07 156
	if (data->outlineTextSurface) {
55ea55dd sago007 2018-03-24 16:07 157
		SDL_FreeSurface(data->outlineTextSurface);
55ea55dd sago007 2018-03-24 16:07 158
		data->outlineTextSurface = nullptr;
55ea55dd sago007 2018-03-24 16:07 159
	}
55ea55dd sago007 2018-03-24 16:07 160
}
55ea55dd sago007 2018-03-24 16:07 161
55ea55dd sago007 2018-03-24 16:07 162
void SagoTextField::UpdateCache(SDL_Renderer* target) {
343fbe43 sago007 2018-03-27 19:53 163
	if (!data->tex) {
343fbe43 sago007 2018-03-27 19:53 164
		std::cerr << "FATAL: DataHolder not set!\n";
343fbe43 sago007 2018-03-27 19:53 165
		abort();
343fbe43 sago007 2018-03-27 19:53 166
	}
55ea55dd sago007 2018-03-24 16:07 167
	ClearCache();
55ea55dd sago007 2018-03-24 16:07 168
	TTF_Font *font = data->tex->getFontPtr(data->fontName, data->fontSize);
55ea55dd sago007 2018-03-24 16:07 169
	data->textSurface = TTF_RenderUTF8_Blended (font, data->text.c_str(), data->color);
55ea55dd sago007 2018-03-24 16:07 170
	data->texture = SDL_CreateTextureFromSurface(target, data->textSurface);
55ea55dd sago007 2018-03-24 16:07 171
	if (data->outline > 0) {
55ea55dd sago007 2018-03-24 16:07 172
		OutlineHandler oh(font, data->outline);
55ea55dd sago007 2018-03-24 16:07 173
		data->outlineTextSurface = TTF_RenderUTF8_Blended (font, data->text.c_str(), data->outlineColor);
55ea55dd sago007 2018-03-24 16:07 174
		data->outlineTexture = SDL_CreateTextureFromSurface(target, data->outlineTextSurface);
55ea55dd sago007 2018-03-24 16:07 175
		oh.reset();
55ea55dd sago007 2018-03-24 16:07 176
	}
55ea55dd sago007 2018-03-24 16:07 177
	data->renderedText = data->text;
55ea55dd sago007 2018-03-24 16:07 178
	data->renderedVersion = data->tex->getVersion();
55ea55dd sago007 2018-03-24 16:07 179
}
55ea55dd sago007 2018-03-24 16:07 180
bd788178 sago007 2018-03-31 16:03 181
void SagoTextField::GetRenderedSize(const char* text, int* w, int* h) {
bd788178 sago007 2018-03-31 16:03 182
	TTF_Font *font = data->tex->getFontPtr(data->fontName, data->fontSize);
bd788178 sago007 2018-03-31 16:03 183
	int ret = TTF_SizeUTF8(font, text, w, h);
bd788178 sago007 2018-03-31 16:03 184
	if (ret) {
bd788178 sago007 2018-03-31 16:03 185
		if (w) {
1ee3769b sago007 2018-03-31 16:34 186
			*w = 0;
bd788178 sago007 2018-03-31 16:03 187
		}
bd788178 sago007 2018-03-31 16:03 188
		if (h) {
1ee3769b sago007 2018-03-31 16:34 189
			*h = 0;
bd788178 sago007 2018-03-31 16:03 190
		}
bd788178 sago007 2018-03-31 16:03 191
		std::cerr << "GetRenderedSize failed to find size of " << text << ". Error code: " << ret << "\n";
bd788178 sago007 2018-03-31 16:03 192
	}
bd788178 sago007 2018-03-31 16:03 193
}
bd788178 sago007 2018-03-31 16:03 194
d91e7363 sago007 2018-03-26 13:09 195
void SagoTextField::Draw(SDL_Renderer* target, int x, int y, Alignment alignment, VerticalAlignment verticalAlignment) {
55ea55dd sago007 2018-03-24 16:07 196
	if (data->text.empty()) {
55ea55dd sago007 2018-03-24 16:07 197
		return;
55ea55dd sago007 2018-03-24 16:07 198
	}
55ea55dd sago007 2018-03-24 16:07 199
	if (data->text != data->renderedText || data->renderedVersion != data->tex->getVersion()) {
55ea55dd sago007 2018-03-24 16:07 200
		UpdateCache(target);
55ea55dd sago007 2018-03-24 16:07 201
	}
55ea55dd sago007 2018-03-24 16:07 202
	if (!data->texture) {
55ea55dd sago007 2018-03-24 16:07 203
		return;
55ea55dd sago007 2018-03-24 16:07 204
	}
55ea55dd sago007 2018-03-24 16:07 205
	int texW = 0;
55ea55dd sago007 2018-03-24 16:07 206
	int texH = 0;
55ea55dd sago007 2018-03-24 16:07 207
	SDL_QueryTexture(data->texture, NULL, NULL, &texW, &texH);
d91e7363 sago007 2018-03-26 13:09 208
	if (alignment == Alignment::center) {
d91e7363 sago007 2018-03-26 13:09 209
		x -= texW/2;
d91e7363 sago007 2018-03-26 13:09 210
	}
fc338170 sago007 2018-03-28 14:31 211
	if (alignment == Alignment::right) {
f9f05e62 sago007 2018-10-28 12:36 212
		x -= texW;
fc338170 sago007 2018-03-28 14:31 213
	}
d91e7363 sago007 2018-03-26 13:09 214
	if (verticalAlignment == VerticalAlignment::center) {
d91e7363 sago007 2018-03-26 13:09 215
		y -= texH/2;
d91e7363 sago007 2018-03-26 13:09 216
	}
492b2753 sago007 2018-04-07 14:37 217
	if (verticalAlignment == VerticalAlignment::bottom) {
492b2753 sago007 2018-04-07 14:37 218
		y -= texH;
492b2753 sago007 2018-04-07 14:37 219
	}
55ea55dd sago007 2018-03-24 16:07 220
	SDL_Rect dstrect = { x, y, texW, texH };
55ea55dd sago007 2018-03-24 16:07 221
	if (data->outlineTexture) {
55ea55dd sago007 2018-03-24 16:07 222
		int outlineTexW = 0;
55ea55dd sago007 2018-03-24 16:07 223
		int outlineTexH = 0;
55ea55dd sago007 2018-03-24 16:07 224
		SDL_QueryTexture(data->outlineTexture, NULL, NULL, &outlineTexW, &outlineTexH);
55ea55dd sago007 2018-03-24 16:07 225
		SDL_Rect dstrectOutline = { x-(data->outline), y-(data->outline), outlineTexW, outlineTexH };
55ea55dd sago007 2018-03-24 16:07 226
		SDL_RenderCopy(target, data->outlineTexture, NULL, &dstrectOutline);
55ea55dd sago007 2018-03-24 16:07 227
	}
55ea55dd sago007 2018-03-24 16:07 228
	SDL_RenderCopy(target, data->texture, NULL, &dstrect);
55ea55dd sago007 2018-03-24 16:07 229
}
55ea55dd sago007 2018-03-24 16:07 230
55ea55dd sago007 2018-03-24 16:07 231
}  //namespace sago