| 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 |
|
| d91e7363 |
sago007 |
2018-03-26 13:09 |
86 |
SagoTextField& SagoTextField::operator=(const SagoTextField& base) { |
| 906183f8 |
sago007 |
2018-03-26 13:14 |
87 |
data = new SagoTextFieldData(); |
| 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) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
115 |
data->text = text; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
116 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
117 |
|
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
118 |
void SagoTextField::SetColor(const SDL_Color& color) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
119 |
data->color = color; |
| 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::SetFont(const char* fontName) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
123 |
data->fontName = fontName; |
| 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::SetFontSize(int fontSize) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
127 |
data->fontSize = fontSize; |
| 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::SetOutline(int outlineSize, const SDL_Color& color) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
131 |
data->outline = outlineSize; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
132 |
data->outlineColor = color; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
133 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
134 |
|
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
135 |
const std::string& SagoTextField::GetText() const { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
136 |
return data->text; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
137 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
138 |
|
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
139 |
void SagoTextField::ClearCache() { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
140 |
if (!data->tex) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
141 |
std::cerr << "FATAL: DataHolder not set!\n"; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
142 |
abort(); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
143 |
} |
| 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) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
163 |
ClearCache(); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
164 |
TTF_Font *font = data->tex->getFontPtr(data->fontName, data->fontSize); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
165 |
data->textSurface = TTF_RenderUTF8_Blended (font, data->text.c_str(), data->color); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
166 |
data->texture = SDL_CreateTextureFromSurface(target, data->textSurface); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
167 |
int textWidth = 0; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
168 |
SDL_QueryTexture(data->texture, NULL, NULL, &textWidth, NULL); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
169 |
if (data->outline > 0) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
170 |
OutlineHandler oh(font, data->outline); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
171 |
data->outlineTextSurface = TTF_RenderUTF8_Blended (font, data->text.c_str(), data->outlineColor); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
172 |
data->outlineTexture = SDL_CreateTextureFromSurface(target, data->outlineTextSurface); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
173 |
oh.reset(); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
174 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
175 |
data->renderedText = data->text; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
176 |
data->renderedVersion = data->tex->getVersion(); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
177 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
178 |
|
| d91e7363 |
sago007 |
2018-03-26 13:09 |
179 |
void SagoTextField::Draw(SDL_Renderer* target, int x, int y, Alignment alignment, VerticalAlignment verticalAlignment) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
180 |
if (data->text.empty()) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
181 |
return; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
182 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
183 |
if (data->text != data->renderedText || data->renderedVersion != data->tex->getVersion()) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
184 |
UpdateCache(target); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
185 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
186 |
if (!data->texture) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
187 |
return; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
188 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
189 |
int texW = 0; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
190 |
int texH = 0; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
191 |
SDL_QueryTexture(data->texture, NULL, NULL, &texW, &texH); |
| d91e7363 |
sago007 |
2018-03-26 13:09 |
192 |
if (alignment == Alignment::center) { |
| d91e7363 |
sago007 |
2018-03-26 13:09 |
193 |
x -= texW/2; |
| d91e7363 |
sago007 |
2018-03-26 13:09 |
194 |
} |
| d91e7363 |
sago007 |
2018-03-26 13:09 |
195 |
if (verticalAlignment == VerticalAlignment::center) { |
| d91e7363 |
sago007 |
2018-03-26 13:09 |
196 |
y -= texH/2; |
| d91e7363 |
sago007 |
2018-03-26 13:09 |
197 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
198 |
SDL_Rect dstrect = { x, y, texW, texH }; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
199 |
if (data->outlineTexture) { |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
200 |
int outlineTexW = 0; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
201 |
int outlineTexH = 0; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
202 |
SDL_QueryTexture(data->outlineTexture, NULL, NULL, &outlineTexW, &outlineTexH); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
203 |
SDL_Rect dstrectOutline = { x-(data->outline), y-(data->outline), outlineTexW, outlineTexH }; |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
204 |
SDL_RenderCopy(target, data->outlineTexture, NULL, &dstrectOutline); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
205 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
206 |
SDL_RenderCopy(target, data->texture, NULL, &dstrect); |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
207 |
} |
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
208 |
|
| 55ea55dd |
sago007 |
2018-03-24 16:07 |
209 |
} //namespace sago |