1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
13 #include "OpenGLRender.hxx"
14 #include <vcl/graph.hxx>
15 #include <com/sun/star/awt/XBitmap.hpp>
16 #include <com/sun/star/beans/XPropertySet.hpp>
17 #include <com/sun/star/graphic/XGraphic.hpp>
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 <editeng/unoprnms.hxx>
33 #include <vcl/virdev.hxx>
34 #include <vcl/dibtools.hxx>
35 #include <vcl/svapp.hxx>
37 #include <vcl/opengl/OpenGLHelper.hxx>
39 #include <CommonConverters.hxx>
41 using namespace com::sun::star
;
46 #include <vcl/pngwrite.hxx>
49 #define GL_PI 3.14159f
53 static GLfloat squareVertices
[] = {
60 static GLfloat coordReverseVertices
[] = {
67 #define CHECK_GL_FRAME_BUFFER_STATUS() \
68 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);\
69 if( status != GL_FRAMEBUFFER_COMPLETE ) {\
70 SAL_WARN("chart2.opengl", "OpenGL error: " << status );\
76 GLfloat texCoords
[] = {
85 int OpenGLRender::InitOpenGL()
87 glEnable(GL_TEXTURE_2D
);
88 glDisable(GL_CULL_FACE
);
90 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
92 glEnable(GL_DEPTH_TEST
);
93 // Accept fragment if it closer to the camera than the former one
95 glEnable(GL_POINT_SMOOTH
);
96 glEnable(GL_LINE_SMOOTH
);
97 glHint(GL_POINT_SMOOTH_HINT
, GL_NICEST
);
98 glHint(GL_LINE_SMOOTH_HINT
, GL_NICEST
);
100 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
102 glClearColor (1.0, 1.0, 1.0, 1.0);
103 glClear(GL_COLOR_BUFFER_BIT
);
105 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
107 glGenBuffers(1, &m_VertexBuffer
);
108 glGenBuffers(1, &m_ColorBuffer
);
112 m_CommonProID
= OpenGLHelper::LoadShaders("commonVertexShader", "commonFragmentShader");
113 m_MatrixID
= glGetUniformLocation(m_CommonProID
, "MVP");
114 m_2DVertexID
= glGetAttribLocation(m_CommonProID
, "vPosition");
115 m_2DColorID
= glGetUniformLocation(m_CommonProID
, "vColor");
118 #if DEBUG_POSITIONING
119 m_DebugProID
= OpenGLHelper::LoadShaders("debugVertexShader", "debugFragmentShader");
120 m_DebugVertexID
= glGetAttribLocation(m_DebugProID
, "vPosition");
124 m_BackgroundProID
= OpenGLHelper::LoadShaders("backgroundVertexShader", "backgroundFragmentShader");
125 m_BackgroundMatrixID
= glGetUniformLocation(m_BackgroundProID
, "MVP");
126 m_BackgroundVertexID
= glGetAttribLocation(m_BackgroundProID
, "vPosition");
127 m_BackgroundColorID
= glGetAttribLocation(m_BackgroundProID
, "vColor");
131 m_SymbolProID
= OpenGLHelper::LoadShaders("symbolVertexShader", "symbolFragmentShader");
132 m_SymbolVertexID
= glGetAttribLocation(m_SymbolProID
, "vPosition");
133 m_SymbolMatrixID
= glGetUniformLocation(m_SymbolProID
, "MVP");
134 m_SymbolColorID
= glGetUniformLocation(m_SymbolProID
, "vColor");
135 m_SymbolShapeID
= glGetUniformLocation(m_SymbolProID
, "shape");
139 m_TextProID
= OpenGLHelper::LoadShaders("textVertexShader", "textFragmentShader");
140 m_TextMatrixID
= glGetUniformLocation(m_TextProID
, "MVP");
141 m_TextVertexID
= glGetAttribLocation(m_TextProID
, "vPosition");
142 m_TextTexCoordID
= glGetAttribLocation(m_TextProID
, "texCoord");
143 m_TextTexID
= glGetUniformLocation(m_TextProID
, "TextTex");
146 glGenBuffers(1, &m_RenderVertexBuf
);
147 glBindBuffer(GL_ARRAY_BUFFER
, m_RenderVertexBuf
);
148 glBufferData(GL_ARRAY_BUFFER
, sizeof(squareVertices
), squareVertices
, GL_STATIC_DRAW
);
149 glBindBuffer(GL_ARRAY_BUFFER
, 0);
151 glGenBuffers(1, &m_RenderTexCoordBuf
);
152 glBindBuffer(GL_ARRAY_BUFFER
, m_RenderTexCoordBuf
);
153 glBufferData(GL_ARRAY_BUFFER
, sizeof(coordReverseVertices
), coordReverseVertices
, GL_STATIC_DRAW
);
154 glBindBuffer(GL_ARRAY_BUFFER
, 0);
156 glGenBuffers(1, &m_TextTexCoordBuf
);
157 glBindBuffer(GL_ARRAY_BUFFER
, m_TextTexCoordBuf
);
158 glBufferData(GL_ARRAY_BUFFER
, sizeof(texCoords
), texCoords
, GL_STATIC_DRAW
);
159 glBindBuffer(GL_ARRAY_BUFFER
, 0);
161 glEnable(GL_LIGHTING
);
162 GLfloat
const light_direction
[] = { 0.0 , 0.0 , 1.0 };
163 GLfloat
const materialDiffuse
[] = { 1.0 , 1.0 , 1.0 , 1.0};
164 glLightfv(GL_LIGHT0
, GL_SPOT_DIRECTION
, light_direction
);
165 glMaterialfv(GL_FRONT
,GL_DIFFUSE
,materialDiffuse
);
167 glEnable(GL_NORMALIZE
);
172 int OpenGLRender::SetLine2DShapePoint(float x
, float y
, int listLength
)
174 if (m_Line2DPointList
.empty())
176 m_Line2DPointList
.reserve(listLength
*3);
178 m_Line2DPointList
.push_back(x
);
179 m_Line2DPointList
.push_back(y
);
180 m_Line2DPointList
.push_back(m_fZStep
);
182 if (m_Line2DPointList
.size() == size_t(listLength
* 3))
184 m_Line2DShapePointList
.push_back(m_Line2DPointList
);
185 m_Line2DPointList
.clear();
190 int OpenGLRender::RenderLine2FBO()
193 glLineWidth(m_fLineWidth
);
194 PosVecf3
const trans
= {0.0f
, 0.0f
, 0.0f
};
195 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
196 PosVecf3
const scale
= {1.0f
, 1.0f
, 1.0f
};
197 MoveModelf(trans
, angle
, scale
);
198 m_MVP
= m_Projection
* m_View
* m_Model
;
199 for (auto const& pointList
: m_Line2DShapePointList
)
202 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
204 glBufferData(GL_ARRAY_BUFFER
, pointList
.size() * sizeof(float), &pointList
[0], GL_STATIC_DRAW
);
207 glUseProgram(m_CommonProID
);
210 glUniform4fv(m_2DColorID
, 1, &m_2DColor
[0]);
212 glUniformMatrix4fv(m_MatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
215 // 1rst attribute buffer : vertices
217 glVertexAttribPointer(
221 GL_FALSE
, // normalized?
223 nullptr // array buffer offset
225 glEnableVertexAttribArray(m_2DVertexID
);
226 glDrawArrays(GL_LINE_STRIP
, 0, pointList
.size()/3); // 12*3 indices starting at 0 -> 12 triangles
229 glDisableVertexAttribArray(m_2DVertexID
);
232 m_Line2DShapePointList
.clear();
234 CHECK_GL_FRAME_BUFFER_STATUS();
239 #if DEBUG_POSITIONING
240 void OpenGLRender::renderDebug()
244 GLfloat vertices
[4][3] = {
250 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
252 glBufferData(GL_ARRAY_BUFFER
, sizeof(vertices
), vertices
, GL_STATIC_DRAW
);
254 glUseProgram(m_DebugProID
);
256 glVertexAttribPointer(m_DebugVertexID
, 3, GL_FLOAT
, GL_FALSE
, 0, (void*)0);
258 glEnableVertexAttribArray(m_DebugVertexID
);
260 glDrawArrays(GL_LINE_STRIP
, 0, 3);
262 glDisableVertexAttribArray(m_DebugVertexID
);
268 void OpenGLRender::prepareToRender()
270 glViewport(0, 0, m_iWidth
, m_iHeight
);
274 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
278 int OpenGLRender::MoveModelf(const PosVecf3
& trans
, const PosVecf3
& angle
, const PosVecf3
& scale
)
280 glm::mat4 aTranslationMatrix
= glm::translate(glm::vec3(trans
.x
, trans
.y
, trans
.z
));
281 glm::mat4 aScaleMatrix
= glm::scale(glm::vec3(scale
.x
, scale
.y
, scale
.z
));
282 glm::mat4 aRotationMatrix
= glm::eulerAngleYXZ(angle
.y
, angle
.x
, angle
.z
);
283 m_Model
= aTranslationMatrix
* aRotationMatrix
* aScaleMatrix
;
287 void OpenGLRender::Release()
289 glDeleteBuffers(1, &m_VertexBuffer
);
290 glDeleteBuffers(1, &m_ColorBuffer
);
291 glDeleteBuffers(1, &m_TextTexCoordBuf
);
292 glDeleteProgram(m_CommonProID
);
293 glDeleteProgram(m_TextProID
);
294 glDeleteProgram(m_BackgroundProID
);
295 glDeleteProgram(m_SymbolProID
);
298 OpenGLRender::OpenGLRender()
301 , m_Model(glm::mat4(1.0f
))
305 , m_RenderVertexBuf(0)
306 , m_RenderTexCoordBuf(0)
307 , m_fLineWidth(0.001f
)
308 , m_2DColor(glm::vec4(1.0, 0.0, 0.0, 1.0))
316 , m_TextTexCoordID(0)
317 , m_TextTexCoordBuf(0)
319 , m_BackgroundProID(0)
320 , m_BackgroundMatrixID(0)
321 , m_BackgroundVertexID(0)
322 , m_BackgroundColorID(0)
324 , m_SymbolVertexID(0)
325 , m_SymbolMatrixID(0)
329 //TODO: moggi: use STL
330 for (float & i
: m_BackgroundColor
)
336 OpenGLRender::~OpenGLRender()
341 // TODO: moggi: that screws up FBO if called after buffers have been created!!!!
342 void OpenGLRender::SetSize(int width
, int height
)
348 void OpenGLRender::SetSizePixel(int width
, int height
)
350 m_Projection
= glm::ortho(0.f
, float(m_iWidth
), 0.f
, float(m_iHeight
), -4.f
, 3.f
);
351 m_Projection
= m_Projection
* glm::scale(glm::vec3(static_cast<float>(width
) / m_iWidth
, -static_cast<float>(height
) / m_iHeight
, 1.0f
));
353 m_View
= glm::lookAt(glm::vec3(0,m_iHeight
,1),
354 glm::vec3(0,m_iHeight
,0),
358 void OpenGLRender::SetLine2DColor(sal_uInt8 r
, sal_uInt8 g
, sal_uInt8 b
, sal_uInt8 nAlpha
)
360 m_2DColor
= glm::vec4(static_cast<float>(r
) / 255.0f
, static_cast<float>(g
) / 255.0f
, static_cast<float>(b
) / 255.0f
, nAlpha
/255.f
);
363 void OpenGLRender::SetLine2DWidth(int width
)
365 m_fLineWidth
= std::max(static_cast<float>(width
), 0.001f
);
368 void OpenGLRender::SetColor(sal_uInt32 color
, sal_uInt8 nAlpha
)
370 sal_uInt8 r
= (color
& 0x00FF0000) >> 16;
371 sal_uInt8 g
= (color
& 0x0000FF00) >> 8;
372 sal_uInt8 b
= (color
& 0x000000FF);
373 m_2DColor
= glm::vec4(static_cast<float>(r
) / 255.0f
, static_cast<float>(g
) / 255.0f
, static_cast<float>(b
) / 255.0f
, nAlpha
/ 255.f
);
376 int OpenGLRender::Create2DCircle(int detail
)
383 m_Bubble2DCircle
.clear();
384 m_Bubble2DCircle
.reserve(2 * (detail
+ 3));
385 m_Bubble2DCircle
.push_back(0);
386 m_Bubble2DCircle
.push_back(0);
387 for(angle
= 2.0f
* GL_PI
; angle
> -(2.0f
* GL_PI
/ detail
); angle
-= (2.0f
* GL_PI
/ detail
))
389 m_Bubble2DCircle
.push_back(std::sin(angle
));
390 m_Bubble2DCircle
.push_back(std::cos(angle
));
395 int OpenGLRender::Bubble2DShapePoint(float x
, float y
, float directionX
, float directionY
)
397 //check whether to create the circle data
398 if (m_Bubble2DCircle
.empty())
403 Bubble2DPointList aBubble2DPointList
;
404 aBubble2DPointList
.xScale
= directionX
;
405 aBubble2DPointList
.yScale
= directionY
;
406 aBubble2DPointList
.x
= x
+ aBubble2DPointList
.xScale
/ 2;
407 aBubble2DPointList
.y
= y
+ aBubble2DPointList
.yScale
/ 2;
409 m_Bubble2DShapePointList
.push_back(aBubble2DPointList
);
413 int OpenGLRender::RenderBubble2FBO()
416 glm::vec4 edgeColor
= glm::vec4(0.0, 0.0, 0.0, 1.0);
417 for (auto const& pointList
: m_Bubble2DShapePointList
)
419 //move the circle to the pos, and scale using the xScale and Y scale
420 PosVecf3
const trans
= {pointList
.x
, pointList
.y
, m_fZStep
};
421 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
422 PosVecf3
const scale
= {pointList
.xScale
/ 2, pointList
.yScale
/ 2 , 1.0f
};
423 MoveModelf(trans
, angle
, scale
);
424 m_MVP
= m_Projection
* m_View
* m_Model
;
427 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
428 if (m_Bubble2DCircle
.empty())
432 glBufferData(GL_ARRAY_BUFFER
, m_Bubble2DCircle
.size() * sizeof(GLfloat
), &m_Bubble2DCircle
[0], GL_STATIC_DRAW
);
434 glUseProgram(m_CommonProID
);
436 glUniform4fv(m_2DColorID
, 1, &m_2DColor
[0]);
438 glUniformMatrix4fv(m_MatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
439 // 1rst attribute buffer : vertices
440 glEnableVertexAttribArray(m_2DVertexID
);
441 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
442 glVertexAttribPointer(
443 m_2DVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
446 GL_FALSE
, // normalized?
448 nullptr // array buffer offset
450 glDrawArrays(GL_TRIANGLE_FAN
, 0, m_Bubble2DCircle
.size() / 2);
451 glDisableVertexAttribArray(m_2DVertexID
);
453 glBindBuffer(GL_ARRAY_BUFFER
, 0);
456 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
457 glBufferData(GL_ARRAY_BUFFER
, m_Bubble2DCircle
.size() * sizeof(GLfloat
) -2 , &m_Bubble2DCircle
[2], GL_STATIC_DRAW
);
458 glUseProgram(m_CommonProID
);
459 glUniform4fv(m_2DColorID
, 1, &edgeColor
[0]);
460 glUniformMatrix4fv(m_MatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
461 glEnableVertexAttribArray(m_2DVertexID
);
462 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
463 glVertexAttribPointer(
464 m_2DVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
467 GL_FALSE
, // normalized?
469 nullptr // array buffer offset
471 glDrawArrays(GL_LINE_STRIP
, 0, (m_Bubble2DCircle
.size() * sizeof(GLfloat
) -2) / sizeof(float) / 2);
472 glDisableVertexAttribArray(m_2DVertexID
);
474 glBindBuffer(GL_ARRAY_BUFFER
, 0);
475 glLineWidth(m_fLineWidth
);
477 m_Bubble2DShapePointList
.clear();
478 //if use MSAA, we should copy the data to the FBO texture
479 GLenum fbResult
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
480 if( fbResult
!= GL_FRAMEBUFFER_COMPLETE
)
482 SAL_WARN("chart2.opengl", "error");
490 int OpenGLRender::RectangleShapePoint(float x
, float y
, float directionX
, float directionY
)
492 RectanglePointList aRectangle
;
494 aRectangle
.points
[0] = x
;
495 aRectangle
.points
[1] = y
;
496 aRectangle
.points
[2] = m_fZStep
;
497 aRectangle
.points
[3] = x
+ directionX
;
498 aRectangle
.points
[4] = y
;
499 aRectangle
.points
[5] = m_fZStep
;
500 aRectangle
.points
[6] = x
+ directionX
;
501 aRectangle
.points
[7] = y
+ directionY
;
502 aRectangle
.points
[8] = m_fZStep
;
503 aRectangle
.points
[9] = x
;
504 aRectangle
.points
[10] = y
+ directionY
;
505 aRectangle
.points
[11] = m_fZStep
;
507 m_RectangleShapePointList
.push_back(aRectangle
);
511 int OpenGLRender::RenderRectangleShape(bool bBorder
, bool bFill
)
513 for (auto const& pointList
: m_RectangleShapePointList
)
515 //move the circle to the pos, and scale using the xScale and Y scale
517 PosVecf3
const trans
= {0, 0, 0};
518 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
519 PosVecf3
const scale
= {1, 1, 1.0f
};
520 MoveModelf(trans
, angle
, scale
);
521 m_MVP
= m_Projection
* m_View
* m_Model
;
526 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
527 glBufferData(GL_ARRAY_BUFFER
, sizeof(pointList
.points
), pointList
.points
, GL_STATIC_DRAW
);
529 glBindBuffer(GL_ARRAY_BUFFER
, m_ColorBuffer
);
530 glBufferData(GL_ARRAY_BUFFER
, sizeof(m_BackgroundColor
), m_BackgroundColor
, GL_STATIC_DRAW
);
531 glUseProgram(m_BackgroundProID
);
533 glUniformMatrix4fv(m_BackgroundMatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
536 glEnableVertexAttribArray(m_BackgroundVertexID
);
537 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
538 glVertexAttribPointer(
539 m_BackgroundVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
542 GL_FALSE
, // normalized?
544 nullptr // array buffer offset
547 // 2nd attribute buffer : color
548 glEnableVertexAttribArray(m_BackgroundColorID
);
549 glBindBuffer(GL_ARRAY_BUFFER
, m_ColorBuffer
);
550 glVertexAttribPointer(
551 m_BackgroundColorID
, // attribute. No particular reason for 0, but must match the layout in the shader.
554 GL_FALSE
, // normalized?
556 nullptr // array buffer offset
558 //TODO: moggi: get rid of GL_QUADS
559 glDrawArrays(GL_QUADS
, 0, 4);
560 glDisableVertexAttribArray(m_BackgroundVertexID
);
561 glDisableVertexAttribArray(m_BackgroundColorID
);
567 PosVecf3
const trans
= {0.0, 0.0, Z_STEP
};
568 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
569 PosVecf3
const scale
= {1, 1, 1.0f
};
570 MoveModelf(trans
, angle
, scale
);
571 m_MVP
= m_Projection
* m_View
* m_Model
;
574 glUniformMatrix4fv(m_BackgroundMatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
576 SetBackGroundColor(COL_BLACK
, COL_BLACK
, css::drawing::FillStyle_SOLID
);
578 glBindBuffer(GL_ARRAY_BUFFER
, m_ColorBuffer
);
579 glBufferData(GL_ARRAY_BUFFER
, sizeof(m_BackgroundColor
), m_BackgroundColor
, GL_STATIC_DRAW
);
580 // 1rst attribute buffer : vertices
581 glEnableVertexAttribArray(m_BackgroundVertexID
);
582 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
583 glVertexAttribPointer(
584 m_BackgroundVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
587 GL_FALSE
, // normalized?
589 nullptr // array buffer offset
592 // 2nd attribute buffer : color
593 glEnableVertexAttribArray(m_BackgroundColorID
);
594 glBindBuffer(GL_ARRAY_BUFFER
, m_ColorBuffer
);
595 glVertexAttribPointer(
596 m_BackgroundColorID
, // attribute. No particular reason for 0, but must match the layout in the shader.
599 GL_FALSE
, // normalized?
601 nullptr // array buffer offset
603 glDrawArrays(GL_LINE_LOOP
, 0, 4);
604 glDisableVertexAttribArray(m_BackgroundVertexID
);
605 glDisableVertexAttribArray(m_BackgroundColorID
);
607 glDisableVertexAttribArray(m_BackgroundVertexID
);
608 glDisableVertexAttribArray(m_BackgroundColorID
);
610 glBindBuffer(GL_ARRAY_BUFFER
, 0);
612 m_RectangleShapePointList
.clear();
620 int OpenGLRender::CreateTextTexture(const BitmapEx
& rBitmapEx
, const awt::Size
& aSize
, long rotation
,
621 const drawing::HomogenMatrix3
& rTrans
)
623 #if DEBUG_PNG // debug PNG writing
625 OUString aName
= OUString( "file:///home/moggi/Documents/work/text" ) + OUString::number( nIdx
++ ) + ".png";
627 vcl::PNGWriter
aWriter( rBitmapEx
);
628 SvFileStream
sOutput( aName
, StreamMode::WRITE
);
629 aWriter
.Write( sOutput
);
632 SAL_WARN("chart2.opengl", "Error writing png to " << aName
);
636 boost::shared_array
<sal_uInt8
> bitmapBuf(new sal_uInt8
[4 * rBitmapEx
.GetSizePixel().Width() * rBitmapEx
.GetSizePixel().Height()]);
638 OpenGLHelper::ConvertBitmapExToRGBATextureBuffer(rBitmapEx
, bitmapBuf
.get());
640 return CreateTextTexture(bitmapBuf
, rBitmapEx
.GetSizePixel(),
641 aSize
, rotation
, rTrans
);
644 int OpenGLRender::CreateTextTexture(const boost::shared_array
<sal_uInt8
> &rPixels
,
645 const ::Size
&aPixelSize
,
646 const awt::Size
& aSize
,
648 const drawing::HomogenMatrix3
& rTrans
)
650 long bmpWidth
= aPixelSize
.Width();
651 long bmpHeight
= aPixelSize
.Height();
654 aTextInfo
.rotation
= -static_cast<double>(rotation
) / 360.0 * 2* GL_PI
;
655 aTextInfo
.vertex
[0] = -aSize
.Width
/ 2;
656 aTextInfo
.vertex
[1] = -aSize
.Height
/ 2;
657 aTextInfo
.vertex
[2] = m_fZStep
;
659 aTextInfo
.vertex
[3] = aSize
.Width
/ 2;
660 aTextInfo
.vertex
[4] = -aSize
.Height
/ 2;
661 aTextInfo
.vertex
[5] = m_fZStep
;
663 aTextInfo
.vertex
[6] = aSize
.Width
/ 2;
664 aTextInfo
.vertex
[7] = aSize
.Height
/ 2;
665 aTextInfo
.vertex
[8] = m_fZStep
;
667 aTextInfo
.vertex
[9] = -aSize
.Width
/ 2;
668 aTextInfo
.vertex
[10] = aSize
.Height
/ 2;
669 aTextInfo
.vertex
[11] = m_fZStep
;
670 aTextInfo
.nDx
= (rTrans
.Line1
.Column3
+ aSize
.Width
/ 2 ) - bmpWidth
/2;
671 aTextInfo
.nDy
= (rTrans
.Line2
.Column3
+ aSize
.Height
/ 2 ) - bmpHeight
/2;
674 glGenTextures(1, &aTextInfo
.texture
);
676 glBindTexture(GL_TEXTURE_2D
, aTextInfo
.texture
);
678 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
680 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
682 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
684 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
686 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, bmpWidth
, bmpHeight
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, rPixels
.get());
688 glBindTexture(GL_TEXTURE_2D
, 0);
690 m_TextInfoVector
.push_back(aTextInfo
);
694 int OpenGLRender::RenderTextShape()
697 for (auto const& textInfo
: m_TextInfoVector
)
699 PosVecf3
const trans
= { textInfo
.nDx
, textInfo
.nDy
, 0};
700 PosVecf3
const angle
= {0.0f
, 0.0f
, float(textInfo
.rotation
)};
701 PosVecf3
const scale
= {1.0, 1.0, 1.0f
};
702 MoveModelf(trans
, angle
, scale
);
703 m_MVP
= m_Projection
* m_View
* m_Model
;
704 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
706 glBufferData(GL_ARRAY_BUFFER
, sizeof(textInfo
.vertex
), textInfo
.vertex
, GL_STATIC_DRAW
);
708 glUseProgram(m_TextProID
);
711 glUniformMatrix4fv(m_TextMatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
712 // 1rst attribute buffer : vertices
713 glEnableVertexAttribArray(m_TextVertexID
);
714 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
715 glVertexAttribPointer(
719 GL_FALSE
, // normalized?
721 nullptr // array buffer offset
725 glEnableVertexAttribArray(m_TextTexCoordID
);
726 glBindBuffer(GL_ARRAY_BUFFER
, m_TextTexCoordBuf
);
727 glVertexAttribPointer(
731 GL_FALSE
, // normalized?
733 nullptr // array buffer offset
737 glBindTexture(GL_TEXTURE_2D
, textInfo
.texture
);
739 glUniform1i(m_TextTexID
, 0);
741 //TODO: moggi: get rid fo GL_QUADS
742 glDrawArrays(GL_QUADS
, 0, 4);
744 glDisableVertexAttribArray(m_TextTexCoordID
);
746 glDisableVertexAttribArray(m_TextVertexID
);
748 glBindTexture(GL_TEXTURE_2D
, 0);
750 glDeleteTextures(1, &textInfo
.texture
);
753 m_TextInfoVector
.clear();
759 int OpenGLRender::SetArea2DShapePoint(float x
, float y
, int listLength
)
761 if (m_Area2DPointList
.empty())
763 m_Area2DPointList
.reserve(listLength
);
765 m_Area2DPointList
.push_back(x
);
766 m_Area2DPointList
.push_back(y
);
767 m_Area2DPointList
.push_back(m_fZStep
);
769 if (m_Area2DPointList
.size() == size_t(listLength
* 3))
771 m_Area2DShapePointList
.push_back(m_Area2DPointList
);
772 m_Area2DPointList
.clear();
780 bool checkCCW(const PointList
& rPoints
)
782 if(rPoints
.size() < 3)
786 for(size_t i
= 1; i
< rPoints
.size()/3; i
+= 3)
788 GLfloat x1
= rPoints
[(i
-1)*3];
789 GLfloat x2
= rPoints
[i
*3];
790 GLfloat y1
= rPoints
[(i
-1)*3 + 1];
791 GLfloat y2
= rPoints
[i
*3 + 1];
792 GLfloat prod
= (x2
-x1
)*(y2
+y1
);
802 int OpenGLRender::RenderArea2DShape()
806 glDisable(GL_MULTISAMPLE
);
807 PosVecf3
const trans
= {0.0f
, 0.0f
, 0.0f
};
808 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
809 PosVecf3
const scale
= {1.0f
, 1.0f
, 1.0f
};
810 MoveModelf(trans
, angle
, scale
);
811 m_MVP
= m_Projection
* m_View
* m_Model
;
812 for (auto const& pointList
: m_Area2DShapePointList
)
814 bool bIsCCW
= checkCCW(pointList
); // is it counter clockwise (CCW) or clockwise (CW)
818 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
819 glBufferData(GL_ARRAY_BUFFER
, pointList
.size() * sizeof(float), &pointList
[0], GL_STATIC_DRAW
);
821 glUseProgram(m_CommonProID
);
823 glUniform4fv(m_2DColorID
, 1, &m_2DColor
[0]);
825 glUniformMatrix4fv(m_MatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
827 // 1rst attribute buffer : vertices
828 glEnableVertexAttribArray(m_2DVertexID
);
829 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
830 glVertexAttribPointer(
831 m_2DVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
834 GL_FALSE
, // normalized?
836 nullptr // array buffer offset
838 // TODO: moggi: remove deprecated GL_POLYGON
839 glDrawArrays(GL_POLYGON
, 0, pointList
.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
840 glDisableVertexAttribArray(m_2DVertexID
);
845 m_Area2DShapePointList
.clear();
846 glEnable(GL_MULTISAMPLE
);
854 void OpenGLRender::SetBackGroundColor(::Color color1
, ::Color color2
, css::drawing::FillStyle fillStyle
)
856 sal_uInt8 r
= color1
.GetRed();
857 sal_uInt8 g
= color1
.GetGreen();
858 sal_uInt8 b
= color1
.GetBlue();
860 m_BackgroundColor
[0] = static_cast<float>(r
) / 255.0f
;
861 m_BackgroundColor
[1] = static_cast<float>(g
) / 255.0f
;
862 m_BackgroundColor
[2] = static_cast<float>(b
) / 255.0f
;
863 m_BackgroundColor
[3] = fillStyle
!= css::drawing::FillStyle_NONE
? 1.0 : 0.0;
865 m_BackgroundColor
[4] = static_cast<float>(r
) / 255.0f
;
866 m_BackgroundColor
[5] = static_cast<float>(g
) / 255.0f
;
867 m_BackgroundColor
[6] = static_cast<float>(b
) / 255.0f
;
868 m_BackgroundColor
[7] = fillStyle
!= css::drawing::FillStyle_NONE
? 1.0 : 0.0;
871 g
= color2
.GetGreen();
872 b
= color2
.GetBlue();
874 m_BackgroundColor
[8] = static_cast<float>(r
) / 255.0f
;
875 m_BackgroundColor
[9] = static_cast<float>(g
) / 255.0f
;
876 m_BackgroundColor
[10] = static_cast<float>(b
) / 255.0f
;
877 m_BackgroundColor
[11] = fillStyle
!= css::drawing::FillStyle_NONE
? 1.0 : 0.0;
879 m_BackgroundColor
[12] = static_cast<float>(r
) / 255.0f
;
880 m_BackgroundColor
[13] = static_cast<float>(g
) / 255.0f
;
881 m_BackgroundColor
[14] = static_cast<float>(b
) / 255.0f
;
882 m_BackgroundColor
[15] = fillStyle
!= css::drawing::FillStyle_NONE
? 1.0 : 0.0;
883 SAL_INFO("chart2.opengl", "color1 = " << sal_uInt32(color1
) << ", color2 = " << sal_uInt32(color2
));
887 void OpenGLRender::SetChartTransparencyGradient(long transparencyGradient
)
889 if (transparencyGradient
== 1)
891 m_BackgroundColor
[11] = 0.0;
892 m_BackgroundColor
[15] = 0.0;
896 void OpenGLRender::GeneratePieSegment2D(double fInnerRadius
, double fOutterRadius
, double nAngleStart
, double nAngleWidth
)
898 double nAngleStep
= 1;
899 PointList aPointList
;
900 // TODO: moggi: GL_TRIANGLE_FAN seems not to work
901 const bool bInnerRadiusNotZero
= true; //!rtl::math::approxEqual(0.0, fInnerRadius);
902 size_t nVectorSize
= 3*(nAngleWidth
/nAngleStep
);
903 if(bInnerRadiusNotZero
)
907 aPointList
.reserve(nVectorSize
);
908 // if inner radius = 0 generate a normal pie segment (triangle fan)
909 // if inner radius != 0 generate a pie segment - inner pie (triangle strip)
910 if(!bInnerRadiusNotZero
)
912 aPointList
.push_back(0);
913 aPointList
.push_back(0);
914 aPointList
.push_back(m_fZStep
);
916 for(double nAngle
= nAngleStart
; nAngle
<= nAngleStart
+ nAngleWidth
; nAngle
+= nAngleStep
)
918 float xVal
= sin(nAngle
/360*2*GL_PI
);
919 float yVal
= cos(nAngle
/360*2*GL_PI
);
920 aPointList
.push_back(fOutterRadius
* xVal
);
921 aPointList
.push_back(fOutterRadius
* yVal
);
922 aPointList
.push_back(m_fZStep
);
924 if(bInnerRadiusNotZero
)
926 aPointList
.push_back(fInnerRadius
* xVal
);
927 aPointList
.push_back(fInnerRadius
* yVal
);
928 aPointList
.push_back(m_fZStep
);
932 m_PieSegment2DShapePointList
.push_back(aPointList
);
935 int OpenGLRender::RenderPieSegment2DShape(float fSize
, float fPosX
, float fPosY
)
937 int listNum
= m_PieSegment2DShapePointList
.size();
938 PosVecf3
const trans
= {fPosX
, fPosY
, 0.0f
};
939 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
940 PosVecf3
const scale
= {fSize
, fSize
, 1.0f
};
941 MoveModelf(trans
, angle
, scale
);
942 m_MVP
= m_Projection
* m_View
* m_Model
;
944 for (int i
= 0; i
< listNum
; i
++)
946 PointList
&pointList
= m_PieSegment2DShapePointList
.back();
948 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
949 glBufferData(GL_ARRAY_BUFFER
, pointList
.size() * sizeof(float), &pointList
[0] , GL_STATIC_DRAW
);
951 glUseProgram(m_CommonProID
);
953 glUniform4fv(m_2DColorID
, 1, &m_2DColor
[0]);
955 glUniformMatrix4fv(m_MatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
957 // 1rst attribute buffer : vertices
958 glEnableVertexAttribArray(m_2DVertexID
);
959 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
960 glVertexAttribPointer(
961 m_2DVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
964 GL_FALSE
, // normalized?
966 nullptr // array buffer offset
968 glDrawArrays(GL_TRIANGLE_STRIP
, 0, pointList
.size() / 3); // 12*3 indices starting at 0 -> 12 triangles
969 glDisableVertexAttribArray(m_2DVertexID
);
971 m_PieSegment2DShapePointList
.pop_back();
981 int OpenGLRender::RenderSymbol2DShape(float x
, float y
, sal_Int32 nSymbol
)
987 PosVecf3
const trans
= {0.0, 0.0, 0.0};
988 PosVecf3
const angle
= {0.0f
, 0.0f
, 0.0f
};
989 PosVecf3
const scale
= {1.0, 1.0, 1.0f
};
990 MoveModelf(trans
, angle
, scale
);
991 m_MVP
= m_Projection
* m_View
* m_Model
;
993 float aPos
[3] = { x
, y
, m_fZStep
};
995 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
997 glBufferData(GL_ARRAY_BUFFER
, 3 * sizeof(float), aPos
, GL_STATIC_DRAW
);
1001 glUseProgram(m_SymbolProID
);
1004 glUniform4fv(m_SymbolColorID
, 1, &m_2DColor
[0]);
1005 glUniform1i(m_SymbolShapeID
, nSymbol
);
1008 glUniformMatrix4fv(m_SymbolMatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
1011 // 1rst attribute buffer : vertices
1012 glEnableVertexAttribArray(m_SymbolVertexID
);
1013 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
1014 glVertexAttribPointer(
1015 m_SymbolVertexID
, // attribute. No particular reason for 0, but must match the layout in the shader.
1018 GL_FALSE
, // normalized?
1020 nullptr // array buffer offset
1023 glDrawArrays(GL_POINTS
, 0, 1);
1025 glDisableVertexAttribArray(m_SymbolVertexID
);
1034 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */