1 
2 #ifndef __GWEN_OPENGL3_CORE_RENDERER_H
3 #define __GWEN_OPENGL3_CORE_RENDERER_H
4 
5 #include "Gwen/Gwen.h"
6 #include "Gwen/BaseRender.h"
7 #include "GLPrimitiveRenderer.h"
8 #include "../OpenGLWindow/OpenGLInclude.h"
9 
10 struct sth_stash;
11 #include "fontstash.h"
12 #include "Gwen/Texture.h"
13 
14 #include "TwFonts.h"
15 static float extraSpacing = 0.;  //6f;
16 #include <assert.h>
17 #include <math.h>
18 
19 template <class T>
MyClamp(T & a,const T & lb,const T & ub)20 inline void MyClamp(T& a, const T& lb, const T& ub)
21 {
22 	if (a < lb)
23 	{
24 		a = lb;
25 	}
26 	else if (ub < a)
27 	{
28 		a = ub;
29 	}
30 }
31 
BindFont(const CTexFont * _Font)32 static GLuint BindFont(const CTexFont* _Font)
33 {
34 	GLuint TexID = 0;
35 	glGenTextures(1, &TexID);
36 	glBindTexture(GL_TEXTURE_2D, TexID);
37 	glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
38 	glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE);
39 	glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
40 	glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
41 	glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
42 	glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
43 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, _Font->m_TexWidth, _Font->m_TexHeight, 0, GL_RED, GL_UNSIGNED_BYTE, _Font->m_TexBytes);
44 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
45 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
46 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
47 	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
48 	glBindTexture(GL_TEXTURE_2D, 0);
49 
50 	return TexID;
51 }
52 
53 struct MyTextureLoader
54 {
~MyTextureLoaderMyTextureLoader55 	virtual ~MyTextureLoader()
56 	{
57 	}
58 	virtual void LoadTexture(Gwen::Texture* pTexture) = 0;
59 	virtual void FreeTexture(Gwen::Texture* pTexture) = 0;
60 };
61 
62 class GwenOpenGL3CoreRenderer : public Gwen::Renderer::Base
63 {
64 	GLPrimitiveRenderer* m_primitiveRenderer;
65 	float m_currentColor[4];
66 	float m_yOffset;
67 	sth_stash* m_font;
68 	float m_screenWidth;
69 	float m_screenHeight;
70 	float m_fontScaling;
71 	float m_retinaScale;
72 	bool m_useTrueTypeFont;
73 	const CTexFont* m_currentFont;
74 
75 	GLuint m_fontTextureId;
76 	MyTextureLoader* m_textureLoader;
77 
78 public:
79 	GwenOpenGL3CoreRenderer(GLPrimitiveRenderer* primRender, sth_stash* font, float screenWidth, float screenHeight, float retinaScale, MyTextureLoader* loader = 0)
m_primitiveRenderer(primRender)80 		: m_primitiveRenderer(primRender),
81 		  m_font(font),
82 		  m_screenWidth(screenWidth),
83 		  m_screenHeight(screenHeight),
84 		  m_retinaScale(retinaScale),
85 		  m_useTrueTypeFont(false),
86 		  m_textureLoader(loader)
87 	{
88 		///only enable true type fonts on Macbook Retina, it looks gorgeous
89 		if (retinaScale == 2.0f)
90 		{
91 			m_useTrueTypeFont = true;
92 		}
93 		m_currentColor[0] = 1;
94 		m_currentColor[1] = 1;
95 		m_currentColor[2] = 1;
96 		m_currentColor[3] = 1;
97 
98 		m_fontScaling = 16.f * m_retinaScale;
99 
100 		TwGenerateDefaultFonts();
101 
102 		m_currentFont = g_DefaultNormalFont;
103 		//m_currentFont = g_DefaultNormalFontAA;
104 
105 		//m_currentFont = g_DefaultLargeFont;
106 		m_fontTextureId = BindFont(m_currentFont);
107 	}
108 
~GwenOpenGL3CoreRenderer()109 	virtual ~GwenOpenGL3CoreRenderer()
110 	{
111 		TwDeleteDefaultFonts();
112 	}
Resize(int width,int height)113 	virtual void Resize(int width, int height)
114 	{
115 		m_screenWidth = width;
116 		m_screenHeight = height;
117 	}
118 
Begin()119 	virtual void Begin()
120 	{
121 		m_yOffset = 0;
122 		glEnable(GL_BLEND);
123 		assert(glGetError() == GL_NO_ERROR);
124 
125 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
126 
127 		assert(glGetError() == GL_NO_ERROR);
128 
129 		assert(glGetError() == GL_NO_ERROR);
130 
131 		glDisable(GL_DEPTH_TEST);
132 		assert(glGetError() == GL_NO_ERROR);
133 		//glColor4ub(255,0,0,255);
134 
135 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
136 
137 		//	saveOpenGLState(width,height);//m_glutScreenWidth,m_glutScreenHeight);
138 
139 		assert(glGetError() == GL_NO_ERROR);
140 
141 		glDisable(GL_CULL_FACE);
142 
143 		glDisable(GL_DEPTH_TEST);
144 		assert(glGetError() == GL_NO_ERROR);
145 
146 		glEnable(GL_BLEND);
147 
148 		assert(glGetError() == GL_NO_ERROR);
149 	}
End()150 	virtual void End()
151 	{
152 		glDisable(GL_BLEND);
153 	}
154 
StartClip()155 	virtual void StartClip()
156 	{
157 		if (m_useTrueTypeFont)
158 			sth_flush_draw(m_font);
159 		Gwen::Rect rect = ClipRegion();
160 
161 		// OpenGL's coords are from the bottom left
162 		// so we need to translate them here.
163 		{
164 			GLint view[4];
165 			glGetIntegerv(GL_VIEWPORT, &view[0]);
166 			rect.y = view[3] / m_retinaScale - (rect.y + rect.h);
167 		}
168 
169 		glScissor(m_retinaScale * rect.x * Scale(), m_retinaScale * rect.y * Scale(), m_retinaScale * rect.w * Scale(), m_retinaScale * rect.h * Scale());
170 		glEnable(GL_SCISSOR_TEST);
171 		//glDisable( GL_SCISSOR_TEST );
172 	};
173 
EndClip()174 	virtual void EndClip()
175 	{
176 		if (m_useTrueTypeFont)
177 			sth_flush_draw(m_font);
178 		glDisable(GL_SCISSOR_TEST);
179 	};
180 
SetDrawColor(Gwen::Color color)181 	virtual void SetDrawColor(Gwen::Color color)
182 	{
183 		m_currentColor[0] = color.r / 256.f;
184 		m_currentColor[1] = color.g / 256.f;
185 		m_currentColor[2] = color.b / 256.f;
186 		m_currentColor[3] = color.a / 256.f;
187 	}
DrawFilledRect(Gwen::Rect rect)188 	virtual void DrawFilledRect(Gwen::Rect rect)
189 	{
190 		//		BT_PROFILE("GWEN_DrawFilledRect");
191 		Translate(rect);
192 
193 		m_primitiveRenderer->drawRect(rect.x, rect.y + m_yOffset,
194 									  rect.x + rect.w, rect.y + rect.h + m_yOffset, m_currentColor);
195 
196 		//		m_primitiveRenderer->drawTexturedRect2a(rect.x, rect.y+m_yOffset,
197 		//		rect.x+rect.w, rect.y+rect.h+m_yOffset, m_currentColor,0,0,1,1);
198 		//		m_yOffset+=rect.h+10;
199 	}
200 
RenderText(Gwen::Font * pFont,Gwen::Point rasterPos,const Gwen::UnicodeString & text)201 	void RenderText(Gwen::Font* pFont, Gwen::Point rasterPos, const Gwen::UnicodeString& text)
202 	{
203 		//		BT_PROFILE("GWEN_RenderText");
204 
205 		Gwen::String str = Gwen::Utility::UnicodeToString(text);
206 		const char* unicodeText = (const char*)str.c_str();
207 
208 		Gwen::Rect r;
209 		r.x = rasterPos.x;
210 		r.y = rasterPos.y;
211 		r.w = 0;
212 		r.h = 0;
213 
214 		//
215 		//printf("str = %s\n",unicodeText);
216 		//int xpos=0;
217 		//int ypos=0;
218 		float dx;
219 
220 		int measureOnly = 0;
221 
222 		if (m_useTrueTypeFont)
223 		{
224 			float yoffset = 0.f;
225 			if (m_retinaScale == 2.0f)
226 			{
227 				yoffset = -12;
228 			}
229 			Translate(r);
230 			sth_draw_text(m_font,
231 						  1, m_fontScaling,
232 						  r.x, r.y + yoffset,
233 						  unicodeText, &dx, m_screenWidth, m_screenHeight, measureOnly, m_retinaScale);
234 		}
235 		else
236 		{
237 			//float width = 0.f;
238 			int pos = 0;
239 			//float color[]={0.2f,0.2,0.2f,1.f};
240 
241 			glBindTexture(GL_TEXTURE_2D, m_fontTextureId);
242 			float width = r.x;
243 
244 			while (unicodeText[pos])
245 			{
246 				int c = unicodeText[pos];
247 				r.h = m_currentFont->m_CharHeight;
248 				r.w = m_currentFont->m_CharWidth[c] + extraSpacing;
249 				Gwen::Rect rect = r;
250 				Translate(rect);
251 
252 				m_primitiveRenderer->drawTexturedRect2(rect.x, rect.y + m_yOffset, rect.x + rect.w, rect.y + rect.h + m_yOffset, m_currentColor, m_currentFont->m_CharU0[c], m_currentFont->m_CharV0[c], m_currentFont->m_CharU1[c], m_currentFont->m_CharV1[c]);
253 
254 				width += r.w;
255 				r.x = width;
256 				pos++;
257 			}
258 			{
259 				m_primitiveRenderer->drawTexturedRect3D2Text(false);
260 			}
261 			glBindTexture(GL_TEXTURE_2D, 0);
262 		}
263 	}
MeasureText(Gwen::Font * pFont,const Gwen::UnicodeString & text)264 	Gwen::Point MeasureText(Gwen::Font* pFont, const Gwen::UnicodeString& text)
265 	{
266 		//		BT_PROFILE("GWEN_MeasureText");
267 		Gwen::String str = Gwen::Utility::UnicodeToString(text);
268 		const char* unicodeText = (const char*)str.c_str();
269 
270 		// printf("str = %s\n",unicodeText);
271 		int xpos = 0;
272 		int ypos = 0;
273 
274 		int measureOnly = 1;
275 		float dx = 0;
276 		if (m_useTrueTypeFont)
277 		{
278 			sth_draw_text(m_font,
279 						  1, m_fontScaling,
280 						  xpos, ypos,
281 						  unicodeText, &dx, m_screenWidth, m_screenHeight, measureOnly);
282 
283 			Gwen::Point pt;
284 
285 			if (m_retinaScale == 2.0f)
286 			{
287 				pt.x = dx * Scale() / 2.f;
288 				pt.y = m_fontScaling / 2 * Scale() + 1;
289 			}
290 			else
291 			{
292 				pt.x = dx * Scale();
293 				pt.y = m_fontScaling * Scale() + 1;
294 			}
295 			return pt;
296 		}
297 		else
298 		{
299 			float width = 0.f;
300 			int pos = 0;
301 			while (unicodeText[pos])
302 			{
303 				width += m_currentFont->m_CharWidth[(int)unicodeText[pos]] + extraSpacing;
304 				pos++;
305 			}
306 			Gwen::Point pt;
307 			int fontHeight = m_currentFont->m_CharHeight;
308 
309 			pt.x = width * Scale();
310 			pt.y = (fontHeight + 2) * Scale();
311 
312 			return pt;
313 		}
314 
315 		return Gwen::Renderer::Base::MeasureText(pFont, text);
316 	}
317 
LoadTexture(Gwen::Texture * pTexture)318 	virtual void LoadTexture(Gwen::Texture* pTexture)
319 	{
320 		if (m_textureLoader)
321 			m_textureLoader->LoadTexture(pTexture);
322 	}
FreeTexture(Gwen::Texture * pTexture)323 	virtual void FreeTexture(Gwen::Texture* pTexture)
324 	{
325 		if (m_textureLoader)
326 			m_textureLoader->FreeTexture(pTexture);
327 	}
328 
329 	virtual void DrawTexturedRect(Gwen::Texture* pTexture, Gwen::Rect rect, float u1 = 0.0f, float v1 = 0.0f, float u2 = 1.0f, float v2 = 1.0f)
330 	{
331 		//		BT_PROFILE("DrawTexturedRect");
332 		Translate(rect);
333 
334 		//float eraseColor[4] = {0,0,0,0};
335 		//m_primitiveRenderer->drawRect(rect.x, rect.y+m_yOffset, rect.x+rect.w, rect.y+rect.h+m_yOffset, eraseColor);
336 
337 		GLint texHandle = (GLint)pTexture->m_intData;
338 		//if (!texHandle)
339 		//	return;
340 
341 		glActiveTexture(GL_TEXTURE0);
342 		glBindTexture(GL_TEXTURE_2D, texHandle);
343 		//		glDisable(GL_DEPTH_TEST);
344 
345 		assert(glGetError() == GL_NO_ERROR);
346 
347 		/*	bool useFiltering = true;
348 	if (useFiltering)
349 	{
350 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
351 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
352 	} else
353 	{
354 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
355 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
356 	}
357 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
358 */
359 
360 		//glEnable(GL_TEXTURE_2D);
361 
362 		//	glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE );
363 		static float add = 0.0;
364 		//add+=1./512.;//0.01;
365 		float color[4] = {1, 1, 1, 1};
366 
367 		m_primitiveRenderer->drawTexturedRect(rect.x, rect.y + m_yOffset, rect.x + rect.w, rect.y + rect.h + m_yOffset, color, 0 + add, 0, 1 + add, 1, true);
368 
369 		assert(glGetError() == GL_NO_ERROR);
370 	}
371 };
372 #endif  //__GWEN_OPENGL3_CORE_RENDERER_H
373