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/.
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
;
47 #include <vcl/pngwrite.hxx>
50 #define GL_PI 3.14159f
54 static GLfloat squareVertices
[] = {
61 static GLfloat coordReverseVertices
[] = {
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 );\
77 GLfloat texCoords
[] = {
86 int OpenGLRender::InitOpenGL()
88 glEnable(GL_TEXTURE_2D
);
89 glDisable(GL_CULL_FACE
);
91 glPolygonMode(GL_FRONT_AND_BACK
, GL_FILL
);
93 glEnable(GL_DEPTH_TEST
);
94 // Accept fragment if it closer to the camera than the former one
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
);
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
);
106 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
108 glGenBuffers(1, &m_VertexBuffer
);
109 glGenBuffers(1, &m_ColorBuffer
);
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");
119 #if DEBUG_POSITIONING
120 m_DebugProID
= OpenGLHelper::LoadShaders("debugVertexShader", "debugFragmentShader");
121 m_DebugVertexID
= glGetAttribLocation(m_DebugProID
, "vPosition");
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");
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");
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");
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
);
168 glEnable(GL_NORMALIZE
);
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();
191 int OpenGLRender::RenderLine2FBO(int)
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();
205 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
207 glBufferData(GL_ARRAY_BUFFER
, pointList
.size() * sizeof(float), &pointList
[0], GL_STATIC_DRAW
);
210 glUseProgram(m_CommonProID
);
213 glUniform4fv(m_2DColorID
, 1, &m_2DColor
[0]);
215 glUniformMatrix4fv(m_MatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
218 // 1rst attribute buffer : vertices
220 glVertexAttribPointer(
224 GL_FALSE
, // normalized?
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
232 glDisableVertexAttribArray(m_2DVertexID
);
234 m_Line2DShapePointList
.pop_front();
237 CHECK_GL_FRAME_BUFFER_STATUS();
242 #if DEBUG_POSITIONING
243 void OpenGLRender::renderDebug()
247 GLfloat vertices
[4][3] = {
253 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
255 glBufferData(GL_ARRAY_BUFFER
, sizeof(vertices
), vertices
, GL_STATIC_DRAW
);
257 glUseProgram(m_DebugProID
);
259 glVertexAttribPointer(m_DebugVertexID
, 3, GL_FLOAT
, GL_FALSE
, 0, (void*)0);
261 glEnableVertexAttribArray(m_DebugVertexID
);
263 glDrawArrays(GL_LINE_STRIP
, 0, 3);
265 glDisableVertexAttribArray(m_DebugVertexID
);
271 void OpenGLRender::prepareToRender()
273 glViewport(0, 0, m_iWidth
, m_iHeight
);
277 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
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
;
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()
304 , m_Model(glm::mat4(1.0f
))
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))
319 , m_TextTexCoordID(0)
320 , m_TextTexCoordBuf(0)
322 , m_BackgroundProID(0)
323 , m_BackgroundMatrixID(0)
324 , m_BackgroundVertexID(0)
325 , m_BackgroundColorID(0)
327 , m_SymbolVertexID(0)
328 , m_SymbolMatrixID(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()
344 // TODO: moggi: that screws up FBO if called after buffers have been created!!!!
345 void OpenGLRender::SetSize(int width
, int 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),
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
)
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
));
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())
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
);
416 int OpenGLRender::RenderBubble2FBO(int)
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
;
432 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
433 if (m_Bubble2DCircle
.empty())
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.
451 GL_FALSE
, // normalized?
453 (void*)0 // array buffer offset
455 glDrawArrays(GL_TRIANGLE_FAN
, 0, m_Bubble2DCircle
.size() / 2);
456 glDisableVertexAttribArray(m_2DVertexID
);
458 glBindBuffer(GL_ARRAY_BUFFER
, 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.
472 GL_FALSE
, // normalized?
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
);
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");
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
);
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
;
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]);
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.
549 GL_FALSE
, // normalized?
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.
561 GL_FALSE
, // normalized?
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
);
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
;
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.
594 GL_FALSE
, // normalized?
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.
606 GL_FALSE
, // normalized?
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
);
617 glBindBuffer(GL_ARRAY_BUFFER
, 0);
618 m_RectangleShapePointList
.pop_front();
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);
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
658 OUString aName
= OUString( "file:///home/moggi/Documents/work/text" ) + OUString::number( nIdx
++ ) + ".png";
660 vcl::PNGWriter
aWriter( rBitmapEx
);
661 SvFileStream
sOutput( aName
, StreamMode::WRITE
);
662 aWriter
.Write( sOutput
);
665 SAL_WARN("chart2.opengl", "Error writing png to " << aName
);
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
,
680 const awt::Size
& aSize
,
682 const drawing::HomogenMatrix3
& rTrans
)
684 long bmpWidth
= aPixelSize
.Width();
685 long bmpHeight
= aPixelSize
.Height();
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;
708 glGenTextures(1, &aTextInfo
.texture
);
710 glBindTexture(GL_TEXTURE_2D
, aTextInfo
.texture
);
712 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP
);
714 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP
);
716 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
718 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
720 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, bmpWidth
, bmpHeight
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, rPixels
.get());
722 glBindTexture(GL_TEXTURE_2D
, 0);
724 m_TextInfoList
.push_back(aTextInfo
);
728 int OpenGLRender::RenderTextShape()
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
);
742 glBufferData(GL_ARRAY_BUFFER
, sizeof(textInfo
.vertex
), textInfo
.vertex
, GL_STATIC_DRAW
);
744 glUseProgram(m_TextProID
);
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(
755 GL_FALSE
, // normalized?
757 (void*)0 // array buffer offset
761 glEnableVertexAttribArray(m_TextTexCoordID
);
762 glBindBuffer(GL_ARRAY_BUFFER
, m_TextTexCoordBuf
);
763 glVertexAttribPointer(
767 GL_FALSE
, // normalized?
769 (void*)0 // array buffer offset
773 glBindTexture(GL_TEXTURE_2D
, textInfo
.texture
);
775 glUniform1i(m_TextTexID
, 0);
777 //TODO: moggi: get rid fo GL_QUADS
778 glDrawArrays(GL_QUADS
, 0, 4);
780 glDisableVertexAttribArray(m_TextTexCoordID
);
782 glDisableVertexAttribArray(m_TextVertexID
);
784 glBindTexture(GL_TEXTURE_2D
, 0);
786 glDeleteTextures(1, &textInfo
.texture
);
788 m_TextInfoList
.pop_front();
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();
816 bool checkCCW(const PointList
& rPoints
)
818 if(rPoints
.size() < 3)
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
);
838 int OpenGLRender::RenderArea2DShape()
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)
856 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
857 glBufferData(GL_ARRAY_BUFFER
, pointList
.size() * sizeof(float), &pointList
[0], GL_STATIC_DRAW
);
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.
872 GL_FALSE
, // normalized?
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
);
882 m_Area2DShapePointList
.pop_front();
884 glEnable(GL_MULTISAMPLE
);
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
)
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();
986 glBindBuffer(GL_ARRAY_BUFFER
, m_VertexBuffer
);
987 glBufferData(GL_ARRAY_BUFFER
, pointList
.size() * sizeof(float), &pointList
[0] , GL_STATIC_DRAW
);
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.
1002 GL_FALSE
, // normalized?
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
);
1009 m_PieSegment2DShapePointList
.pop_back();
1019 int OpenGLRender::RenderSymbol2DShape(float x
, float y
, float , float , sal_Int32 nSymbol
)
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
);
1035 glBufferData(GL_ARRAY_BUFFER
, 3 * sizeof(float), aPos
, GL_STATIC_DRAW
);
1039 glUseProgram(m_SymbolProID
);
1042 glUniform4fv(m_SymbolColorID
, 1, &m_2DColor
[0]);
1043 glUniform1i(m_SymbolShapeID
, nSymbol
);
1046 glUniformMatrix4fv(m_SymbolMatrixID
, 1, GL_FALSE
, &m_MVP
[0][0]);
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.
1056 GL_FALSE
, // normalized?
1058 (void*)0 // array buffer offset
1061 glDrawArrays(GL_POINTS
, 0, 1);
1063 glDisableVertexAttribArray(m_SymbolVertexID
);
1072 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */