fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / chart2 / source / view / main / OpenGLRender.cxx
blob1b64ef1d193ecf83991e4b72387792a54fb637db
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #include <GL/glew.h>
11 #include <vector>
12 #include "OpenGLRender.hxx"
13 #include <vcl/graph.hxx>
14 #include <com/sun/star/awt/XBitmap.hpp>
15 #include <com/sun/star/beans/XPropertySet.hpp>
16 #include <com/sun/star/graphic/XGraphic.hpp>
17 #include <comphelper/InlineContainer.hxx>
18 #include <com/sun/star/drawing/CircleKind.hpp>
19 #include <com/sun/star/drawing/DoubleSequence.hpp>
20 #include <com/sun/star/drawing/FlagSequence.hpp>
21 #include <com/sun/star/drawing/FillStyle.hpp>
22 #include <com/sun/star/drawing/LineStyle.hpp>
23 #include <com/sun/star/drawing/NormalsKind.hpp>
24 #include <com/sun/star/drawing/PointSequence.hpp>
25 #include <com/sun/star/drawing/PolygonKind.hpp>
26 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
27 #include <com/sun/star/drawing/ProjectionMode.hpp>
28 #include <com/sun/star/drawing/ShadeMode.hpp>
29 #include <com/sun/star/drawing/TextFitToSizeType.hpp>
30 #include <com/sun/star/drawing/TextureProjectionMode.hpp>
31 #include <com/sun/star/text/XText.hpp>
32 #include <com/sun/star/uno/Any.hxx>
33 #include <editeng/unoprnms.hxx>
34 #include <vcl/virdev.hxx>
35 #include <vcl/dibtools.hxx>
36 #include <vcl/svapp.hxx>
38 #include <vcl/opengl/OpenGLHelper.hxx>
40 #include "CommonConverters.hxx"
42 using namespace com::sun::star;
44 #define DEBUG_PNG 0
46 #if DEBUG_PNG
47 #include <vcl/pngwrite.hxx>
48 #endif
50 #define GL_PI 3.14159f
52 #define Z_STEP 0.001f
54 static GLfloat squareVertices[] = {
55 -1.0f, -1.0f, -1.0,
56 1.0f, -1.0f, -1.0,
57 1.0f, 1.0f, -1.0,
58 -1.0f, 1.0f, -1.0
61 static GLfloat coordReverseVertices[] = {
62 0.0f, 1.0f,
63 1.0f, 1.0f,
64 1.0f, 0.0f,
65 0.0f, 0.0f,
68 #define CHECK_GL_FRAME_BUFFER_STATUS() \
69 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\
70 if( status != GL_FRAMEBUFFER_COMPLETE ) {\
71 SAL_WARN("chart2.opengl", "OpenGL error: " << status );\
72 return -1;\
75 namespace {
77 GLfloat texCoords[] = {
78 0.0f, 0.0f,
79 1.0f, 0.0f,
80 1.0f, 1.0f,
81 0.0f, 1.0f
86 int OpenGLRender::InitOpenGL()
88 glEnable(GL_TEXTURE_2D);
89 glDisable(GL_CULL_FACE);
90 glCullFace(GL_BACK);
91 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
92 // Enable depth test
93 glEnable(GL_DEPTH_TEST);
94 // Accept fragment if it closer to the camera than the former one
95 glDepthFunc(GL_LESS);
96 glEnable(GL_POINT_SMOOTH);
97 glEnable(GL_LINE_SMOOTH);
98 glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
99 glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
100 glEnable(GL_BLEND);
101 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
103 glClearColor (1.0, 1.0, 1.0, 1.0);
104 glClear(GL_COLOR_BUFFER_BIT);
105 glClearDepth(1.0f);
106 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
108 glGenBuffers(1, &m_VertexBuffer);
109 glGenBuffers(1, &m_ColorBuffer);
111 CHECK_GL_ERROR();
113 m_CommonProID = OpenGLHelper::LoadShaders("commonVertexShader", "commonFragmentShader");
114 m_MatrixID = glGetUniformLocation(m_CommonProID, "MVP");
115 m_2DVertexID = glGetAttribLocation(m_CommonProID, "vPosition");
116 m_2DColorID = glGetUniformLocation(m_CommonProID, "vColor");
117 CHECK_GL_ERROR();
119 #if DEBUG_POSITIONING
120 m_DebugProID = OpenGLHelper::LoadShaders("debugVertexShader", "debugFragmentShader");
121 m_DebugVertexID = glGetAttribLocation(m_DebugProID, "vPosition");
122 CHECK_GL_ERROR();
123 #endif
125 m_BackgroundProID = OpenGLHelper::LoadShaders("backgroundVertexShader", "backgroundFragmentShader");
126 m_BackgroundMatrixID = glGetUniformLocation(m_BackgroundProID, "MVP");
127 m_BackgroundVertexID = glGetAttribLocation(m_BackgroundProID, "vPosition");
128 m_BackgroundColorID = glGetAttribLocation(m_BackgroundProID, "vColor");
130 CHECK_GL_ERROR();
132 m_SymbolProID = OpenGLHelper::LoadShaders("symbolVertexShader", "symbolFragmentShader");
133 m_SymbolVertexID = glGetAttribLocation(m_SymbolProID, "vPosition");
134 m_SymbolMatrixID = glGetUniformLocation(m_SymbolProID, "MVP");
135 m_SymbolColorID = glGetUniformLocation(m_SymbolProID, "vColor");
136 m_SymbolShapeID = glGetUniformLocation(m_SymbolProID, "shape");
138 CHECK_GL_ERROR();
140 m_TextProID = OpenGLHelper::LoadShaders("textVertexShader", "textFragmentShader");
141 m_TextMatrixID = glGetUniformLocation(m_TextProID, "MVP");
142 m_TextVertexID = glGetAttribLocation(m_TextProID, "vPosition");
143 m_TextTexCoordID = glGetAttribLocation(m_TextProID, "texCoord");
144 m_TextTexID = glGetUniformLocation(m_TextProID, "TextTex");
145 CHECK_GL_ERROR();
147 glGenBuffers(1, &m_RenderVertexBuf);
148 glBindBuffer(GL_ARRAY_BUFFER, m_RenderVertexBuf);
149 glBufferData(GL_ARRAY_BUFFER, sizeof(squareVertices), squareVertices, GL_STATIC_DRAW);
150 glBindBuffer(GL_ARRAY_BUFFER, 0);
152 glGenBuffers(1, &m_RenderTexCoordBuf);
153 glBindBuffer(GL_ARRAY_BUFFER, m_RenderTexCoordBuf);
154 glBufferData(GL_ARRAY_BUFFER, sizeof(coordReverseVertices), coordReverseVertices, GL_STATIC_DRAW);
155 glBindBuffer(GL_ARRAY_BUFFER, 0);
157 glGenBuffers(1, &m_TextTexCoordBuf);
158 glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
159 glBufferData(GL_ARRAY_BUFFER, sizeof(texCoords), texCoords, GL_STATIC_DRAW);
160 glBindBuffer(GL_ARRAY_BUFFER, 0);
162 glEnable(GL_LIGHTING);
163 GLfloat light_direction[] = { 0.0 , 0.0 , 1.0 };
164 GLfloat materialDiffuse[] = { 1.0 , 1.0 , 1.0 , 1.0};
165 glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light_direction);
166 glMaterialfv(GL_FRONT,GL_DIFFUSE,materialDiffuse);
167 glEnable(GL_LIGHT0);
168 glEnable(GL_NORMALIZE);
170 return 0;
173 int OpenGLRender::SetLine2DShapePoint(float x, float y, int listLength)
175 if (m_Line2DPointList.empty())
177 m_Line2DPointList.reserve(listLength*3);
179 m_Line2DPointList.push_back(x);
180 m_Line2DPointList.push_back(y);
181 m_Line2DPointList.push_back(m_fZStep);
183 if (m_Line2DPointList.size() == size_t(listLength * 3))
185 m_Line2DShapePointList.push_back(m_Line2DPointList);
186 m_Line2DPointList.clear();
188 return 0;
191 int OpenGLRender::RenderLine2FBO(int)
193 CHECK_GL_ERROR();
194 glLineWidth(m_fLineWidth);
195 size_t listNum = m_Line2DShapePointList.size();
196 PosVecf3 trans = {0.0f, 0.0f, 0.0f};
197 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
198 PosVecf3 scale = {1.0f, 1.0f, 1.0f};
199 MoveModelf(trans, angle, scale);
200 m_MVP = m_Projection * m_View * m_Model;
201 for (size_t i = 0; i < listNum; i++)
203 PointList &pointList = m_Line2DShapePointList.front();
204 //fill vertex buffer
205 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
206 CHECK_GL_ERROR();
207 glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0], GL_STATIC_DRAW);
208 CHECK_GL_ERROR();
209 // Use our shader
210 glUseProgram(m_CommonProID);
211 CHECK_GL_ERROR();
213 glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
214 CHECK_GL_ERROR();
215 glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
216 //CHECK_GL_ERROR();
218 // 1rst attribute buffer : vertices
219 CHECK_GL_ERROR();
220 glVertexAttribPointer(
221 m_2DVertexID,
222 3, // size
223 GL_FLOAT, // type
224 GL_FALSE, // normalized?
225 0, // stride
226 (void*)0 // array buffer offset
228 glEnableVertexAttribArray(m_2DVertexID);
229 glDrawArrays(GL_LINE_STRIP, 0, pointList.size()/3); // 12*3 indices starting at 0 -> 12 triangles
230 CHECK_GL_ERROR();
231 glUseProgram(0);
232 glDisableVertexAttribArray(m_2DVertexID);
233 CHECK_GL_ERROR();
234 m_Line2DShapePointList.pop_front();
236 CHECK_GL_ERROR();
237 CHECK_GL_FRAME_BUFFER_STATUS();
238 m_fZStep += Z_STEP;
239 return 0;
242 #if DEBUG_POSITIONING
243 void OpenGLRender::renderDebug()
245 CHECK_GL_ERROR();
247 GLfloat vertices[4][3] = {
248 {-0.9, -0.9, 0 },
249 {-0.6, -0.2, 0 },
250 {0.3, 0.3, 0 },
251 {0.9, 0.9, 0 } };
253 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
254 CHECK_GL_ERROR();
255 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
256 CHECK_GL_ERROR();
257 glUseProgram(m_DebugProID);
258 CHECK_GL_ERROR();
259 glVertexAttribPointer(m_DebugVertexID, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
260 CHECK_GL_ERROR();
261 glEnableVertexAttribArray(m_DebugVertexID);
263 glDrawArrays(GL_LINE_STRIP, 0, 3);
264 CHECK_GL_ERROR();
265 glDisableVertexAttribArray(m_DebugVertexID);
267 CHECK_GL_ERROR();
269 #endif
271 void OpenGLRender::prepareToRender()
273 glViewport(0, 0, m_iWidth, m_iHeight);
275 // Clear the screen
276 glClearDepth(1.0f);
277 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
278 m_fZStep = 0;
281 int OpenGLRender::MoveModelf(const PosVecf3& trans, const PosVecf3& angle, const PosVecf3& scale)
283 glm::mat4 aTranslationMatrix = glm::translate(glm::vec3(trans.x, trans.y, trans.z));
284 glm::mat4 aScaleMatrix = glm::scale(glm::vec3(scale.x, scale.y, scale.z));
285 glm::mat4 aRotationMatrix = glm::eulerAngleYXZ(angle.y, angle.x, angle.z);
286 m_Model = aTranslationMatrix * aRotationMatrix * aScaleMatrix;
287 return 0;
290 void OpenGLRender::Release()
292 glDeleteBuffers(1, &m_VertexBuffer);
293 glDeleteBuffers(1, &m_ColorBuffer);
294 glDeleteBuffers(1, &m_TextTexCoordBuf);
295 glDeleteProgram(m_CommonProID);
296 glDeleteProgram(m_TextProID);
297 glDeleteProgram(m_BackgroundProID);
298 glDeleteProgram(m_SymbolProID);
301 OpenGLRender::OpenGLRender()
302 : m_iWidth(1600)
303 , m_iHeight(900)
304 , m_Model(glm::mat4(1.0f))
305 , m_VertexBuffer(0)
306 , m_ColorBuffer(0)
307 , m_MatrixID(0)
308 , m_RenderVertexBuf(0)
309 , m_RenderTexCoordBuf(0)
310 , m_fLineWidth(0.001f)
311 , m_2DColor(glm::vec4(1.0, 0.0, 0.0, 1.0))
312 , m_CommonProID(0)
313 , m_2DVertexID(0)
314 , m_2DColorID(0)
315 , m_fZStep(0)
316 , m_TextProID(0)
317 , m_TextMatrixID(0)
318 , m_TextVertexID(0)
319 , m_TextTexCoordID(0)
320 , m_TextTexCoordBuf(0)
321 , m_TextTexID(0)
322 , m_BackgroundProID(0)
323 , m_BackgroundMatrixID(0)
324 , m_BackgroundVertexID(0)
325 , m_BackgroundColorID(0)
326 , m_SymbolProID(0)
327 , m_SymbolVertexID(0)
328 , m_SymbolMatrixID(0)
329 , m_SymbolColorID(0)
330 , m_SymbolShapeID(0)
332 //TODO: moggi: use STL
333 for (size_t i = 0; i < sizeof(m_BackgroundColor) / sizeof(float); i++)
335 m_BackgroundColor[i] = 1.0;
339 OpenGLRender::~OpenGLRender()
341 Release();
344 // TODO: moggi: that screws up FBO if called after buffers have been created!!!!
345 void OpenGLRender::SetSize(int width, int height)
347 m_iWidth = width;
348 m_iHeight = height;
351 void OpenGLRender::SetSizePixel(int width, int height)
353 m_Projection = glm::ortho(0.f, float(m_iWidth), 0.f, float(m_iHeight), -4.f, 3.f);
354 m_Projection = m_Projection * glm::scale(glm::vec3((float)width / m_iWidth, -(float)height / m_iHeight, 1.0f));
356 m_View = glm::lookAt(glm::vec3(0,m_iHeight,1),
357 glm::vec3(0,m_iHeight,0),
358 glm::vec3(0,1,0) );
361 void OpenGLRender::SetLine2DColor(sal_uInt8 r, sal_uInt8 g, sal_uInt8 b, sal_uInt8 nAlpha)
363 m_2DColor = glm::vec4((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, nAlpha/255.f);
366 void OpenGLRender::SetLine2DWidth(int width)
368 m_fLineWidth = std::max((float)width, 0.001f);
371 void OpenGLRender::SetColor(sal_uInt32 color, sal_uInt8 nAlpha)
373 sal_uInt8 r = (color & 0x00FF0000) >> 16;
374 sal_uInt8 g = (color & 0x0000FF00) >> 8;
375 sal_uInt8 b = (color & 0x000000FF);
376 m_2DColor = glm::vec4((float)r / 255.0f, (float)g / 255.0f, (float)b / 255.0f, nAlpha/ 255.f);
379 int OpenGLRender::Create2DCircle(int detail)
381 float angle;
382 if (detail <= 0)
384 return -1;
386 m_Bubble2DCircle.clear();
387 m_Bubble2DCircle.reserve(2 * (detail + 3));
388 m_Bubble2DCircle.push_back(0);
389 m_Bubble2DCircle.push_back(0);
390 for(angle = 2.0f * GL_PI; angle > -(2.0f * GL_PI / detail); angle -= (2.0f * GL_PI / detail))
392 m_Bubble2DCircle.push_back(sin(angle));
393 m_Bubble2DCircle.push_back(cos(angle));
395 return 0;
398 int OpenGLRender::Bubble2DShapePoint(float x, float y, float directionX, float directionY)
400 //check whether to create the circle data
401 if (m_Bubble2DCircle.empty())
403 Create2DCircle(100);
406 Bubble2DPointList aBubble2DPointList;
407 aBubble2DPointList.xScale = directionX;
408 aBubble2DPointList.yScale = directionY;
409 aBubble2DPointList.x = x + aBubble2DPointList.xScale / 2;
410 aBubble2DPointList.y = y + aBubble2DPointList.yScale / 2;
412 m_Bubble2DShapePointList.push_back(aBubble2DPointList);
413 return 0;
416 int OpenGLRender::RenderBubble2FBO(int)
418 CHECK_GL_ERROR();
419 glm::vec4 edgeColor = glm::vec4(0.0, 0.0, 0.0, 1.0);
420 size_t listNum = m_Bubble2DShapePointList.size();
421 for (size_t i = 0; i < listNum; i++)
423 //move the circle to the pos, and scale using the xScale and Y scale
424 Bubble2DPointList &pointList = m_Bubble2DShapePointList.front();
425 PosVecf3 trans = {pointList.x, pointList.y, m_fZStep};
426 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
427 PosVecf3 scale = {pointList.xScale / 2, pointList.yScale / 2 , 1.0f};
428 MoveModelf(trans, angle, scale);
429 m_MVP = m_Projection * m_View * m_Model;
430 //render to fbo
431 //fill vertex buffer
432 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
433 if (m_Bubble2DCircle.empty())
435 Create2DCircle(100);
437 glBufferData(GL_ARRAY_BUFFER, m_Bubble2DCircle.size() * sizeof(GLfloat), &m_Bubble2DCircle[0], GL_STATIC_DRAW);
439 glUseProgram(m_CommonProID);
441 glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
443 glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
444 // 1rst attribute buffer : vertices
445 glEnableVertexAttribArray(m_2DVertexID);
446 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
447 glVertexAttribPointer(
448 m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
449 2, // size
450 GL_FLOAT, // type
451 GL_FALSE, // normalized?
452 0, // stride
453 (void*)0 // array buffer offset
455 glDrawArrays(GL_TRIANGLE_FAN, 0, m_Bubble2DCircle.size() / 2);
456 glDisableVertexAttribArray(m_2DVertexID);
457 glUseProgram(0);
458 glBindBuffer(GL_ARRAY_BUFFER, 0);
459 //add black edge
460 glLineWidth(3.0);
461 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
462 glBufferData(GL_ARRAY_BUFFER, m_Bubble2DCircle.size() * sizeof(GLfloat) -2 , &m_Bubble2DCircle[2], GL_STATIC_DRAW);
463 glUseProgram(m_CommonProID);
464 glUniform4fv(m_2DColorID, 1, &edgeColor[0]);
465 glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
466 glEnableVertexAttribArray(m_2DVertexID);
467 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
468 glVertexAttribPointer(
469 m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
470 2, // size
471 GL_FLOAT, // type
472 GL_FALSE, // normalized?
473 0, // stride
474 (void*)0 // array buffer offset
476 glDrawArrays(GL_LINE_STRIP, 0, (m_Bubble2DCircle.size() * sizeof(GLfloat) -2) / sizeof(float) / 2);
477 glDisableVertexAttribArray(m_2DVertexID);
478 glUseProgram(0);
479 glBindBuffer(GL_ARRAY_BUFFER, 0);
480 m_Bubble2DShapePointList.pop_front();
481 glLineWidth(m_fLineWidth);
483 //if use MSAA, we should copy the data to the FBO texture
484 GLenum fbResult = glCheckFramebufferStatus(GL_FRAMEBUFFER);
485 if( fbResult != GL_FRAMEBUFFER_COMPLETE )
487 SAL_WARN("chart2.opengl", "error");
488 return -1;
490 CHECK_GL_ERROR();
491 m_fZStep += Z_STEP;
492 return 0;
495 int OpenGLRender::RectangleShapePoint(float x, float y, float directionX, float directionY)
497 RectanglePointList aRectangle;
499 aRectangle.points[0] = x;
500 aRectangle.points[1] = y;
501 aRectangle.points[2] = m_fZStep;
502 aRectangle.points[3] = x + directionX;
503 aRectangle.points[4] = y;
504 aRectangle.points[5] = m_fZStep;
505 aRectangle.points[6] = x + directionX;
506 aRectangle.points[7] = y + directionY;
507 aRectangle.points[8] = m_fZStep;
508 aRectangle.points[9] = x;
509 aRectangle.points[10] = y + directionY;
510 aRectangle.points[11] = m_fZStep;
512 m_RectangleShapePointList.push_back(aRectangle);
513 return 0;
516 int OpenGLRender::RenderRectangleShape(bool bBorder, bool bFill)
518 size_t listNum = m_RectangleShapePointList.size();
519 for (size_t i = 0; i < listNum; i++)
521 //move the circle to the pos, and scale using the xScale and Y scale
522 RectanglePointList &pointList = m_RectangleShapePointList.front();
524 PosVecf3 trans = {0, 0, 0};
525 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
526 PosVecf3 scale = {1, 1, 1.0f};
527 MoveModelf(trans, angle, scale);
528 m_MVP = m_Projection * m_View * m_Model;
531 //render to fbo
532 //fill vertex buffer
533 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
534 glBufferData(GL_ARRAY_BUFFER, sizeof(pointList.points), pointList.points, GL_STATIC_DRAW);
536 glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
537 glBufferData(GL_ARRAY_BUFFER, sizeof(m_BackgroundColor), m_BackgroundColor, GL_STATIC_DRAW);
538 glUseProgram(m_BackgroundProID);
540 glUniformMatrix4fv(m_BackgroundMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
541 if(bFill)
543 glEnableVertexAttribArray(m_BackgroundVertexID);
544 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
545 glVertexAttribPointer(
546 m_BackgroundVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
547 3, // size
548 GL_FLOAT, // type
549 GL_FALSE, // normalized?
550 0, // stride
551 (void*)0 // array buffer offset
554 // 2nd attribute buffer : color
555 glEnableVertexAttribArray(m_BackgroundColorID);
556 glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
557 glVertexAttribPointer(
558 m_BackgroundColorID, // attribute. No particular reason for 0, but must match the layout in the shader.
559 4, // size
560 GL_FLOAT, // type
561 GL_FALSE, // normalized?
562 0, // stride
563 (void*)0 // array buffer offset
565 //TODO: moggi: get rid of GL_QUADS
566 glDrawArrays(GL_QUADS, 0, 4);
567 glDisableVertexAttribArray(m_BackgroundVertexID);
568 glDisableVertexAttribArray(m_BackgroundColorID);
570 if(bBorder)
572 if(bFill)
574 PosVecf3 trans = {0.0, 0.0, Z_STEP };
575 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
576 PosVecf3 scale = {1, 1, 1.0f};
577 MoveModelf(trans, angle, scale);
578 m_MVP = m_Projection * m_View * m_Model;
580 m_fZStep += Z_STEP;
581 glUniformMatrix4fv(m_BackgroundMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
583 SetBackGroundColor(COL_BLACK, COL_BLACK, 255);
585 glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
586 glBufferData(GL_ARRAY_BUFFER, sizeof(m_BackgroundColor), m_BackgroundColor, GL_STATIC_DRAW);
587 // 1rst attribute buffer : vertices
588 glEnableVertexAttribArray(m_BackgroundVertexID);
589 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
590 glVertexAttribPointer(
591 m_BackgroundVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
592 3, // size
593 GL_FLOAT, // type
594 GL_FALSE, // normalized?
595 0, // stride
596 (void*)0 // array buffer offset
599 // 2nd attribute buffer : color
600 glEnableVertexAttribArray(m_BackgroundColorID);
601 glBindBuffer(GL_ARRAY_BUFFER, m_ColorBuffer);
602 glVertexAttribPointer(
603 m_BackgroundColorID, // attribute. No particular reason for 0, but must match the layout in the shader.
604 4, // size
605 GL_FLOAT, // type
606 GL_FALSE, // normalized?
607 0, // stride
608 (void*)0 // array buffer offset
610 glDrawArrays(GL_LINE_LOOP, 0, 4);
611 glDisableVertexAttribArray(m_BackgroundVertexID);
612 glDisableVertexAttribArray(m_BackgroundColorID);
614 glDisableVertexAttribArray(m_BackgroundVertexID);
615 glDisableVertexAttribArray(m_BackgroundColorID);
616 glUseProgram(0);
617 glBindBuffer(GL_ARRAY_BUFFER, 0);
618 m_RectangleShapePointList.pop_front();
620 CHECK_GL_ERROR();
622 m_fZStep += Z_STEP;
623 return 0;
626 int OpenGLRender::CreateTextTexture(::rtl::OUString const &textValue, vcl::Font aFont, long , awt::Point aPos, awt::Size aSize, long rotation)
628 ScopedVclPtrInstance< VirtualDevice > pDevice(*Application::GetDefaultDevice(), 0, 0);
629 pDevice->Erase();
630 Rectangle aRect;
631 pDevice->SetFont(aFont);
632 pDevice->GetTextBoundRect(aRect, textValue);
633 int screenWidth = (aRect.BottomRight().X() + 3) & ~3;
634 int screenHeight = (aRect.BottomRight().Y() + 3) & ~3;
635 pDevice->SetOutputSizePixel(Size(screenWidth * 3, screenHeight));
636 pDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
637 pDevice->DrawText(Point(0, 0), textValue);
638 int bmpWidth = (aRect.Right() - aRect.Left() + 3) & ~3;
639 int bmpHeight = (aRect.Bottom() - aRect.Top() + 3) & ~3;
640 BitmapEx aBitmap = BitmapEx(pDevice->GetBitmapEx(aRect.TopLeft(), Size(bmpWidth, bmpHeight)));
642 sal_Int32 nXPos = aPos.X;
643 sal_Int32 nYPos = aPos.Y;
644 ::basegfx::B2DHomMatrix aM;
645 aM.rotate( -rotation*F_PI/180.0 );//#i78696#->#i80521#
646 aM.translate( nXPos, nYPos );
647 drawing::HomogenMatrix3 aTrans = chart::B2DHomMatrixToHomogenMatrix3(aM);
648 aTrans.Line1.Column1 = 20 * bmpWidth;
649 aTrans.Line2.Column2 = 20 * bmpHeight;
650 return CreateTextTexture(aBitmap,aPos,aSize,rotation,aTrans);
653 int OpenGLRender::CreateTextTexture(const BitmapEx& rBitmapEx, const awt::Point&, const awt::Size& aSize, long rotation,
654 const drawing::HomogenMatrix3& rTrans)
656 #if DEBUG_PNG // debug PNG writing
657 static int nIdx = 0;
658 OUString aName = OUString( "file:///home/moggi/Documents/work/text" ) + OUString::number( nIdx++ ) + ".png";
659 try {
660 vcl::PNGWriter aWriter( rBitmapEx );
661 SvFileStream sOutput( aName, StreamMode::WRITE );
662 aWriter.Write( sOutput );
663 sOutput.Close();
664 } catch (...) {
665 SAL_WARN("chart2.opengl", "Error writing png to " << aName);
667 #endif
669 boost::shared_array<sal_uInt8> bitmapBuf(new sal_uInt8[4 * rBitmapEx.GetSizePixel().Width() * rBitmapEx.GetSizePixel().Height()]);
671 OpenGLHelper::ConvertBitmapExToRGBATextureBuffer(rBitmapEx, bitmapBuf.get());
673 return CreateTextTexture(bitmapBuf, rBitmapEx.GetSizePixel(),
674 awt::Point(), aSize, rotation, rTrans);
677 int OpenGLRender::CreateTextTexture(const boost::shared_array<sal_uInt8> &rPixels,
678 const ::Size &aPixelSize,
679 const awt::Point&,
680 const awt::Size& aSize,
681 long rotation,
682 const drawing::HomogenMatrix3& rTrans)
684 long bmpWidth = aPixelSize.Width();
685 long bmpHeight = aPixelSize.Height();
687 TextInfo aTextInfo;
688 aTextInfo.rotation = -(double)rotation / 360.0 * 2* GL_PI;
689 aTextInfo.vertex[0] = -aSize.Width / 2;
690 aTextInfo.vertex[1] = -aSize.Height / 2;
691 aTextInfo.vertex[2] = m_fZStep;
693 aTextInfo.vertex[3] = aSize.Width / 2;
694 aTextInfo.vertex[4] = -aSize.Height / 2;
695 aTextInfo.vertex[5] = m_fZStep;
697 aTextInfo.vertex[6] = aSize.Width / 2;
698 aTextInfo.vertex[7] = aSize.Height / 2;
699 aTextInfo.vertex[8] = m_fZStep;
701 aTextInfo.vertex[9] = -aSize.Width / 2;
702 aTextInfo.vertex[10] = aSize.Height / 2;
703 aTextInfo.vertex[11] = m_fZStep;
704 aTextInfo.nDx = (rTrans.Line1.Column3 + aSize.Width / 2 ) - bmpWidth/2;
705 aTextInfo.nDy = (rTrans.Line2.Column3 + aSize.Height / 2 ) - bmpHeight/2;
707 CHECK_GL_ERROR();
708 glGenTextures(1, &aTextInfo.texture);
709 CHECK_GL_ERROR();
710 glBindTexture(GL_TEXTURE_2D, aTextInfo.texture);
711 CHECK_GL_ERROR();
712 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
713 CHECK_GL_ERROR();
714 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
715 CHECK_GL_ERROR();
716 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
717 CHECK_GL_ERROR();
718 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
719 CHECK_GL_ERROR();
720 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmpWidth, bmpHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, rPixels.get());
721 CHECK_GL_ERROR();
722 glBindTexture(GL_TEXTURE_2D, 0);
723 CHECK_GL_ERROR();
724 m_TextInfoList.push_back(aTextInfo);
725 return 0;
728 int OpenGLRender::RenderTextShape()
730 CHECK_GL_ERROR();
731 size_t listNum = m_TextInfoList.size();
732 for (size_t i = 0; i < listNum; i++)
734 TextInfo &textInfo = m_TextInfoList.front();
735 PosVecf3 trans = { textInfo.nDx, textInfo.nDy, 0};
736 PosVecf3 angle = {0.0f, 0.0f, float(textInfo.rotation)};
737 PosVecf3 scale = {1.0, 1.0, 1.0f};
738 MoveModelf(trans, angle, scale);
739 m_MVP = m_Projection * m_View * m_Model;
740 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
741 CHECK_GL_ERROR();
742 glBufferData(GL_ARRAY_BUFFER, sizeof(textInfo.vertex), textInfo.vertex, GL_STATIC_DRAW);
743 CHECK_GL_ERROR();
744 glUseProgram(m_TextProID);
746 CHECK_GL_ERROR();
747 glUniformMatrix4fv(m_TextMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
748 // 1rst attribute buffer : vertices
749 glEnableVertexAttribArray(m_TextVertexID);
750 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
751 glVertexAttribPointer(
752 m_TextVertexID,
753 3, // size
754 GL_FLOAT, // type
755 GL_FALSE, // normalized?
756 0, // stride
757 (void*)0 // array buffer offset
759 //tex coord
760 CHECK_GL_ERROR();
761 glEnableVertexAttribArray(m_TextTexCoordID);
762 glBindBuffer(GL_ARRAY_BUFFER, m_TextTexCoordBuf);
763 glVertexAttribPointer(
764 m_TextTexCoordID,
765 2, // size
766 GL_FLOAT, // type
767 GL_FALSE, // normalized?
768 0, // stride
769 (void*)0 // array buffer offset
771 //texture
772 CHECK_GL_ERROR();
773 glBindTexture(GL_TEXTURE_2D, textInfo.texture);
774 CHECK_GL_ERROR();
775 glUniform1i(m_TextTexID, 0);
776 CHECK_GL_ERROR();
777 //TODO: moggi: get rid fo GL_QUADS
778 glDrawArrays(GL_QUADS, 0, 4);
779 CHECK_GL_ERROR();
780 glDisableVertexAttribArray(m_TextTexCoordID);
781 CHECK_GL_ERROR();
782 glDisableVertexAttribArray(m_TextVertexID);
783 CHECK_GL_ERROR();
784 glBindTexture(GL_TEXTURE_2D, 0);
785 glUseProgram(0);
786 glDeleteTextures(1, &textInfo.texture);
787 CHECK_GL_ERROR();
788 m_TextInfoList.pop_front();
790 CHECK_GL_ERROR();
791 m_fZStep += Z_STEP;
792 return 0;
795 int OpenGLRender::SetArea2DShapePoint(float x, float y, int listLength)
797 if (m_Area2DPointList.empty())
799 m_Area2DPointList.reserve(listLength);
801 m_Area2DPointList.push_back(x);
802 m_Area2DPointList.push_back(y);
803 m_Area2DPointList.push_back(m_fZStep);
805 if (m_Area2DPointList.size() == size_t(listLength * 3))
807 m_Area2DShapePointList.push_back(m_Area2DPointList);
808 m_Area2DPointList.clear();
810 return 0;
813 namespace {
815 // only 2D
816 bool checkCCW(const PointList& rPoints)
818 if(rPoints.size() < 3)
819 return true;
821 GLfloat sum = 0;
822 for(size_t i = 1; i < rPoints.size()/3; i += 3)
824 GLfloat x1 = rPoints[(i-1)*3];
825 GLfloat x2 = rPoints[i*3];
826 GLfloat y1 = rPoints[(i-1)*3 + 1];
827 GLfloat y2 = rPoints[i*3 + 1];
828 GLfloat prod = (x2-x1)*(y2+y1);
830 sum += prod;
833 return (sum <= 0);
838 int OpenGLRender::RenderArea2DShape()
840 CHECK_GL_ERROR();
842 glDisable(GL_MULTISAMPLE);
843 size_t listNum = m_Area2DShapePointList.size();
844 PosVecf3 trans = {0.0f, 0.0f, 0.0f};
845 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
846 PosVecf3 scale = {1.0f, 1.0f, 1.0f};
847 MoveModelf(trans, angle, scale);
848 m_MVP = m_Projection * m_View * m_Model;
849 for (size_t i = 0; i < listNum; ++i)
851 PointList &pointList = m_Area2DShapePointList.front();
852 bool bIsCCW = checkCCW(pointList); // is it counter clockwise (CCW) or clockwise (CW)
853 if(!bIsCCW)
854 glFrontFace(GL_CW);
855 //fill vertex buffer
856 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
857 glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0], GL_STATIC_DRAW);
858 // Use our shader
859 glUseProgram(m_CommonProID);
861 glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
863 glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
865 // 1rst attribute buffer : vertices
866 glEnableVertexAttribArray(m_2DVertexID);
867 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
868 glVertexAttribPointer(
869 m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
870 3, // size
871 GL_FLOAT, // type
872 GL_FALSE, // normalized?
873 0, // stride
874 (void*)0 // array buffer offset
876 // TODO: moggi: remove deprecated GL_POLYGON
877 glDrawArrays(GL_POLYGON, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
878 glDisableVertexAttribArray(m_2DVertexID);
879 glUseProgram(0);
880 if(!bIsCCW)
881 glFrontFace(GL_CCW);
882 m_Area2DShapePointList.pop_front();
884 glEnable(GL_MULTISAMPLE);
885 m_fZStep += Z_STEP;
887 CHECK_GL_ERROR();
889 return 0;
892 void OpenGLRender::SetBackGroundColor(sal_uInt32 color1, sal_uInt32 color2, sal_uInt8 fillStyle)
894 sal_uInt8 r = (color1 & 0x00FF0000) >> 16;
895 sal_uInt8 g = (color1 & 0x0000FF00) >> 8;
896 sal_uInt8 b = (color1 & 0x000000FF);
898 m_BackgroundColor[0] = (float)r / 255.0f;
899 m_BackgroundColor[1] = (float)g / 255.0f;
900 m_BackgroundColor[2] = (float)b / 255.0f;
901 m_BackgroundColor[3] = fillStyle ? 1.0 : 0.0;
903 m_BackgroundColor[4] = (float)r / 255.0f;
904 m_BackgroundColor[5] = (float)g / 255.0f;
905 m_BackgroundColor[6] = (float)b / 255.0f;
906 m_BackgroundColor[7] = fillStyle ? 1.0 : 0.0;
908 r = (color2 & 0x00FF0000) >> 16;
909 g = (color2 & 0x0000FF00) >> 8;
910 b = (color2 & 0x000000FF);
912 m_BackgroundColor[8] = (float)r / 255.0f;
913 m_BackgroundColor[9] = (float)g / 255.0f;
914 m_BackgroundColor[10] = (float)b / 255.0f;
915 m_BackgroundColor[11] = fillStyle ? 1.0 : 0.0;
917 m_BackgroundColor[12] = (float)r / 255.0f;
918 m_BackgroundColor[13] = (float)g / 255.0f;
919 m_BackgroundColor[14] = (float)b / 255.0f;
920 m_BackgroundColor[15] = fillStyle ? 1.0 : 0.0;
921 SAL_INFO("chart2.opengl", "color1 = " << color1 << ", color2 = " << color2);
925 void OpenGLRender::SetChartTransparencyGradient(long transparencyGradient)
927 if (transparencyGradient == 1)
929 m_BackgroundColor[11] = 0.0;
930 m_BackgroundColor[15] = 0.0;
934 void OpenGLRender::GeneratePieSegment2D(double fInnerRadius, double fOutterRadius, double nAngleStart, double nAngleWidth)
936 double nAngleStep = 1;
937 PointList aPointList;
938 // TODO: moggi: GL_TRIANGLE_FAN seems not to work
939 const bool bInnerRadiusNotZero = true; //!rtl::math::approxEqual(0.0, fInnerRadius);
940 size_t nVectorSize = 3*(nAngleWidth/nAngleStep);
941 if(bInnerRadiusNotZero)
942 nVectorSize *= 2;
944 nAngleStart += 90;
945 aPointList.reserve(nVectorSize);
946 // if inner radius = 0 generate a normal pie segment (triangle fan)
947 // if inner radius != 0 generate a pie segment - inner pie (triangle strip)
948 if(!bInnerRadiusNotZero)
950 aPointList.push_back(0);
951 aPointList.push_back(0);
952 aPointList.push_back(m_fZStep);
954 for(double nAngle = nAngleStart; nAngle <= nAngleStart + nAngleWidth; nAngle += nAngleStep)
956 float xVal = sin(nAngle/360*2*GL_PI);
957 float yVal = cos(nAngle/360*2*GL_PI);
958 aPointList.push_back(fOutterRadius * xVal);
959 aPointList.push_back(fOutterRadius * yVal);
960 aPointList.push_back(m_fZStep);
962 if(bInnerRadiusNotZero)
964 aPointList.push_back(fInnerRadius * xVal);
965 aPointList.push_back(fInnerRadius * yVal);
966 aPointList.push_back(m_fZStep);
970 m_PieSegment2DShapePointList.push_back(aPointList);
973 int OpenGLRender::RenderPieSegment2DShape(float fSize, float fPosX, float fPosY)
975 int listNum = m_PieSegment2DShapePointList.size();
976 PosVecf3 trans = {fPosX, fPosY, 0.0f};
977 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
978 PosVecf3 scale = {fSize, fSize, 1.0f};
979 MoveModelf(trans, angle, scale);
980 m_MVP = m_Projection * m_View * m_Model;
982 for (int i = 0; i < listNum; i++)
984 PointList &pointList = m_PieSegment2DShapePointList.back();
985 //fill vertex buffer
986 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
987 glBufferData(GL_ARRAY_BUFFER, pointList.size() * sizeof(float), &pointList[0] , GL_STATIC_DRAW);
988 // Use our shader
989 glUseProgram(m_CommonProID);
991 glUniform4fv(m_2DColorID, 1, &m_2DColor[0]);
993 glUniformMatrix4fv(m_MatrixID, 1, GL_FALSE, &m_MVP[0][0]);
995 // 1rst attribute buffer : vertices
996 glEnableVertexAttribArray(m_2DVertexID);
997 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
998 glVertexAttribPointer(
999 m_2DVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
1000 3, // size
1001 GL_FLOAT, // type
1002 GL_FALSE, // normalized?
1003 0, // stride
1004 (void*)0 // array buffer offset
1006 glDrawArrays(GL_TRIANGLE_STRIP, 0, pointList.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
1007 glDisableVertexAttribArray(m_2DVertexID);
1008 glUseProgram(0);
1009 m_PieSegment2DShapePointList.pop_back();
1010 CHECK_GL_ERROR();
1013 m_fZStep += Z_STEP;
1015 CHECK_GL_ERROR();
1016 return 0;
1019 int OpenGLRender::RenderSymbol2DShape(float x, float y, float , float , sal_Int32 nSymbol)
1021 CHECK_GL_ERROR();
1023 glPointSize(20.f);
1024 CHECK_GL_ERROR();
1025 PosVecf3 trans = {0.0, 0.0, 0.0};
1026 PosVecf3 angle = {0.0f, 0.0f, 0.0f};
1027 PosVecf3 scale = {1.0, 1.0, 1.0f};
1028 MoveModelf(trans, angle, scale);
1029 m_MVP = m_Projection * m_View * m_Model;
1031 float aPos[3] = { x, y, m_fZStep };
1032 //fill vertex buffer
1033 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1034 CHECK_GL_ERROR();
1035 glBufferData(GL_ARRAY_BUFFER, 3 * sizeof(float), aPos, GL_STATIC_DRAW);
1036 CHECK_GL_ERROR();
1038 // Use our shader
1039 glUseProgram(m_SymbolProID);
1040 CHECK_GL_ERROR();
1042 glUniform4fv(m_SymbolColorID, 1, &m_2DColor[0]);
1043 glUniform1i(m_SymbolShapeID, nSymbol);
1044 CHECK_GL_ERROR();
1046 glUniformMatrix4fv(m_SymbolMatrixID, 1, GL_FALSE, &m_MVP[0][0]);
1048 CHECK_GL_ERROR();
1049 // 1rst attribute buffer : vertices
1050 glEnableVertexAttribArray(m_SymbolVertexID);
1051 glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
1052 glVertexAttribPointer(
1053 m_SymbolVertexID, // attribute. No particular reason for 0, but must match the layout in the shader.
1054 3, // size
1055 GL_FLOAT, // type
1056 GL_FALSE, // normalized?
1057 0, // stride
1058 (void*)0 // array buffer offset
1061 glDrawArrays(GL_POINTS, 0, 1);
1063 glDisableVertexAttribArray(m_SymbolVertexID);
1064 CHECK_GL_ERROR();
1065 glUseProgram(0);
1066 m_fZStep += Z_STEP;
1068 CHECK_GL_ERROR();
1069 return 0;
1072 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */