sd a11y: fix dozen of missing mnemonics
[LibreOffice.git] / vcl / opengl / LineRenderUtils.cxx
blobe62d884b3b6ef2f7780563d72c1f6a5112f73c49
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/.
9 */
11 #include <opengl/LineRenderUtils.hxx>
13 namespace vcl
16 LineBuilder::LineBuilder(std::vector<Vertex>& rVertices, std::vector<GLuint>& rIndices,
17 Color nColor, GLfloat fTransparency,
18 GLfloat fLineWidth, bool bUseAA)
19 : mrVertices(rVertices)
20 , mrIndices(rIndices)
21 , mR(nColor.GetRed())
22 , mG(nColor.GetGreen())
23 , mB(nColor.GetBlue())
24 , mA((1.0f - fTransparency) * 255.0f)
25 , mfLineWidth(fLineWidth)
26 , mfLineWidthAndAA(bUseAA ? fLineWidth : -fLineWidth)
27 , mnInitialIndexSize(rIndices.size())
28 , mbIncomplete(false)
32 void LineBuilder::appendLineSegment(const glm::vec2& rPoint1, const glm::vec2& rNormal1, GLfloat aExtrusion1,
33 const glm::vec2& rPoint2, const glm::vec2& rNormal2, GLfloat aExtrusion2)
35 GLuint zero = mrVertices.size();
37 mrVertices.insert(mrVertices.end(), {
38 {rPoint1, glm::vec4{mR, mG, mB, mA}, glm::vec4{-rNormal1.x, -rNormal1.y, -aExtrusion1, mfLineWidthAndAA}},
39 {rPoint1, glm::vec4{mR, mG, mB, mA}, glm::vec4{ rNormal1.x, rNormal1.y, aExtrusion1, mfLineWidthAndAA}},
40 {rPoint2, glm::vec4{mR, mG, mB, mA}, glm::vec4{-rNormal2.x, -rNormal2.y, -aExtrusion2, mfLineWidthAndAA}},
41 {rPoint2, glm::vec4{mR, mG, mB, mA}, glm::vec4{ rNormal2.x, rNormal2.y, aExtrusion2, mfLineWidthAndAA}},
42 });
44 mrIndices.insert(mrIndices.end(), {
45 zero + 0, zero + 1, zero + 2,
46 zero + 2, zero + 1, zero + 3
47 });
51 void LineBuilder::appendLine(const glm::vec2& rPoint1, const glm::vec2& rPoint2)
53 glm::vec2 aLineVector = vcl::vertex::normalize(rPoint2 - rPoint1);
54 glm::vec2 aNormal = vcl::vertex::perpendicular(aLineVector);
56 appendLineSegment(rPoint1, aNormal, 1.0f,
57 rPoint2, aNormal, 1.0f);
60 void LineBuilder::appendAndConnectLinePoint(const glm::vec2& rPoint, const glm::vec2& aNormal, GLfloat aExtrusion)
62 GLuint zero = mrVertices.size();
64 mrVertices.insert(mrVertices.end(), {
65 {rPoint, glm::vec4{mR, mG, mB, mA}, glm::vec4{-aNormal.x, -aNormal.y, -aExtrusion, mfLineWidthAndAA}},
66 {rPoint, glm::vec4{mR, mG, mB, mA}, glm::vec4{ aNormal.x, aNormal.y, aExtrusion, mfLineWidthAndAA}},
67 });
69 if (mnInitialIndexSize == mrIndices.size())
71 mrIndices.insert(mrIndices.end(), {
72 zero + 0, zero + 1
73 });
74 mbIncomplete = true;
76 else
78 if (mbIncomplete)
80 mrIndices.insert(mrIndices.end(), {
81 zero + 0,
82 zero + 0, zero - 1, zero + 1
83 });
84 mbIncomplete = false;
86 else
88 mrIndices.insert(mrIndices.end(), {
89 zero - 2, zero - 1, zero + 0,
90 zero + 0, zero - 1, zero + 1
91 });
96 void LineBuilder::appendMiterJoint(glm::vec2 const& point, const glm::vec2& prevLineVector,
97 glm::vec2 const& nextLineVector)
99 // With miter join we calculate the extrusion vector by adding normals of
100 // previous and next line segment. The vector shows the way but we also
101 // need the length (otherwise the line will be deformed). Length factor is
102 // calculated as dot product of extrusion vector and one of the normals.
103 // The value we get is the inverse length (used in the shader):
104 // length = line_width / dot(extrusionVector, normal)
106 glm::vec2 normal(-prevLineVector.y, prevLineVector.x);
108 glm::vec2 tangent = vcl::vertex::normalize(nextLineVector + prevLineVector);
109 glm::vec2 extrusionVector(-tangent.y, tangent.x);
110 GLfloat length = glm::dot(extrusionVector, normal);
112 appendAndConnectLinePoint(point, extrusionVector, length);
115 void LineBuilder::appendBevelJoint(glm::vec2 const& point, const glm::vec2& prevLineVector,
116 const glm::vec2& nextLineVector)
118 // For bevel join we just add 2 additional vertices and use previous
119 // line segment normal and next line segment normal as extrusion vector.
120 // All the magic is done by the fact that we draw triangle strips, so we
121 // cover the joins correctly.
123 glm::vec2 prevNormal = glm::vec2(-prevLineVector.y, prevLineVector.x);
124 glm::vec2 nextNormal = glm::vec2(-nextLineVector.y, nextLineVector.x);
126 appendAndConnectLinePoint(point, prevNormal, 1.0f);
127 appendAndConnectLinePoint(point, nextNormal, 1.0f);
130 void LineBuilder::appendRoundJoint(glm::vec2 const& point, const glm::vec2& prevLineVector,
131 const glm::vec2& nextLineVector)
133 // For round join we do a similar thing as in bevel, we add more intermediate
134 // vertices and add normals to get extrusion vectors in the between the
135 // both normals.
137 // 3 additional extrusion vectors + normals are enough to make most
138 // line joins look round. Ideally the number of vectors could be
139 // calculated.
141 glm::vec2 prevNormal = glm::vec2(-prevLineVector.y, prevLineVector.x);
142 glm::vec2 nextNormal = glm::vec2(-nextLineVector.y, nextLineVector.x);
144 glm::vec2 middle = vcl::vertex::normalize(prevNormal + nextNormal);
145 glm::vec2 middleLeft = vcl::vertex::normalize(prevNormal + middle);
146 glm::vec2 middleRight = vcl::vertex::normalize(middle + nextNormal);
148 appendAndConnectLinePoint(point, prevNormal, 1.0f);
149 appendAndConnectLinePoint(point, middleLeft, 1.0f);
150 appendAndConnectLinePoint(point, middle, 1.0f);
151 appendAndConnectLinePoint(point, middleRight, 1.0f);
152 appendAndConnectLinePoint(point, nextNormal, 1.0f);
155 void LineBuilder::appendRoundLineCapVertices(const glm::vec2& rPoint1, const glm::vec2& rPoint2)
157 constexpr int nRoundCapIteration = 12;
159 glm::vec2 lineVector = vcl::vertex::normalize(rPoint2 - rPoint1);
160 glm::vec2 normal = glm::vec2(-lineVector.y, lineVector.x);
161 glm::vec2 previousRoundNormal = normal;
163 for (int nFactor = 1; nFactor <= nRoundCapIteration; nFactor++)
165 float angle = float(nFactor) * (M_PI / float(nRoundCapIteration));
166 glm::vec2 roundNormal(normal.x * glm::cos(angle) - normal.y * glm::sin(angle),
167 normal.x * glm::sin(angle) + normal.y * glm::cos(angle));
169 appendLineSegment(rPoint1, previousRoundNormal, 1.0f,
170 rPoint1, roundNormal, 1.0f);
171 previousRoundNormal = roundNormal;
175 void LineBuilder::appendSquareLineCapVertices(const glm::vec2& rPoint1, const glm::vec2& rPoint2)
177 glm::vec2 lineVector = vcl::vertex::normalize(rPoint2 - rPoint1);
178 glm::vec2 normal = glm::vec2(-lineVector.y, lineVector.x);
180 glm::vec2 extrudedPoint = rPoint1 + -lineVector * (mfLineWidth / 2.0f);
182 appendLineSegment(extrudedPoint, normal, 1.0f,
183 rPoint1, normal, 1.0f);
186 } // end vcl
188 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */