qopengltextureglyphcache.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopengltextureglyphcache.cpp
Switch to Source codePreprocessed file
LineSourceCount
1-
2-
3-
4-
5QBasicAtomicInt qopengltextureglyphcache_serial_number = { 1 };-
6-
7QOpenGLTextureGlyphCache::QOpenGLTextureGlyphCache(QFontEngine::GlyphFormat format, const QTransform &matrix)-
8 : QImageTextureGlyphCache(format, matrix)-
9 , m_textureResource(0)-
10 , pex(0)-
11 , m_blitProgram(0)-
12 , m_filterMode(Nearest)-
13 , m_serialNumber(qopengltextureglyphcache_serial_number.fetchAndAddRelaxed(1))-
14 , m_buffer(QOpenGLBuffer::VertexBuffer)-
15{-
16-
17-
18-
19 m_vertexCoordinateArray[0] = -1.0f;-
20 m_vertexCoordinateArray[1] = -1.0f;-
21 m_vertexCoordinateArray[2] = 1.0f;-
22 m_vertexCoordinateArray[3] = -1.0f;-
23 m_vertexCoordinateArray[4] = 1.0f;-
24 m_vertexCoordinateArray[5] = 1.0f;-
25 m_vertexCoordinateArray[6] = -1.0f;-
26 m_vertexCoordinateArray[7] = 1.0f;-
27-
28 m_textureCoordinateArray[0] = 0.0f;-
29 m_textureCoordinateArray[1] = 0.0f;-
30 m_textureCoordinateArray[2] = 1.0f;-
31 m_textureCoordinateArray[3] = 0.0f;-
32 m_textureCoordinateArray[4] = 1.0f;-
33 m_textureCoordinateArray[5] = 1.0f;-
34 m_textureCoordinateArray[6] = 0.0f;-
35 m_textureCoordinateArray[7] = 1.0f;-
36}
never executed: end of block
0
37-
38QOpenGLTextureGlyphCache::~QOpenGLTextureGlyphCache()-
39{-
40-
41-
42-
43 clear();-
44}
never executed: end of block
0
45-
46-
47static inline bool isCoreProfile()-
48{-
49 return
never executed: return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile;
QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile;
never executed: return QOpenGLContext::currentContext()->format().profile() == QSurfaceFormat::CoreProfile;
0
50}-
51-
52-
53void QOpenGLTextureGlyphCache::createTextureData(int width, int height)-
54{-
55 QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());-
56 if (ctx == 0
ctx == 0Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
57 QMessageLogger(__FILE__, 102, __PRETTY_FUNCTION__).warning("QOpenGLTextureGlyphCache::createTextureData: Called with no context");-
58 return;
never executed: return;
0
59 }-
60-
61-
62-
63-
64 if (ctx->d_func()->workaround_brokenFBOReadBack
ctx->d_func()-...kenFBOReadBackDescription
TRUEnever evaluated
FALSEnever evaluated
&& image().isNull()
image().isNull()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
65 QImageTextureGlyphCache::createTextureData(width, height);
never executed: QImageTextureGlyphCache::createTextureData(width, height);
0
66-
67-
68 if (width < 16
width < 16Description
TRUEnever evaluated
FALSEnever evaluated
)
0
69 width = 16;
never executed: width = 16;
0
70 if (height < 16
height < 16Description
TRUEnever evaluated
FALSEnever evaluated
)
0
71 height = 16;
never executed: height = 16;
0
72-
73 if (m_textureResource
m_textureResourceDescription
TRUEnever evaluated
FALSEnever evaluated
&& !m_textureResource->m_texture
!m_textureResource->m_textureDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
74 delete m_textureResource;-
75 m_textureResource = 0;-
76 }
never executed: end of block
0
77-
78 if (!m_textureResource
!m_textureResourceDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
79 m_textureResource = new QOpenGLGlyphTexture(ctx);
never executed: m_textureResource = new QOpenGLGlyphTexture(ctx);
0
80-
81 QOpenGLFunctions *funcs = ctx->functions();-
82 funcs->glGenTextures(1, &m_textureResource->m_texture);-
83 funcs->glBindTexture(0x0DE1, m_textureResource->m_texture);-
84-
85 m_textureResource->m_width = width;-
86 m_textureResource->m_height = height;-
87-
88 if (m_format == QFontEngine::Format_A32
m_format == QF...ne::Format_A32Description
TRUEnever evaluated
FALSEnever evaluated
|| m_format == QFontEngine::Format_ARGB
m_format == QF...e::Format_ARGBDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
89 QVarLengthArray<uchar> data(width * height * 4);-
90 for (int i = 0; i < data.size()
i < data.size()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i)
0
91 data[i] = 0;
never executed: data[i] = 0;
0
92 funcs->glTexImage2D(0x0DE1, 0, 0x1908, width, height, 0, 0x1908, 0x1401, &data[0]);-
93 }
never executed: end of block
else {
0
94 QVarLengthArray<uchar> data(width * height);-
95 for (int i = 0; i < data.size()
i < data.size()Description
TRUEnever evaluated
FALSEnever evaluated
; ++i)
0
96 data[i] = 0;
never executed: data[i] = 0;
0
97-
98 const GLint internalFormat = isCoreProfile()
isCoreProfile()Description
TRUEnever evaluated
FALSEnever evaluated
? 0x8229 : 0x1906;
0
99 const GLenum format = isCoreProfile()
isCoreProfile()Description
TRUEnever evaluated
FALSEnever evaluated
? 0x1903 : 0x1906;
0
100-
101-
102-
103-
104 funcs->glTexImage2D(0x0DE1, 0, internalFormat, width, height, 0, format, 0x1401, &data[0]);-
105 }
never executed: end of block
0
106-
107 funcs->glTexParameteri(0x0DE1, 0x2800, 0x2600);-
108 funcs->glTexParameteri(0x0DE1, 0x2801, 0x2600);-
109 funcs->glTexParameteri(0x0DE1, 0x2802, 0x812F);-
110 funcs->glTexParameteri(0x0DE1, 0x2803, 0x812F);-
111 m_filterMode = Nearest;-
112-
113 if (!m_buffer.isCreated()
!m_buffer.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
114 m_buffer.create();-
115 m_buffer.bind();-
116 static GLfloat buf[sizeof(m_vertexCoordinateArray) + sizeof(m_textureCoordinateArray)];-
117 memcpy(buf, m_vertexCoordinateArray, sizeof(m_vertexCoordinateArray));-
118 memcpy(buf + (sizeof(m_vertexCoordinateArray) / sizeof(GLfloat)),-
119 m_textureCoordinateArray,-
120 sizeof(m_textureCoordinateArray));-
121 m_buffer.allocate(buf, sizeof(buf));-
122 m_buffer.release();-
123 }
never executed: end of block
0
124-
125 if (!m_vao.isCreated()
!m_vao.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
126 m_vao.create();
never executed: m_vao.create();
0
127}
never executed: end of block
0
128-
129void QOpenGLTextureGlyphCache::setupVertexAttribs()-
130{-
131 m_buffer.bind();-
132 m_blitProgram->setAttributeBuffer(int(QT_VERTEX_COORDS_ATTR), 0x1406, 0, 2);-
133 m_blitProgram->setAttributeBuffer(int(QT_TEXTURE_COORDS_ATTR), 0x1406, sizeof(m_vertexCoordinateArray), 2);-
134 m_blitProgram->enableAttributeArray(int(QT_VERTEX_COORDS_ATTR));-
135 m_blitProgram->enableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));-
136 m_buffer.release();-
137}
never executed: end of block
0
138-
139static void load_glyph_image_to_texture(QOpenGLContext *ctx,-
140 QImage &img,-
141 GLuint texture,-
142 int tx, int ty)-
143{-
144 QOpenGLFunctions *funcs = ctx->functions();-
145-
146 const int imgWidth = img.width();-
147 const int imgHeight = img.height();-
148-
149 if (img.format() == QImage::Format_Mono
img.format() =...e::Format_MonoDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
150 img = img.convertToFormat(QImage::Format_Grayscale8);-
151 }
never executed: end of block
else if (img.depth() == 32
img.depth() == 32Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
152 if (img.format() == QImage::Format_RGB32
img.format() =...::Format_RGB32Description
TRUEnever evaluated
FALSEnever evaluated
0
153-
154-
155-
156-
157-
158 || (img.format() == QImage::Format_ARGB32_Premultiplied
img.format() =..._PremultipliedDescription
TRUEnever evaluated
FALSEnever evaluated
0
159 && ctx->isOpenGLES()
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
160-
161 ) {-
162 for (int y = 0; y < imgHeight
y < imgHeightDescription
TRUEnever evaluated
FALSEnever evaluated
; ++y) {
0
163 QRgb *src = (QRgb *) img.scanLine(y);-
164 for (int x = 0; x < imgWidth
x < imgWidthDescription
TRUEnever evaluated
FALSEnever evaluated
; ++x) {
0
165 int r = qRed(src[x]);-
166 int g = qGreen(src[x]);-
167 int b = qBlue(src[x]);-
168 int avg;-
169 if (img.format() == QImage::Format_RGB32
img.format() =...::Format_RGB32Description
TRUEnever evaluated
FALSEnever evaluated
)
0
170 avg = (r + g + b + 1) / 3;
never executed: avg = (r + g + b + 1) / 3;
0
171 else-
172 avg = qAlpha(src[x]);
never executed: avg = qAlpha(src[x]);
0
173-
174 src[x] = qRgba(r, g, b, avg);-
175-
176-
177 if (ctx->isOpenGLES()
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
178-
179 src[x] = ARGB2RGBA(src[x]);
never executed: src[x] = ARGB2RGBA(src[x]);
0
180 }
never executed: end of block
0
181 }
never executed: end of block
0
182 }
never executed: end of block
0
183 }
never executed: end of block
0
184-
185 funcs->glBindTexture(0x0DE1, texture);-
186 if (img.depth() == 32
img.depth() == 32Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
187-
188-
189-
190 GLenum fmt = ctx->isOpenGLES()
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
? 0x1908 : 0x80E1;
0
191-
192-
193-
194-
195-
196 funcs->glTexSubImage2D(0x0DE1, 0, tx, ty, imgWidth, imgHeight, fmt, 0x1401, img.constBits());-
197 }
never executed: end of block
else {
0
198-
199-
200-
201 const GLenum format = isCoreProfile()
isCoreProfile()Description
TRUEnever evaluated
FALSEnever evaluated
? 0x1903 : 0x1906;
0
202-
203-
204-
205 funcs->glTexSubImage2D(0x0DE1, 0, tx, ty, imgWidth, imgHeight, format, 0x1401, img.constBits());-
206 }
never executed: end of block
0
207}-
208-
209static void load_glyph_image_region_to_texture(QOpenGLContext *ctx,-
210 const QImage &srcImg,-
211 int x, int y,-
212 int w, int h,-
213 GLuint texture,-
214 int tx, int ty)-
215{-
216 ((!(x + w <= srcImg.width() && y + h <= srcImg.height())) ? qt_assert("x + w <= srcImg.width() && y + h <= srcImg.height()",__FILE__,261) : qt_noop());-
217-
218 QImage img;-
219 if (x != 0
x != 0Description
TRUEnever evaluated
FALSEnever evaluated
|| y != 0
y != 0Description
TRUEnever evaluated
FALSEnever evaluated
|| w != srcImg.width()
w != srcImg.width()Description
TRUEnever evaluated
FALSEnever evaluated
|| h != srcImg.height()
h != srcImg.height()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
220 img = srcImg.copy(x, y, w, h);
never executed: img = srcImg.copy(x, y, w, h);
0
221 else-
222 img = srcImg;
never executed: img = srcImg;
0
223-
224 load_glyph_image_to_texture(ctx, img, texture, tx, ty);-
225}
never executed: end of block
0
226-
227void QOpenGLTextureGlyphCache::resizeTextureData(int width, int height)-
228{-
229 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
230 if (ctx == 0
ctx == 0Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
231 QMessageLogger(__FILE__, 276, __PRETTY_FUNCTION__).warning("QOpenGLTextureGlyphCache::resizeTextureData: Called with no context");-
232 return;
never executed: return;
0
233 }-
234-
235 QOpenGLFunctions *funcs = ctx->functions();-
236 GLint oldFbo;-
237 funcs->glGetIntegerv(0x8CA6, &oldFbo);-
238-
239 int oldWidth = m_textureResource->m_width;-
240 int oldHeight = m_textureResource->m_height;-
241-
242-
243 if (width < 16
width < 16Description
TRUEnever evaluated
FALSEnever evaluated
)
0
244 width = 16;
never executed: width = 16;
0
245 if (height < 16
height < 16Description
TRUEnever evaluated
FALSEnever evaluated
)
0
246 height = 16;
never executed: height = 16;
0
247-
248 GLuint oldTexture = m_textureResource->m_texture;-
249 createTextureData(width, height);-
250-
251 if (ctx->d_func()->workaround_brokenFBOReadBack
ctx->d_func()-...kenFBOReadBackDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
252 QImageTextureGlyphCache::resizeTextureData(width, height);-
253 load_glyph_image_region_to_texture(ctx, image(), 0, 0, qMin(oldWidth, width), qMin(oldHeight, height),-
254 m_textureResource->m_texture, 0, 0);-
255 return;
never executed: return;
0
256 }-
257-
258-
259-
260-
261 funcs->glBindFramebuffer(0x8D40, m_textureResource->m_fbo);-
262-
263 GLuint tmp_texture;-
264 funcs->glGenTextures(1, &tmp_texture);-
265 funcs->glBindTexture(0x0DE1, tmp_texture);-
266 funcs->glTexImage2D(0x0DE1, 0, 0x1908, oldWidth, oldHeight, 0,-
267 0x1908, 0x1401, __null);-
268 funcs->glTexParameteri(0x0DE1, 0x2801, 0x2600);-
269 funcs->glTexParameteri(0x0DE1, 0x2800, 0x2600);-
270 funcs->glTexParameteri(0x0DE1, 0x2802, 0x812F);-
271 funcs->glTexParameteri(0x0DE1, 0x2803, 0x812F);-
272 m_filterMode = Nearest;-
273 funcs->glBindTexture(0x0DE1, 0);-
274 funcs->glFramebufferTexture2D(0x8D40, 0x8CE0,-
275 0x0DE1, tmp_texture, 0);-
276-
277 funcs->glActiveTexture(0x84C0 + GLuint(0));-
278 funcs->glBindTexture(0x0DE1, oldTexture);-
279-
280 if (pex != 0
pex != 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
281 pex->transferMode(BrushDrawingMode);
never executed: pex->transferMode(BrushDrawingMode);
0
282-
283 funcs->glDisable(0x0B90);-
284 funcs->glDisable(0x0B71);-
285 funcs->glDisable(0x0C11);-
286 funcs->glDisable(0x0BE2);-
287-
288 funcs->glViewport(0, 0, oldWidth, oldHeight);-
289-
290 QOpenGLShaderProgram *blitProgram = 0;-
291 if (pex == 0
pex == 0Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
292 if (m_blitProgram == 0
m_blitProgram == 0Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
293 m_blitProgram = new QOpenGLShaderProgram;-
294 const bool isCoreProfile = ctx->format().profile() == QSurfaceFormat::CoreProfile;-
295-
296 {-
297 QString source;-
298 source.append(QLatin1String(isCoreProfile ? qopenglslMainWithTexCoordsVertexShader_core : qopenglslMainWithTexCoordsVertexShader));-
299 source.append(QLatin1String(isCoreProfile ? qopenglslUntransformedPositionVertexShader_core : qopenglslUntransformedPositionVertexShader));-
300-
301 QOpenGLShader *vertexShader = new QOpenGLShader(QOpenGLShader::Vertex, m_blitProgram);-
302 vertexShader->compileSourceCode(source);-
303-
304 m_blitProgram->addShader(vertexShader);-
305 }-
306-
307 {-
308 QString source;-
309 source.append(QLatin1String(isCoreProfile ? qopenglslMainFragmentShader_core : qopenglslMainFragmentShader));-
310 source.append(QLatin1String(isCoreProfile ? qopenglslImageSrcFragmentShader_core : qopenglslImageSrcFragmentShader));-
311-
312 QOpenGLShader *fragmentShader = new QOpenGLShader(QOpenGLShader::Fragment, m_blitProgram);-
313 fragmentShader->compileSourceCode(source);-
314-
315 m_blitProgram->addShader(fragmentShader);-
316 }-
317-
318 m_blitProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);-
319 m_blitProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);-
320-
321 m_blitProgram->link();-
322-
323 if (m_vao.isCreated()
m_vao.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
324 m_vao.bind();-
325 setupVertexAttribs();-
326 }
never executed: end of block
0
327 }
never executed: end of block
0
328-
329 if (m_vao.isCreated()
m_vao.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
)
0
330 m_vao.bind();
never executed: m_vao.bind();
0
331 else-
332 setupVertexAttribs();
never executed: setupVertexAttribs();
0
333-
334 m_blitProgram->bind();-
335 blitProgram = m_blitProgram;-
336-
337 }
never executed: end of block
else {
0
338 pex->setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, m_vertexCoordinateArray);-
339 pex->setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, m_textureCoordinateArray);-
340-
341 pex->shaderManager->useBlitProgram();-
342 blitProgram = pex->shaderManager->blitProgram();-
343 }
never executed: end of block
0
344-
345 blitProgram->setUniformValue("imageTexture", GLuint(0));-
346-
347 funcs->glDrawArrays(0x0006, 0, 4);-
348-
349 funcs->glBindTexture(0x0DE1, m_textureResource->m_texture);-
350-
351 funcs->glCopyTexSubImage2D(0x0DE1, 0, 0, 0, 0, 0, oldWidth, oldHeight);-
352-
353 funcs->glFramebufferRenderbuffer(0x8D40, 0x8CE0,-
354 0x8D41, 0);-
355 funcs->glDeleteTextures(1, &tmp_texture);-
356 funcs->glDeleteTextures(1, &oldTexture);-
357-
358 funcs->glBindFramebuffer(0x8D40, (GLuint)oldFbo);-
359-
360 if (pex != 0
pex != 0Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
361 funcs->glViewport(0, 0, pex->width, pex->height);-
362 pex->updateClipScissorTest();-
363 }
never executed: end of block
else {
0
364 if (m_vao.isCreated()
m_vao.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
365 m_vao.release();-
366 }
never executed: end of block
else {
0
367 m_blitProgram->disableAttributeArray(int(QT_VERTEX_COORDS_ATTR));-
368 m_blitProgram->disableAttributeArray(int(QT_TEXTURE_COORDS_ATTR));-
369 }
never executed: end of block
0
370 }-
371}-
372-
373void QOpenGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph, QFixed subPixelPosition)-
374{-
375 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
376 if (ctx == 0
ctx == 0Description
TRUEnever evaluated
FALSEnever evaluated
) {
0
377 QMessageLogger(__FILE__, 422, __PRETTY_FUNCTION__).warning("QOpenGLTextureGlyphCache::fillTexture: Called with no context");-
378 return;
never executed: return;
0
379 }-
380-
381 if (ctx->d_func()->workaround_brokenFBOReadBack
ctx->d_func()-...kenFBOReadBackDescription
TRUEnever evaluated
FALSEnever evaluated
) {
0
382 QImageTextureGlyphCache::fillTexture(c, glyph, subPixelPosition);-
383 load_glyph_image_region_to_texture(ctx, image(), c.x, c.y, c.w, c.h, m_textureResource->m_texture, c.x, c.y);-
384 return;
never executed: return;
0
385 }-
386-
387 QImage mask = textureMapForGlyph(glyph, subPixelPosition);-
388 load_glyph_image_to_texture(ctx, mask, m_textureResource->m_texture, c.x, c.y);-
389}
never executed: end of block
0
390-
391int QOpenGLTextureGlyphCache::glyphPadding() const-
392{-
393 return
never executed: return 1;
1;
never executed: return 1;
0
394}-
395-
396int QOpenGLTextureGlyphCache::maxTextureWidth() const-
397{-
398 QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());-
399 if (ctx == 0
ctx == 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
400 return
never executed: return QImageTextureGlyphCache::maxTextureWidth();
QImageTextureGlyphCache::maxTextureWidth();
never executed: return QImageTextureGlyphCache::maxTextureWidth();
0
401 else-
402 return
never executed: return ctx->d_func()->maxTextureSize();
ctx->d_func()->maxTextureSize();
never executed: return ctx->d_func()->maxTextureSize();
0
403}-
404-
405int QOpenGLTextureGlyphCache::maxTextureHeight() const-
406{-
407 QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());-
408 if (ctx == 0
ctx == 0Description
TRUEnever evaluated
FALSEnever evaluated
)
0
409 return
never executed: return QImageTextureGlyphCache::maxTextureHeight();
QImageTextureGlyphCache::maxTextureHeight();
never executed: return QImageTextureGlyphCache::maxTextureHeight();
0
410-
411 if (ctx->d_func()->workaround_brokenTexSubImage
ctx->d_func()-...kenTexSubImageDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
412 return
never executed: return qMin(1024, ctx->d_func()->maxTextureSize());
qMin(1024, ctx->d_func()->maxTextureSize());
never executed: return qMin(1024, ctx->d_func()->maxTextureSize());
0
413 else-
414 return
never executed: return ctx->d_func()->maxTextureSize();
ctx->d_func()->maxTextureSize();
never executed: return ctx->d_func()->maxTextureSize();
0
415}-
416-
417void QOpenGLTextureGlyphCache::clear()-
418{-
419 if (m_textureResource
m_textureResourceDescription
TRUEnever evaluated
FALSEnever evaluated
)
0
420 m_textureResource->free();
never executed: m_textureResource->free();
0
421 m_textureResource = 0;-
422-
423 delete m_blitProgram;-
424 m_blitProgram = 0;-
425-
426 m_w = 0;-
427 m_h = 0;-
428 m_cx = 0;-
429 m_cy = 0;-
430 m_currentRowHeight = 0;-
431 coords.clear();-
432}
never executed: end of block
0
433-
434-
Switch to Source codePreprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9