1 /***************************************************************************
2  *   Copyright (C) 2005-2019 by the FIFE team                              *
3  *   http://www.fifengine.net                                              *
4  *   This file is part of FIFE.                                            *
5  *                                                                         *
6  *   FIFE is free software; you can redistribute it and/or                 *
7  *   modify it under the terms of the GNU Lesser General Public            *
8  *   License as published by the Free Software Foundation; either          *
9  *   version 2.1 of the License, or (at your option) any later version.    *
10  *                                                                         *
11  *   This library is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
14  *   Lesser General Public License for more details.                       *
15  *                                                                         *
16  *   You should have received a copy of the GNU Lesser General Public      *
17  *   License along with this library; if not, write to the                 *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 
24 // This needs to be here, before Fifechan includes gl.h
25 #include "video/opengl/fife_opengl.h"
26 
27 // 3rd party library includes
28 #include <fifechan/opengl.hpp>
29 #include <fifechan/font.hpp>
30 
31 
32 // FIFE includes
33 // These includes are split up in two parts, separated by one empty line
34 // First block: files included from the FIFE root src dir
35 #include "util/log/logger.h"
36 #include "util/base/exception.h"
37 #include "gui/fifechan/base/gui_image.h"
38 #include "util/structures/rect.h"
39 #include "video/image.h"
40 #include "video/imagemanager.h"
41 #include "video/opengl/renderbackendopengl.h"
42 
43 #include "opengl_gui_graphics.h"
44 
45 namespace FIFE {
46 	static Logger _log(LM_GUI);
47 
OpenGLGuiGraphics()48 	OpenGLGuiGraphics::OpenGLGuiGraphics() {
49 		mColor = fcn::Color(255, 255, 255, 255);
50 		m_renderbackend = static_cast<RenderBackendOpenGL*>(RenderBackend::instance());
51 		setTargetPlane(m_renderbackend->getWidth(), m_renderbackend->getHeight());
52 	}
53 
updateTarget()54 	void OpenGLGuiGraphics::updateTarget() {
55 		setTargetPlane(m_renderbackend->getWidth(), m_renderbackend->getHeight());
56 	}
57 
drawImage(const fcn::Image * image,int32_t srcX,int32_t srcY,int32_t dstX,int32_t dstY,int32_t width,int32_t height)58 	void OpenGLGuiGraphics::drawImage(const fcn::Image* image, int32_t srcX, int32_t srcY, int32_t dstX, int32_t dstY, int32_t width, int32_t height) {
59 		const GuiImage* g_img = dynamic_cast<const GuiImage*>(image);
60 		assert(g_img);
61 
62 		ImagePtr fifeimg = g_img->getFIFEImage();
63 		const fcn::ClipRectangle& clip = mClipStack.top();
64 		fifeimg->render(Rect(dstX + clip.xOffset, dstY + clip.yOffset,
65 			width, height));
66 	}
67 
drawText(const std::string & text,int32_t x,int32_t y,uint32_t alignment)68 	void OpenGLGuiGraphics::drawText(const std::string& text, int32_t x, int32_t y,
69 			uint32_t alignment) {
70 		if (mFont == NULL)
71 		{
72 			throw GuiException("OpenGLGuiGraphics::drawText() - No font set!");
73 		}
74 
75 		switch (alignment)
76 		{
77 			case Left:
78 				mFont->drawString(this, text, x, y);
79 				break;
80 			case Center:
81 				mFont->drawString(this, text, x - mFont->getWidth(text) / 2, y);
82 				break;
83 			case Right:
84 				mFont->drawString(this, text, x - mFont->getWidth(text), y);
85 				break;
86 			default:
87 				FL_WARN(_log, LMsg("OpenGLGuiGraphics::drawText() - ") << "Unknown alignment: " << alignment);
88 				mFont->drawString(this, text, x, y);
89 		}
90 	}
91 
drawPoint(int32_t x,int32_t y)92 	void OpenGLGuiGraphics::drawPoint(int32_t x, int32_t y) {
93 		const fcn::ClipRectangle& top = mClipStack.top();
94 		m_renderbackend->putPixel(x + top.xOffset, y + top.yOffset,
95 			mColor.r, mColor.g, mColor.b, mColor.a);
96 	}
97 
drawLine(int32_t x1,int32_t y1,int32_t x2,int32_t y2)98 	void OpenGLGuiGraphics::drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2) {
99 		const fcn::ClipRectangle& top = mClipStack.top();
100 		x1 += top.xOffset;
101 		x2 += top.xOffset;
102 		y1 += top.yOffset;
103 		y2 += top.yOffset;
104 
105 		/*Point pbegin(static_cast<int32_t>(ceil(x1 + 0.375f)), static_cast<int32_t>(ceil(y1 + 0.375f)));
106 		Point pend(static_cast<int32_t>(ceil(x2 + 0.625f)), static_cast<int32_t>(ceil(y2 + 0.625f)));*/
107 		/*if (x1 == x2) {
108 			y2 += 1;
109 		} else if (y1 == y2) {
110 			x2 += 1;
111 		}*/
112 		Point pbegin(x1, y1);
113 		Point pend(x2, y2);
114 
115 		m_renderbackend->drawLine(pbegin, pend,
116 			mColor.r, mColor.g, mColor.b, mColor.a);
117 		//m_renderbackend->putPixel(pbegin.x, pbegin.y,
118 		//	mColor.r, mColor.g, mColor.b, mColor.a);
119 		m_renderbackend->putPixel(pend.x, pend.y,
120 			mColor.r, mColor.g, mColor.b, mColor.a);
121 	}
122 
drawLine(int32_t x1,int32_t y1,int32_t x2,int32_t y2,uint32_t width)123 	void OpenGLGuiGraphics::drawLine(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t width) {
124 		const fcn::ClipRectangle& top = mClipStack.top();
125 		m_renderbackend->drawThickLine(Point(x1+top.xOffset, y1+top.yOffset), Point(x2+top.xOffset, y2+top.yOffset), width, mColor.r, mColor.g, mColor.b, mColor.a);
126 	}
127 
drawPolyLine(const fcn::PointVector & points,uint32_t width)128 	void OpenGLGuiGraphics::drawPolyLine(const fcn::PointVector& points, uint32_t width) {
129 		const fcn::ClipRectangle& top = mClipStack.top();
130 		std::vector<Point> npoints;
131 		fcn::PointVector::const_iterator it = points.begin();
132 		for (; it != points.end(); ++it) {
133 			npoints.push_back(Point((*it).x+top.xOffset, (*it).y+top.yOffset));
134 		}
135 		m_renderbackend->drawPolyLine(npoints, width, mColor.r, mColor.g, mColor.b, mColor.a);
136 	}
137 
drawBezier(const fcn::PointVector & points,int32_t steps,uint32_t width)138 	void OpenGLGuiGraphics::drawBezier(const fcn::PointVector& points, int32_t steps, uint32_t width) {
139 		const fcn::ClipRectangle& top = mClipStack.top();
140 		std::vector<Point> npoints;
141 		fcn::PointVector::const_iterator it = points.begin();
142 		for (; it != points.end(); ++it) {
143 			npoints.push_back(Point((*it).x+top.xOffset, (*it).y+top.yOffset));
144 		}
145 		m_renderbackend->drawBezier(npoints, steps, width, mColor.r, mColor.g, mColor.b, mColor.a);
146 	}
147 
drawRectangle(const fcn::Rectangle & rectangle)148 	void OpenGLGuiGraphics::drawRectangle(const fcn::Rectangle& rectangle) {
149 		const fcn::ClipRectangle& top = mClipStack.top();
150 		m_renderbackend->drawRectangle(
151 			Point(rectangle.x + top.xOffset, rectangle.y + top.yOffset),
152 			rectangle.width, rectangle.height,
153 			mColor.r, mColor.g, mColor.b, mColor.a);
154 	}
155 
fillRectangle(const fcn::Rectangle & rectangle)156 	void OpenGLGuiGraphics::fillRectangle(const fcn::Rectangle& rectangle) {
157 		const fcn::ClipRectangle& top = mClipStack.top();
158 		m_renderbackend->fillRectangle(
159 			Point(rectangle.x + top.xOffset, rectangle.y + top.yOffset),
160 			rectangle.width, rectangle.height,
161 			mColor.r, mColor.g, mColor.b, mColor.a);
162 	}
163 
drawCircle(const fcn::Point & p,uint32_t radius)164 	void OpenGLGuiGraphics::drawCircle(const fcn::Point& p, uint32_t radius) {
165 		const fcn::ClipRectangle& top = mClipStack.top();
166 		m_renderbackend->drawCircle(Point(p.x+top.xOffset, p.y+top.yOffset), radius, mColor.r, mColor.g, mColor.b, mColor.a);
167 	}
168 
drawFillCircle(const fcn::Point & p,uint32_t radius)169 	void OpenGLGuiGraphics::drawFillCircle(const fcn::Point& p, uint32_t radius) {
170 		const fcn::ClipRectangle& top = mClipStack.top();
171 		m_renderbackend->drawFillCircle(Point(p.x+top.xOffset, p.y+top.yOffset), radius, mColor.r, mColor.g, mColor.b, mColor.a);
172 	}
173 
drawCircleSegment(const fcn::Point & p,uint32_t radius,int32_t sangle,int32_t eangle)174 	void OpenGLGuiGraphics::drawCircleSegment(const fcn::Point& p, uint32_t radius, int32_t sangle, int32_t eangle) {
175 		const fcn::ClipRectangle& top = mClipStack.top();
176 		m_renderbackend->drawCircleSegment(Point(p.x+top.xOffset, p.y+top.yOffset), radius, sangle, eangle, mColor.r, mColor.g, mColor.b, mColor.a);
177 	}
178 
drawFillCircleSegment(const fcn::Point & p,uint32_t radius,int32_t sangle,int32_t eangle)179 	void OpenGLGuiGraphics::drawFillCircleSegment(const fcn::Point& p, uint32_t radius, int32_t sangle, int32_t eangle) {
180 		const fcn::ClipRectangle& top = mClipStack.top();
181 		m_renderbackend->drawFillCircleSegment(Point(p.x+top.xOffset, p.y+top.yOffset), radius, sangle, eangle, mColor.r, mColor.g, mColor.b, mColor.a);
182 	}
183 
_beginDraw()184 	void OpenGLGuiGraphics::_beginDraw() {
185 		fcn::Rectangle area(0, 0, mWidth, mHeight);
186 		fcn::Graphics::pushClipArea(area);
187 		m_renderbackend->pushClipArea(Rect(0, 0, mWidth, mHeight), false);
188 	}
189 
_endDraw()190 	void OpenGLGuiGraphics::_endDraw() {
191 		m_renderbackend->renderVertexArrays();
192 
193 		// Cleanup
194 		fcn::Graphics::popClipArea();
195 		m_renderbackend->popClipArea();
196 	}
197 
pushClipArea(fcn::Rectangle area)198 	bool OpenGLGuiGraphics::pushClipArea(fcn::Rectangle area) {
199 		// Render what we gathered so far
200 		m_renderbackend->renderVertexArrays();
201 		fcn::Graphics::pushClipArea(area);
202 
203 		// Due to some odd conception in guiChan some of area
204 		// has xOffset and yOffset > 0. And if it happens we
205 		// need to offset our clip area. Or we can use Fifechan stack.
206 		const fcn::ClipRectangle& top = mClipStack.top();
207 
208 		m_renderbackend->pushClipArea(
209 			Rect(top.x, top.y, top.width, top.height), false);
210 
211 		return true;
212 	}
213 
popClipArea()214 	void OpenGLGuiGraphics::popClipArea() {
215 		// Render what we gathered so far
216 		m_renderbackend->renderVertexArrays();
217 		fcn::Graphics::popClipArea();
218 		m_renderbackend->popClipArea();
219 	}
220 
setColor(const fcn::Color & color)221 	void OpenGLGuiGraphics::setColor(const fcn::Color& color) {
222 		mColor = color;
223 	}
224 }
225