58 #include "qvarlengtharray.h" |
58 #include "qvarlengtharray.h" |
59 #include <private/qpainter_p.h> |
59 #include <private/qpainter_p.h> |
60 #include <private/qglpixelbuffer_p.h> |
60 #include <private/qglpixelbuffer_p.h> |
61 #include <private/qbezier_p.h> |
61 #include <private/qbezier_p.h> |
62 #include <qglframebufferobject.h> |
62 #include <qglframebufferobject.h> |
|
63 #include <private/qstatictext_p.h> |
63 |
64 |
64 #include "private/qtessellator_p.h" |
65 #include "private/qtessellator_p.h" |
65 |
66 |
66 #include "util/fragmentprograms_p.h" |
67 #include "util/fragmentprograms_p.h" |
67 |
68 |
68 #ifdef Q_WS_QWS |
69 #ifdef Q_WS_QWS |
69 #include "private/qglwindowsurface_qws_p.h" |
70 #include "private/qglwindowsurface_qws_p.h" |
70 #include "qwsmanager_qws.h" |
71 #include "qwsmanager_qws.h" |
71 #include "private/qwsmanager_p.h" |
72 #include "private/qwsmanager_p.h" |
72 #endif |
|
73 |
|
74 #ifdef QT_OPENGL_ES_1_CL |
|
75 #include "qgl_cl_p.h" |
|
76 #endif |
73 #endif |
77 |
74 |
78 #define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context()); |
75 #define QGL_FUNC_CONTEXT QGLContext *ctx = const_cast<QGLContext *>(device->context()); |
79 |
76 |
80 #include <stdlib.h> |
77 #include <stdlib.h> |
778 void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset); |
776 void drawTiledImageAsPath(const QRectF &r, const QImage &img, qreal sx, qreal sy, const QPointF &offset); |
779 |
777 |
780 void drawOffscreenPath(const QPainterPath &path); |
778 void drawOffscreenPath(const QPainterPath &path); |
781 |
779 |
782 void composite(const QRectF &rect, const QPoint &maskOffset = QPoint()); |
780 void composite(const QRectF &rect, const QPoint &maskOffset = QPoint()); |
783 void composite(GLuint primitive, const q_vertexType *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint()); |
781 void composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset = QPoint()); |
784 |
782 |
785 bool createFragmentPrograms(); |
783 bool createFragmentPrograms(); |
786 void deleteFragmentPrograms(); |
784 void deleteFragmentPrograms(); |
787 void updateFragmentProgramData(int locations[]); |
785 void updateFragmentProgramData(int locations[]); |
788 |
786 |
1806 if (size > allocated - 8) { |
1809 if (size > allocated - 8) { |
1807 #else |
1810 #else |
1808 if (size > allocated - 12) { |
1811 if (size > allocated - 12) { |
1809 #endif |
1812 #endif |
1810 allocated = qMax(2*allocated, 512); |
1813 allocated = qMax(2*allocated, 512); |
1811 vertices = (q_vertexType *)realloc(vertices, allocated * sizeof(q_vertexType)); |
1814 vertices = (GLfloat *)realloc(vertices, allocated * sizeof(GLfloat)); |
1812 } |
1815 } |
1813 |
1816 |
1814 QGLTrapezoid t = toGLTrapezoid(trap); |
1817 QGLTrapezoid t = toGLTrapezoid(trap); |
1815 |
1818 |
1816 #ifndef QT_OPENGL_ES |
1819 #ifndef QT_OPENGL_ES |
1817 vertices[size++] = f2vt(t.topLeftX); |
1820 vertices[size++] = t.topLeftX; |
1818 vertices[size++] = f2vt(t.top); |
1821 vertices[size++] = t.top; |
1819 vertices[size++] = f2vt(t.topRightX); |
1822 vertices[size++] = t.topRightX; |
1820 vertices[size++] = f2vt(t.top); |
1823 vertices[size++] = t.top; |
1821 vertices[size++] = f2vt(t.bottomRightX); |
1824 vertices[size++] = t.bottomRightX; |
1822 vertices[size++] = f2vt(t.bottom); |
1825 vertices[size++] = t.bottom; |
1823 vertices[size++] = f2vt(t.bottomLeftX); |
1826 vertices[size++] = t.bottomLeftX; |
1824 vertices[size++] = f2vt(t.bottom); |
1827 vertices[size++] = t.bottom; |
1825 #else |
1828 #else |
1826 // First triangle |
1829 // First triangle |
1827 vertices[size++] = f2vt(t.topLeftX); |
1830 vertices[size++] = t.topLeftX; |
1828 vertices[size++] = f2vt(t.top); |
1831 vertices[size++] = t.top; |
1829 vertices[size++] = f2vt(t.topRightX); |
1832 vertices[size++] = t.topRightX; |
1830 vertices[size++] = f2vt(t.top); |
1833 vertices[size++] = t.top; |
1831 vertices[size++] = f2vt(t.bottomRightX); |
1834 vertices[size++] = t.bottomRightX; |
1832 vertices[size++] = f2vt(t.bottom); |
1835 vertices[size++] = t.bottom; |
1833 |
1836 |
1834 // Second triangle |
1837 // Second triangle |
1835 vertices[size++] = f2vt(t.bottomLeftX); |
1838 vertices[size++] = t.bottomLeftX; |
1836 vertices[size++] = f2vt(t.bottom); |
1839 vertices[size++] = t.bottom; |
1837 vertices[size++] = f2vt(t.topLeftX); |
1840 vertices[size++] = t.topLeftX; |
1838 vertices[size++] = f2vt(t.top); |
1841 vertices[size++] = t.top; |
1839 vertices[size++] = f2vt(t.bottomRightX); |
1842 vertices[size++] = t.bottomRightX; |
1840 vertices[size++] = f2vt(t.bottom); |
1843 vertices[size++] = t.bottom; |
1841 #endif |
1844 #endif |
1842 } |
1845 } |
1843 |
1846 |
1844 |
1847 |
1845 void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount, |
1848 void QOpenGLPaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount, |
1862 #endif |
1865 #endif |
1863 |
1866 |
1864 if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) { |
1867 if (use_fragment_programs && !(fast_style && has_fast_composition_mode)) { |
1865 composite(geometry_mode, tessellator.vertices, tessellator.size / 2); |
1868 composite(geometry_mode, tessellator.vertices, tessellator.size / 2); |
1866 } else { |
1869 } else { |
1867 glVertexPointer(2, q_vertexTypeEnum, 0, tessellator.vertices); |
1870 glVertexPointer(2, GL_FLOAT, 0, tessellator.vertices); |
1868 glEnableClientState(GL_VERTEX_ARRAY); |
1871 glEnableClientState(GL_VERTEX_ARRAY); |
1869 glDrawArrays(geometry_mode, 0, tessellator.size/2); |
1872 glDrawArrays(geometry_mode, 0, tessellator.size/2); |
1870 glDisableClientState(GL_VERTEX_ARRAY); |
1873 glDisableClientState(GL_VERTEX_ARRAY); |
1871 } |
1874 } |
1872 } |
1875 } |
2279 glDepthFunc(GL_ALWAYS); |
2284 glDepthFunc(GL_ALWAYS); |
2280 |
2285 |
2281 const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects(); |
2286 const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects(); |
2282 |
2287 |
2283 // rectangle count * 2 (triangles) * vertex count * component count (Z omitted) |
2288 // rectangle count * 2 (triangles) * vertex count * component count (Z omitted) |
2284 QDataBuffer<q_vertexType> clipVertex(rects.size()*2*3*2); |
2289 QDataBuffer<GLfloat> clipVertex(rects.size()*2*3*2); |
2285 for (int i = 0; i < rects.size(); ++i) { |
2290 for (int i = 0; i < rects.size(); ++i) { |
2286 q_vertexType x = i2vt(rects.at(i).left()); |
2291 GLfloat x = GLfloat(rects.at(i).left()); |
2287 q_vertexType w = i2vt(rects.at(i).width()); |
2292 GLfloat w = GLfloat(rects.at(i).width()); |
2288 q_vertexType h = i2vt(rects.at(i).height()); |
2293 GLfloat h = GLfloat(rects.at(i).height()); |
2289 q_vertexType y = i2vt(rects.at(i).top()); |
2294 GLfloat y = GLfloat(rects.at(i).top()); |
2290 |
2295 |
2291 // First triangle |
2296 // First triangle |
2292 clipVertex.add(x); |
2297 clipVertex.add(x); |
2293 clipVertex.add(y); |
2298 clipVertex.add(y); |
2294 |
2299 |
3136 |
3141 |
3137 QVector<QGLTrapezoid> trapezoids = generateTrapezoids(); |
3142 QVector<QGLTrapezoid> trapezoids = generateTrapezoids(); |
3138 |
3143 |
3139 // clear mask |
3144 // clear mask |
3140 glBlendFunc(GL_ZERO, GL_ZERO); // clear |
3145 glBlendFunc(GL_ZERO, GL_ZERO); // clear |
3141 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
3146 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
3142 glEnableClientState(GL_VERTEX_ARRAY); |
3147 glEnableClientState(GL_VERTEX_ARRAY); |
3143 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
3148 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
3144 glDisableClientState(GL_VERTEX_ARRAY); |
3149 glDisableClientState(GL_VERTEX_ARRAY); |
3145 |
3150 |
3146 glBlendFunc(GL_ONE, GL_ONE); // add mask |
3151 glBlendFunc(GL_ONE, GL_ONE); // add mask |
3343 |
3348 |
3344 QTransform translate(1, 0, 0, 1, -ellipseRect.center().x(), -ellipseRect.center().y()); |
3349 QTransform translate(1, 0, 0, 1, -ellipseRect.center().x(), -ellipseRect.center().y()); |
3345 QTransform gl_to_qt(1, 0, 0, -1, 0, offscreen->drawableSize().height()); |
3350 QTransform gl_to_qt(1, 0, 0, -1, 0, offscreen->drawableSize().height()); |
3346 QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate; |
3351 QTransform inv_matrix = gl_to_qt * matrix().inverted() * translate; |
3347 |
3352 |
3348 float m[3][4] = { { inv_matrix.m11(), inv_matrix.m12(), inv_matrix.m13() }, |
3353 float m[3][4] = { { float(inv_matrix.m11()), float(inv_matrix.m12()), float(inv_matrix.m13()) }, |
3349 { inv_matrix.m21(), inv_matrix.m22(), inv_matrix.m23() }, |
3354 { float(inv_matrix.m21()), float(inv_matrix.m22()), float(inv_matrix.m23()) }, |
3350 { inv_matrix.m31(), inv_matrix.m32(), inv_matrix.m33() } }; |
3355 { float(inv_matrix.m31()), float(inv_matrix.m32()), float(inv_matrix.m33()) } }; |
3351 |
3356 |
3352 QPoint offs(screen_rect.left() - rect.left(), (offscreen->drawableSize().height() - screen_rect.top()) |
3357 QPoint offs(screen_rect.left() - rect.left(), (offscreen->drawableSize().height() - screen_rect.top()) |
3353 - (offscreen->offscreenSize().height() - rect.top())); |
3358 - (offscreen->offscreenSize().height() - rect.top())); |
3354 |
3359 |
3355 // last component needs to be 1.0f to avoid Nvidia bug on linux |
3360 // last component needs to be 1.0f to avoid Nvidia bug on linux |
3356 float ellipse_offset[4] = { offs.x(), offs.y(), 0.0f, 1.0f }; |
3361 float ellipse_offset[4] = { float(offs.x()), float(offs.y()), 0.0f, 1.0f }; |
3357 |
3362 |
3358 GLfloat vertexArray[4 * 2]; |
3363 GLfloat vertexArray[4 * 2]; |
3359 qt_add_rect_to_array(rect, vertexArray); |
3364 qt_add_rect_to_array(rect, vertexArray); |
3360 |
3365 |
3361 glBlendFunc(GL_ONE, GL_ZERO); // set mask |
3366 glBlendFunc(GL_ONE, GL_ZERO); // set mask |
3367 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M2], m[2]); |
3372 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_INV_MATRIX_M2], m[2]); |
3368 |
3373 |
3369 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset); |
3374 glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, maskVariableLocations[VAR_ELLIPSE_OFFSET], ellipse_offset); |
3370 |
3375 |
3371 glEnableClientState(GL_VERTEX_ARRAY); |
3376 glEnableClientState(GL_VERTEX_ARRAY); |
3372 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
3377 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
3373 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
3378 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
3374 glDisableClientState(GL_VERTEX_ARRAY); |
3379 glDisableClientState(GL_VERTEX_ARRAY); |
3375 glDisable(GL_FRAGMENT_PROGRAM_ARB); |
3380 glDisable(GL_FRAGMENT_PROGRAM_ARB); |
3376 #endif |
3381 #endif |
3377 } |
3382 } |
3418 bool fast_style = current_style == Qt::LinearGradientPattern |
3423 bool fast_style = current_style == Qt::LinearGradientPattern |
3419 || current_style == Qt::SolidPattern; |
3424 || current_style == Qt::SolidPattern; |
3420 |
3425 |
3421 if (fast_style && has_fast_composition_mode) { |
3426 if (fast_style && has_fast_composition_mode) { |
3422 glEnableClientState(GL_VERTEX_ARRAY); |
3427 glEnableClientState(GL_VERTEX_ARRAY); |
3423 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
3428 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
3424 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
3429 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
3425 glDisableClientState(GL_VERTEX_ARRAY); |
3430 glDisableClientState(GL_VERTEX_ARRAY); |
3426 } else { |
3431 } else { |
3427 composite(r); |
3432 composite(r); |
3428 } |
3433 } |
3437 setGradientOps(cpen.brush(), r); |
3442 setGradientOps(cpen.brush(), r); |
3438 |
3443 |
3439 vertexArray[8] = vertexArray[0]; |
3444 vertexArray[8] = vertexArray[0]; |
3440 vertexArray[9] = vertexArray[1]; |
3445 vertexArray[9] = vertexArray[1]; |
3441 |
3446 |
3442 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
3447 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
3443 glEnableClientState(GL_VERTEX_ARRAY); |
3448 glEnableClientState(GL_VERTEX_ARRAY); |
3444 glDrawArrays(GL_LINE_STRIP, 0, 5); |
3449 glDrawArrays(GL_LINE_STRIP, 0, 5); |
3445 glDisableClientState(GL_VERTEX_ARRAY); |
3450 glDisableClientState(GL_VERTEX_ARRAY); |
3446 } else { |
3451 } else { |
3447 QPainterPath path; |
3452 QPainterPath path; |
3605 } |
3610 } |
3606 |
3611 |
3607 d->flushDrawQueue(); |
3612 d->flushDrawQueue(); |
3608 |
3613 |
3609 if (d->has_fast_pen) { |
3614 if (d->has_fast_pen) { |
3610 QVarLengthArray<q_vertexType> vertexArray(6 * pointCount); |
3615 QVarLengthArray<GLfloat> vertexArray(6 * pointCount); |
3611 |
3616 |
3612 glMatrixMode(GL_MODELVIEW); |
3617 glMatrixMode(GL_MODELVIEW); |
3613 glPushMatrix(); |
3618 glPushMatrix(); |
3614 glLoadIdentity(); |
3619 glLoadIdentity(); |
3615 |
3620 |
3616 int j = 0; |
3621 int j = 0; |
3617 for (int i = 0; i < pointCount; ++i) { |
3622 for (int i = 0; i < pointCount; ++i) { |
3618 QPointF mapped = d->matrix.map(points[i]); |
3623 QPointF mapped = d->matrix.map(points[i]); |
3619 |
3624 |
3620 qreal xf = qRound(mapped.x()); |
3625 GLfloat x = GLfloat(qRound(mapped.x())); |
3621 qreal yf = qRound(mapped.y()); |
3626 GLfloat y = GLfloat(qRound(mapped.y())); |
3622 |
|
3623 q_vertexType x = f2vt(xf); |
|
3624 q_vertexType y = f2vt(yf); |
|
3625 |
3627 |
3626 vertexArray[j++] = x; |
3628 vertexArray[j++] = x; |
3627 vertexArray[j++] = y - f2vt(0.5); |
3629 vertexArray[j++] = y - 0.5f; |
3628 |
3630 |
3629 vertexArray[j++] = x + f2vt(1.5); |
3631 vertexArray[j++] = x + 1.5f; |
3630 vertexArray[j++] = y + f2vt(1.0); |
3632 vertexArray[j++] = y + 1.0f; |
3631 |
3633 |
3632 vertexArray[j++] = x; |
3634 vertexArray[j++] = x; |
3633 vertexArray[j++] = y + f2vt(1.0); |
3635 vertexArray[j++] = y + 1.0f; |
3634 } |
3636 } |
3635 |
3637 |
3636 glEnableClientState(GL_VERTEX_ARRAY); |
3638 glEnableClientState(GL_VERTEX_ARRAY); |
3637 |
3639 |
3638 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData()); |
3640 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); |
3639 glDrawArrays(GL_TRIANGLES, 0, pointCount*3); |
3641 glDrawArrays(GL_TRIANGLES, 0, pointCount*3); |
3640 |
3642 |
3641 glDisableClientState(GL_VERTEX_ARRAY); |
3643 glDisableClientState(GL_VERTEX_ARRAY); |
3642 |
3644 |
3643 glPopMatrix(); |
3645 glPopMatrix(); |
3650 Q_ASSERT(sizeof(QPointF) == 16); |
3652 Q_ASSERT(sizeof(QPointF) == 16); |
3651 glVertexPointer(2, GL_DOUBLE, 0, vertexArray); |
3653 glVertexPointer(2, GL_DOUBLE, 0, vertexArray); |
3652 } |
3654 } |
3653 else { |
3655 else { |
3654 Q_ASSERT(sizeof(QPointF) == 8); |
3656 Q_ASSERT(sizeof(QPointF) == 8); |
3655 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
3657 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
3656 } |
3658 } |
3657 |
3659 |
3658 glEnableClientState(GL_VERTEX_ARRAY); |
3660 glEnableClientState(GL_VERTEX_ARRAY); |
3659 glDrawArrays(GL_POINTS, 0, pointCount); |
3661 glDrawArrays(GL_POINTS, 0, pointCount); |
3660 glDisableClientState(GL_VERTEX_ARRAY); |
3662 glDisableClientState(GL_VERTEX_ARRAY); |
3718 break; |
3720 break; |
3719 } |
3721 } |
3720 } |
3722 } |
3721 } |
3723 } |
3722 |
3724 |
3723 q_vertexType endCap = f2vt(d->cpen.capStyle() == Qt::FlatCap ? 0 : 0.5); |
3725 GLfloat endCap = d->cpen.capStyle() == Qt::FlatCap ? 0.0f : 0.5f; |
3724 if (useRects) { |
3726 if (useRects) { |
3725 QVarLengthArray<q_vertexType> vertexArray(12 * lineCount); |
3727 QVarLengthArray<GLfloat> vertexArray(12 * lineCount); |
3726 |
3728 |
3727 q_vertexType quad[8]; |
3729 GLfloat quad[8]; |
3728 for (int i = 0; i < lineCount; ++i) { |
3730 for (int i = 0; i < lineCount; ++i) { |
3729 q_vertexType x1 = f2vt(lines[i].x1()); |
3731 GLfloat x1 = lines[i].x1(); |
3730 q_vertexType x2 = f2vt(lines[i].x2()); |
3732 GLfloat x2 = lines[i].x2(); |
3731 q_vertexType y1 = f2vt(lines[i].y1()); |
3733 GLfloat y1 = lines[i].y1(); |
3732 q_vertexType y2 = f2vt(lines[i].y2()); |
3734 GLfloat y2 = lines[i].y2(); |
3733 |
3735 |
3734 if (x1 == x2) { |
3736 if (x1 == x2) { |
3735 if (y1 > y2) |
3737 if (y1 > y2) |
3736 qSwap(y1, y2); |
3738 qSwap(y1, y2); |
3737 |
3739 |
3738 quad[0] = x1 - f2vt(0.5); |
3740 quad[0] = x1 - 0.5f; |
3739 quad[1] = y1 - endCap; |
3741 quad[1] = y1 - endCap; |
3740 |
3742 |
3741 quad[2] = x1 + f2vt(0.5); |
3743 quad[2] = x1 + 0.5f; |
3742 quad[3] = y1 - endCap; |
3744 quad[3] = y1 - endCap; |
3743 |
3745 |
3744 quad[4] = x1 + f2vt(0.5); |
3746 quad[4] = x1 + 0.5f; |
3745 quad[5] = y2 + endCap; |
3747 quad[5] = y2 + endCap; |
3746 |
3748 |
3747 quad[6] = x1 - f2vt(0.5); |
3749 quad[6] = x1 - 0.5f; |
3748 quad[7] = y2 + endCap; |
3750 quad[7] = y2 + endCap; |
3749 } else { |
3751 } else { |
3750 if (x1 > x2) |
3752 if (x1 > x2) |
3751 qSwap(x1, x2); |
3753 qSwap(x1, x2); |
3752 |
3754 |
3753 quad[0] = x1 - endCap; |
3755 quad[0] = x1 - endCap; |
3754 quad[1] = y1 + f2vt(0.5); |
3756 quad[1] = y1 + 0.5f; |
3755 |
3757 |
3756 quad[2] = x1 - endCap; |
3758 quad[2] = x1 - endCap; |
3757 quad[3] = y1 - f2vt(0.5); |
3759 quad[3] = y1 - 0.5f; |
3758 |
3760 |
3759 quad[4] = x2 + endCap; |
3761 quad[4] = x2 + endCap; |
3760 quad[5] = y1 - f2vt(0.5); |
3762 quad[5] = y1 - 0.5f; |
3761 |
3763 |
3762 quad[6] = x2 + endCap; |
3764 quad[6] = x2 + endCap; |
3763 quad[7] = y1 + f2vt(0.5); |
3765 quad[7] = y1 + 0.5f; |
3764 } |
3766 } |
3765 |
3767 |
3766 addQuadAsTriangle(quad, &vertexArray[12*i]); |
3768 addQuadAsTriangle(quad, &vertexArray[12*i]); |
3767 } |
3769 } |
3768 |
3770 |
3769 glEnableClientState(GL_VERTEX_ARRAY); |
3771 glEnableClientState(GL_VERTEX_ARRAY); |
3770 |
3772 |
3771 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData()); |
3773 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); |
3772 glDrawArrays(GL_TRIANGLES, 0, lineCount*6); |
3774 glDrawArrays(GL_TRIANGLES, 0, lineCount*6); |
3773 |
3775 |
3774 glDisableClientState(GL_VERTEX_ARRAY); |
3776 glDisableClientState(GL_VERTEX_ARRAY); |
3775 } else { |
3777 } else { |
3776 QVarLengthArray<q_vertexType> vertexArray(4 * lineCount); |
3778 QVarLengthArray<GLfloat> vertexArray(4 * lineCount); |
3777 for (int i = 0; i < lineCount; ++i) { |
3779 for (int i = 0; i < lineCount; ++i) { |
3778 const QPointF a = lines[i].p1(); |
3780 const QPointF a = lines[i].p1(); |
3779 vertexArray[4*i] = f2vt(lines[i].x1()); |
3781 vertexArray[4*i] = lines[i].x1(); |
3780 vertexArray[4*i+1] = f2vt(lines[i].y1()); |
3782 vertexArray[4*i+1] = lines[i].y1(); |
3781 vertexArray[4*i+2] = f2vt(lines[i].x2()); |
3783 vertexArray[4*i+2] = lines[i].x2(); |
3782 vertexArray[4*i+3] = f2vt(lines[i].y2()); |
3784 vertexArray[4*i+3] = lines[i].y2(); |
3783 } |
3785 } |
3784 |
3786 |
3785 glEnableClientState(GL_VERTEX_ARRAY); |
3787 glEnableClientState(GL_VERTEX_ARRAY); |
3786 |
3788 |
3787 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData()); |
3789 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); |
3788 glDrawArrays(GL_LINES, 0, lineCount*2); |
3790 glDrawArrays(GL_LINES, 0, lineCount*2); |
3789 |
3791 |
3790 glVertexPointer(2, q_vertexTypeEnum, 4*sizeof(q_vertexType), vertexArray.constData() + 2); |
3792 glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), vertexArray.constData() + 2); |
3791 glDrawArrays(GL_POINTS, 0, lineCount); |
3793 glDrawArrays(GL_POINTS, 0, lineCount); |
3792 |
3794 |
3793 glDisableClientState(GL_VERTEX_ARRAY); |
3795 glDisableClientState(GL_VERTEX_ARRAY); |
3794 } |
3796 } |
3795 } else { |
3797 } else { |
3872 Q_ASSERT(sizeof(QPointF) == 16); |
3874 Q_ASSERT(sizeof(QPointF) == 16); |
3873 glVertexPointer(2, GL_DOUBLE, 0, vertexArray); |
3875 glVertexPointer(2, GL_DOUBLE, 0, vertexArray); |
3874 } |
3876 } |
3875 else { |
3877 else { |
3876 Q_ASSERT(sizeof(QPointF) == 8); |
3878 Q_ASSERT(sizeof(QPointF) == 8); |
3877 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
3879 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
3878 } |
3880 } |
3879 |
3881 |
3880 glEnableClientState(GL_VERTEX_ARRAY); |
3882 glEnableClientState(GL_VERTEX_ARRAY); |
3881 glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount); |
3883 glDrawArrays(GL_TRIANGLE_FAN, 0, pointCount); |
3882 glDisableClientState(GL_VERTEX_ARRAY); |
3884 glDisableClientState(GL_VERTEX_ARRAY); |
3891 } |
3893 } |
3892 |
3894 |
3893 if (d->has_pen) { |
3895 if (d->has_pen) { |
3894 if (d->has_fast_pen && !d->high_quality_antialiasing) { |
3896 if (d->has_fast_pen && !d->high_quality_antialiasing) { |
3895 d->setGradientOps(d->cpen.brush(), bounds); |
3897 d->setGradientOps(d->cpen.brush(), bounds); |
3896 QVarLengthArray<q_vertexType> vertexArray(pointCount*2 + 2); |
3898 QVarLengthArray<GLfloat> vertexArray(pointCount*2 + 2); |
3897 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray.constData()); |
3899 glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData()); |
3898 int i; |
3900 int i; |
3899 for (i=0; i<pointCount; ++i) { |
3901 for (i=0; i<pointCount; ++i) { |
3900 vertexArray[i*2] = f2vt(points[i].x()); |
3902 vertexArray[i*2] = points[i].x(); |
3901 vertexArray[i*2+1] = f2vt(points[i].y()); |
3903 vertexArray[i*2+1] = points[i].y(); |
3902 } |
3904 } |
3903 |
3905 |
3904 glEnableClientState(GL_VERTEX_ARRAY); |
3906 glEnableClientState(GL_VERTEX_ARRAY); |
3905 if (mode != PolylineMode) { |
3907 if (mode != PolylineMode) { |
3906 vertexArray[i*2] = vertexArray[0]; |
3908 vertexArray[i*2] = vertexArray[0]; |
4072 for (int i=0; i<path.elementCount(); ++i) { |
4074 for (int i=0; i<path.elementCount(); ++i) { |
4073 const QPainterPath::Element &e = path.elementAt(i); |
4075 const QPainterPath::Element &e = path.elementAt(i); |
4074 switch (e.type) { |
4076 switch (e.type) { |
4075 case QPainterPath::MoveToElement: |
4077 case QPainterPath::MoveToElement: |
4076 if (i != 0) { |
4078 if (i != 0) { |
4077 glVertexPointer(2, q_vertexTypeEnum, 0, tess_points.data()); |
4079 glVertexPointer(2, GL_FLOAT, 0, tess_points.data()); |
4078 glDrawArrays(GL_LINE_STRIP, 0, tess_points.size()); |
4080 glDrawArrays(GL_LINE_STRIP, 0, tess_points.size()); |
4079 tess_points.reset(); |
4081 tess_points.reset(); |
4080 } |
4082 } |
4081 tess_points.add(QPointF(e.x, e.y)); |
4083 tess_points.add(QPointF(e.x, e.y)); |
4082 |
4084 |
4389 glPushMatrix(); |
4391 glPushMatrix(); |
4390 glRotatef(180.0, 0.0, 1.0, 0.0); |
4392 glRotatef(180.0, 0.0, 1.0, 0.0); |
4391 glRotatef(180.0, 0.0, 0.0, 1.0); |
4393 glRotatef(180.0, 0.0, 0.0, 1.0); |
4392 } |
4394 } |
4393 |
4395 |
4394 q_vertexType vertexArray[4*2]; |
4396 GLfloat vertexArray[4*2]; |
4395 q_vertexType texCoordArray[4*2]; |
4397 GLfloat texCoordArray[4*2]; |
4396 |
4398 |
4397 double offset_x = offset.x() / pm.width(); |
4399 double offset_x = offset.x() / pm.width(); |
4398 double offset_y = offset.y() / pm.height(); |
4400 double offset_y = offset.y() / pm.height(); |
4399 |
4401 |
4400 qt_add_rect_to_array(r, vertexArray); |
4402 qt_add_rect_to_array(r, vertexArray); |
4401 qt_add_texcoords_to_array(offset_x, offset_y, |
4403 qt_add_texcoords_to_array(offset_x, offset_y, |
4402 tc_w + offset_x, tc_h + offset_y, texCoordArray); |
4404 tc_w + offset_x, tc_h + offset_y, texCoordArray); |
4403 |
4405 |
4404 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
4406 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
4405 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray); |
4407 glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); |
4406 |
4408 |
4407 glEnableClientState(GL_VERTEX_ARRAY); |
4409 glEnableClientState(GL_VERTEX_ARRAY); |
4408 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
4410 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
4409 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
4411 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
4410 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
4412 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
4481 x2 = sr.right(); |
4483 x2 = sr.right(); |
4482 y1 = sr.bottom(); |
4484 y1 = sr.bottom(); |
4483 y2 = sr.y(); |
4485 y2 = sr.y(); |
4484 } |
4486 } |
4485 |
4487 |
4486 q_vertexType vertexArray[4*2]; |
4488 GLfloat vertexArray[4*2]; |
4487 q_vertexType texCoordArray[4*2]; |
4489 GLfloat texCoordArray[4*2]; |
4488 |
4490 |
4489 qt_add_rect_to_array(r, vertexArray); |
4491 qt_add_rect_to_array(r, vertexArray); |
4490 qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray); |
4492 qt_add_texcoords_to_array(x1, y2, x2, y1, texCoordArray); |
4491 |
4493 |
4492 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
4494 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
4493 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray); |
4495 glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); |
4494 |
4496 |
4495 glEnableClientState(GL_VERTEX_ARRAY); |
4497 glEnableClientState(GL_VERTEX_ARRAY); |
4496 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
4498 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
4497 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
4499 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
4498 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
4500 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
4742 } else { |
4744 } else { |
4743 font_cache = dev_it.value(); |
4745 font_cache = dev_it.value(); |
4744 } |
4746 } |
4745 Q_ASSERT(font_cache != 0); |
4747 Q_ASSERT(font_cache != 0); |
4746 |
4748 |
4747 QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(ti.fontEngine); |
4749 QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(fontEngine); |
4748 QGLGlyphHash *cache = 0; |
4750 QGLGlyphHash *cache = 0; |
4749 if (cache_it == font_cache->constEnd()) { |
4751 if (cache_it == font_cache->constEnd()) { |
4750 cache = new QGLGlyphHash; |
4752 cache = new QGLGlyphHash; |
4751 font_cache->insert(ti.fontEngine, cache); |
4753 font_cache->insert(fontEngine, cache); |
4752 connect(ti.fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*))); |
4754 connect(fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*))); |
4753 } else { |
4755 } else { |
4754 cache = cache_it.value(); |
4756 cache = cache_it.value(); |
4755 } |
4757 } |
4756 current_cache = cache; |
4758 current_cache = cache; |
4757 |
4759 |
4758 quint64 font_key = (reinterpret_cast<quint64>(context_key ? context_key : context) << 32) |
4760 quint64 font_key = (reinterpret_cast<quint64>(context_key ? context_key : context) << 32) |
4759 | reinterpret_cast<quint64>(ti.fontEngine); |
4761 | reinterpret_cast<quint64>(fontEngine); |
4760 QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key); |
4762 QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key); |
4761 QGLFontTexture *font_tex; |
4763 QGLFontTexture *font_tex; |
4762 if (it == qt_font_textures.constEnd()) { |
4764 if (it == qt_font_textures.constEnd()) { |
4763 GLuint font_texture; |
4765 GLuint font_texture; |
4764 glGenTextures(1, &font_texture); |
4766 glGenTextures(1, &font_texture); |
4765 GLint tex_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2); |
4767 GLint tex_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2); |
4766 GLint tex_width = qt_next_power_of_two(tex_height*30); // ### |
4768 GLint tex_width = qt_next_power_of_two(tex_height*30); // ### |
4767 GLint max_tex_size; |
4769 GLint max_tex_size; |
4768 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); |
4770 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); |
4769 Q_ASSERT(max_tex_size > 0); |
4771 Q_ASSERT(max_tex_size > 0); |
4770 if (tex_width > max_tex_size) |
4772 if (tex_width > max_tex_size) |
4782 } else { |
4784 } else { |
4783 font_tex = it.value(); |
4785 font_tex = it.value(); |
4784 glBindTexture(GL_TEXTURE_2D, font_tex->texture); |
4786 glBindTexture(GL_TEXTURE_2D, font_tex->texture); |
4785 } |
4787 } |
4786 |
4788 |
4787 for (int i=0; i< glyphs.size(); ++i) { |
4789 for (int i=0; i< numGlyphs; ++i) { |
4788 QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]); |
4790 QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]); |
4789 if (it == cache->constEnd()) { |
4791 if (it == cache->constEnd()) { |
4790 // render new glyph and put it in the cache |
4792 // render new glyph and put it in the cache |
4791 glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); |
4793 glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]); |
4792 int glyph_width = qRound(metrics.width.toReal())+2; |
4794 int glyph_width = qRound(metrics.width.toReal())+2; |
4793 int glyph_height = qRound(ti.ascent.toReal() + ti.descent.toReal())+2; |
4795 int glyph_height = qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2; |
4794 |
4796 |
4795 if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) { |
4797 if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) { |
4796 int strip_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2); |
4798 int strip_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2); |
4797 font_tex->x_offset = x_margin; |
4799 font_tex->x_offset = x_margin; |
4798 font_tex->y_offset += strip_height; |
4800 font_tex->y_offset += strip_height; |
4799 if (font_tex->y_offset >= font_tex->height) { |
4801 if (font_tex->y_offset >= font_tex->height) { |
4800 // get hold of the old font texture |
4802 // get hold of the old font texture |
4801 uchar *old_tex_data = (uchar *) malloc(font_tex->width*font_tex->height*2); |
4803 uchar *old_tex_data = (uchar *) malloc(font_tex->width*font_tex->height*2); |
4904 void qgl_cleanup_glyph_cache(QGLContext *ctx) |
4906 void qgl_cleanup_glyph_cache(QGLContext *ctx) |
4905 { |
4907 { |
4906 qt_glyph_cache()->cleanupContext(ctx); |
4908 qt_glyph_cache()->cleanupContext(ctx); |
4907 } |
4909 } |
4908 |
4910 |
|
4911 void QOpenGLPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) |
|
4912 { |
|
4913 Q_D(QOpenGLPaintEngine); |
|
4914 |
|
4915 d->flushDrawQueue(); |
|
4916 |
|
4917 // make sure the glyphs we want to draw are in the cache |
|
4918 qt_glyph_cache()->cacheGlyphs(d->device->context(), textItem->fontEngine, textItem->glyphs, |
|
4919 textItem->numGlyphs); |
|
4920 |
|
4921 d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops |
|
4922 qt_glColor4ubv(d->pen_color); |
|
4923 glEnable(GL_TEXTURE_2D); |
|
4924 |
|
4925 #ifdef Q_WS_QWS |
|
4926 // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want |
|
4927 // text rendering to update the alpha in the window surface. |
|
4928 // XXX: This may not be needed as this behavior does seem to be caused by driver bug |
|
4929 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); |
|
4930 #endif |
|
4931 |
|
4932 // do the actual drawing |
|
4933 GLfloat vertexArray[4*2]; |
|
4934 GLfloat texCoordArray[4*2]; |
|
4935 |
|
4936 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
|
4937 glTexCoordPointer(2, GL_FLOAT, 0, texCoordArray); |
|
4938 |
|
4939 glEnableClientState(GL_VERTEX_ARRAY); |
|
4940 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|
4941 bool antialias = !(textItem->fontEngine->fontDef.styleStrategy & QFont::NoAntialias) |
|
4942 && (d->matrix.type() > QTransform::TxTranslate); |
|
4943 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST); |
|
4944 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST); |
|
4945 |
|
4946 for (int i=0; i< textItem->numGlyphs; ++i) { |
|
4947 QGLGlyphCoord *g = qt_glyph_cache()->lookup(textItem->fontEngine, textItem->glyphs[i]); |
|
4948 |
|
4949 // we don't cache glyphs with no width/height |
|
4950 if (!g) |
|
4951 continue; |
|
4952 |
|
4953 qreal x1, x2, y1, y2; |
|
4954 x1 = g->x; |
|
4955 y1 = g->y; |
|
4956 x2 = x1 + g->width; |
|
4957 y2 = y1 + g->height; |
|
4958 |
|
4959 QPointF logical_pos((textItem->glyphPositions[i].x - g->x_offset).toReal(), |
|
4960 (textItem->glyphPositions[i].y + g->y_offset).toReal()); |
|
4961 |
|
4962 qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray); |
|
4963 qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray); |
|
4964 |
|
4965 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
|
4966 } |
|
4967 |
|
4968 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
|
4969 glDisableClientState(GL_VERTEX_ARRAY); |
|
4970 |
|
4971 glDisable(GL_TEXTURE_2D); |
|
4972 |
|
4973 #ifdef Q_WS_QWS |
|
4974 // XXX: This may not be needed as this behavior does seem to be caused by driver bug |
|
4975 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
|
4976 #endif |
|
4977 |
|
4978 } |
|
4979 |
4909 void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) |
4980 void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) |
4910 { |
4981 { |
4911 Q_D(QOpenGLPaintEngine); |
4982 Q_D(QOpenGLPaintEngine); |
4912 |
4983 |
4913 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); |
4984 const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); |
4918 && d->pen_brush_style <= Qt::ConicalGradientPattern)) { |
4989 && d->pen_brush_style <= Qt::ConicalGradientPattern)) { |
4919 QPaintEngine::drawTextItem(p, textItem); |
4990 QPaintEngine::drawTextItem(p, textItem); |
4920 return; |
4991 return; |
4921 } |
4992 } |
4922 |
4993 |
4923 d->flushDrawQueue(); |
|
4924 |
|
4925 // add the glyphs used to the glyph texture cache |
4994 // add the glyphs used to the glyph texture cache |
4926 QVarLengthArray<QFixedPoint> positions; |
4995 QVarLengthArray<QFixedPoint> positions; |
4927 QVarLengthArray<glyph_t> glyphs; |
4996 QVarLengthArray<glyph_t> glyphs; |
4928 QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y())); |
4997 QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y())); |
4929 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); |
4998 ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); |
4930 |
4999 |
4931 // make sure the glyphs we want to draw are in the cache |
5000 { |
4932 qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs); |
5001 QStaticTextItem staticTextItem; |
4933 |
5002 staticTextItem.chars = ti.chars; |
4934 d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops |
5003 staticTextItem.fontEngine = ti.fontEngine; |
4935 qt_glColor4ubv(d->pen_color); |
5004 staticTextItem.glyphs = glyphs.data(); |
4936 glEnable(GL_TEXTURE_2D); |
5005 staticTextItem.numChars = ti.num_chars; |
4937 |
5006 staticTextItem.numGlyphs = glyphs.size(); |
4938 #ifdef Q_WS_QWS |
5007 staticTextItem.glyphPositions = positions.data(); |
4939 // XXX: it is necessary to disable alpha writes on GLES/embedded because we don't want |
5008 drawStaticTextItem(&staticTextItem); |
4940 // text rendering to update the alpha in the window surface. |
5009 } |
4941 // XXX: This may not be needed as this behavior does seem to be caused by driver bug |
5010 |
4942 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); |
|
4943 #endif |
|
4944 |
|
4945 // do the actual drawing |
|
4946 q_vertexType vertexArray[4*2]; |
|
4947 q_vertexType texCoordArray[4*2]; |
|
4948 |
|
4949 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
|
4950 glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray); |
|
4951 |
|
4952 glEnableClientState(GL_VERTEX_ARRAY); |
|
4953 glEnableClientState(GL_TEXTURE_COORD_ARRAY); |
|
4954 bool antialias = !(ti.fontEngine->fontDef.styleStrategy & QFont::NoAntialias) |
|
4955 && (d->matrix.type() > QTransform::TxTranslate); |
|
4956 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST); |
|
4957 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST); |
|
4958 |
|
4959 for (int i=0; i< glyphs.size(); ++i) { |
|
4960 QGLGlyphCoord *g = qt_glyph_cache()->lookup(ti.fontEngine, glyphs[i]); |
|
4961 |
|
4962 // we don't cache glyphs with no width/height |
|
4963 if (!g) |
|
4964 continue; |
|
4965 |
|
4966 qreal x1, x2, y1, y2; |
|
4967 x1 = g->x; |
|
4968 y1 = g->y; |
|
4969 x2 = x1 + g->width; |
|
4970 y2 = y1 + g->height; |
|
4971 |
|
4972 QPointF logical_pos((positions[i].x - g->x_offset).toReal(), |
|
4973 (positions[i].y + g->y_offset).toReal()); |
|
4974 |
|
4975 qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray); |
|
4976 qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray); |
|
4977 |
|
4978 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
|
4979 } |
|
4980 |
|
4981 glDisableClientState(GL_TEXTURE_COORD_ARRAY); |
|
4982 glDisableClientState(GL_VERTEX_ARRAY); |
|
4983 |
|
4984 glDisable(GL_TEXTURE_2D); |
|
4985 |
|
4986 #ifdef Q_WS_QWS |
|
4987 // XXX: This may not be needed as this behavior does seem to be caused by driver bug |
|
4988 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
|
4989 #endif |
|
4990 } |
5011 } |
4991 |
5012 |
4992 |
5013 |
4993 void QOpenGLPaintEngine::drawEllipse(const QRectF &rect) |
5014 void QOpenGLPaintEngine::drawEllipse(const QRectF &rect) |
4994 { |
5015 { |
5158 { |
5179 { |
5159 #ifdef Q_WS_QWS |
5180 #ifdef Q_WS_QWS |
5160 Q_UNUSED(rect); |
5181 Q_UNUSED(rect); |
5161 Q_UNUSED(maskOffset); |
5182 Q_UNUSED(maskOffset); |
5162 #else |
5183 #else |
5163 q_vertexType vertexArray[8]; |
5184 GLfloat vertexArray[8]; |
5164 qt_add_rect_to_array(rect, vertexArray); |
5185 qt_add_rect_to_array(rect, vertexArray); |
5165 |
5186 |
5166 composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset); |
5187 composite(GL_TRIANGLE_FAN, vertexArray, 4, maskOffset); |
5167 #endif |
5188 #endif |
5168 } |
5189 } |
5169 |
5190 |
5170 |
5191 |
5171 void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const q_vertexType *vertexArray, int vertexCount, const QPoint &maskOffset) |
5192 void QOpenGLPaintEnginePrivate::composite(GLuint primitive, const GLfloat *vertexArray, int vertexCount, const QPoint &maskOffset) |
5172 { |
5193 { |
5173 #ifdef QT_OPENGL_ES |
5194 #ifdef QT_OPENGL_ES |
5174 Q_UNUSED(primitive); |
5195 Q_UNUSED(primitive); |
5175 Q_UNUSED(vertexArray); |
5196 Q_UNUSED(vertexArray); |
5176 Q_UNUSED(vertexCount); |
5197 Q_UNUSED(vertexCount); |
5189 q->updateCompositionMode(composition_mode); |
5210 q->updateCompositionMode(composition_mode); |
5190 else { |
5211 else { |
5191 qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9; |
5212 qreal minX = 1e9, minY = 1e9, maxX = -1e9, maxY = -1e9; |
5192 |
5213 |
5193 for (int i = 0; i < vertexCount; ++i) { |
5214 for (int i = 0; i < vertexCount; ++i) { |
5194 qreal x = vt2f(vertexArray[2 * i]); |
5215 qreal x = vertexArray[2 * i]; |
5195 qreal y = vt2f(vertexArray[2 * i + 1]); |
5216 qreal y = vertexArray[2 * i + 1]; |
5196 |
5217 |
5197 qreal tx, ty; |
5218 qreal tx, ty; |
5198 matrix.map(x, y, &tx, &ty); |
5219 matrix.map(x, y, &tx, &ty); |
5199 |
5220 |
5200 minX = qMin(minX, tx); |
5221 minX = qMin(minX, tx); |
5249 |
5270 |
5250 updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform); |
5271 updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, use_smooth_pixmap_transform); |
5251 } |
5272 } |
5252 |
5273 |
5253 glEnableClientState(GL_VERTEX_ARRAY); |
5274 glEnableClientState(GL_VERTEX_ARRAY); |
5254 glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray); |
5275 glVertexPointer(2, GL_FLOAT, 0, vertexArray); |
5255 glEnable(GL_FRAGMENT_PROGRAM_ARB); |
5276 glEnable(GL_FRAGMENT_PROGRAM_ARB); |
5256 GLuint program = qt_gl_program_cache()->getProgram(device->context(), |
5277 GLuint program = qt_gl_program_cache()->getProgram(device->context(), |
5257 fragment_brush, |
5278 fragment_brush, |
5258 fragment_composition_mode, false); |
5279 fragment_composition_mode, false); |
5259 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program); |
5280 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program); |