mirror of
https://bitbucket.org/smil3y/katie.git
synced 2025-02-24 19:02:59 +00:00
cleanup the OpenGL painting engine
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
This commit is contained in:
parent
06d091d4a3
commit
da73e0a79a
1 changed files with 34 additions and 436 deletions
|
@ -99,10 +99,6 @@ static bool DEBUG_TEMP_FLAG;
|
||||||
#define DEBUG_ONCE_STR(str) DEBUG_ONCE qDebug() << (str);
|
#define DEBUG_ONCE_STR(str) DEBUG_ONCE qDebug() << (str);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_WS_X11
|
|
||||||
static bool qt_nvidiaFboNeedsFinish = false;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline void qt_glColor4ubv(unsigned char *col)
|
static inline void qt_glColor4ubv(unsigned char *col)
|
||||||
{
|
{
|
||||||
glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f);
|
glColor4f(col[0]/255.0f, col[1]/255.0f, col[2]/255.0f, col[3]/255.0f);
|
||||||
|
@ -416,12 +412,6 @@ inline void QGLOffscreen::release()
|
||||||
if (!offscreen || !bound)
|
if (!offscreen || !bound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#ifdef Q_WS_X11
|
|
||||||
// workaround for bug in nvidia driver versions 9x.xx
|
|
||||||
if (qt_nvidiaFboNeedsFinish)
|
|
||||||
glFinish();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DEBUG_ONCE_STR("QGLOffscreen: releasing offscreen");
|
DEBUG_ONCE_STR("QGLOffscreen: releasing offscreen");
|
||||||
|
|
||||||
if (drawable_fbo)
|
if (drawable_fbo)
|
||||||
|
@ -650,7 +640,6 @@ public:
|
||||||
, composition_mode(QPainter::CompositionMode_SourceOver)
|
, composition_mode(QPainter::CompositionMode_SourceOver)
|
||||||
, has_pen(false)
|
, has_pen(false)
|
||||||
, has_brush(false)
|
, has_brush(false)
|
||||||
, has_fast_pen(false)
|
|
||||||
, use_stencil_method(false)
|
, use_stencil_method(false)
|
||||||
, dirty_drawable_texture(false)
|
, dirty_drawable_texture(false)
|
||||||
, has_stencil_face_ext(false)
|
, has_stencil_face_ext(false)
|
||||||
|
@ -701,7 +690,6 @@ public:
|
||||||
|
|
||||||
void drawFastRect(const QRectF &rect);
|
void drawFastRect(const QRectF &rect);
|
||||||
void strokePath(const QPainterPath &path, bool use_cache);
|
void strokePath(const QPainterPath &path, bool use_cache);
|
||||||
void strokePathFastPen(const QPainterPath &path, bool needsResolving);
|
|
||||||
void strokeLines(const QPainterPath &path);
|
void strokeLines(const QPainterPath &path);
|
||||||
|
|
||||||
void updateDepthClip();
|
void updateDepthClip();
|
||||||
|
@ -712,16 +700,6 @@ public:
|
||||||
shader_ctx = 0;
|
shader_ctx = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void updateFastPen() {
|
|
||||||
qreal pen_width = cpen.widthF();
|
|
||||||
has_fast_pen =
|
|
||||||
((pen_width == 0 || (pen_width <= 1 && matrix.type() <= QTransform::TxTranslate))
|
|
||||||
|| cpen.isCosmetic())
|
|
||||||
&& cpen.style() == Qt::SolidLine
|
|
||||||
&& cpen.isSolid();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void disableClipping();
|
void disableClipping();
|
||||||
void enableClipping();
|
void enableClipping();
|
||||||
void ensureDrawableTexture();
|
void ensureDrawableTexture();
|
||||||
|
@ -738,7 +716,6 @@ public:
|
||||||
|
|
||||||
uint has_pen : 1;
|
uint has_pen : 1;
|
||||||
uint has_brush : 1;
|
uint has_brush : 1;
|
||||||
uint has_fast_pen : 1;
|
|
||||||
uint use_stencil_method : 1;
|
uint use_stencil_method : 1;
|
||||||
uint dirty_drawable_texture : 1;
|
uint dirty_drawable_texture : 1;
|
||||||
uint has_stencil_face_ext : 1;
|
uint has_stencil_face_ext : 1;
|
||||||
|
@ -1246,7 +1223,6 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
d->offscreen.setDevice(pdev);
|
d->offscreen.setDevice(pdev);
|
||||||
d->has_fast_pen = false;
|
|
||||||
d->inverseScale = 1;
|
d->inverseScale = 1;
|
||||||
d->opacity = 1;
|
d->opacity = 1;
|
||||||
d->device->beginPaint();
|
d->device->beginPaint();
|
||||||
|
@ -1281,22 +1257,6 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
|
||||||
&& (d->use_stencil_method && QGLExtensions::glExtensions() & QGLExtensions::StencilTwoSide))
|
&& (d->use_stencil_method && QGLExtensions::glExtensions() & QGLExtensions::StencilTwoSide))
|
||||||
d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx);
|
d->has_stencil_face_ext = qt_resolve_stencil_face_extension(ctx);
|
||||||
|
|
||||||
#ifdef Q_WS_X11
|
|
||||||
static bool nvidia_workaround_needs_init = true;
|
|
||||||
if (nvidia_workaround_needs_init) {
|
|
||||||
// nvidia 9x.xx unix drivers contain a bug which requires us to
|
|
||||||
// call glFinish before releasing an fbo to avoid painting
|
|
||||||
// artifacts
|
|
||||||
const QByteArray versionString(reinterpret_cast<const char*>(glGetString(GL_VERSION)));
|
|
||||||
const int pos = versionString.indexOf("NVIDIA");
|
|
||||||
if (pos >= 0) {
|
|
||||||
const float nvidiaDriverVersion = versionString.mid(pos + strlen("NVIDIA")).toFloat();
|
|
||||||
qt_nvidiaFboNeedsFinish = nvidiaDriverVersion >= 90.0 && nvidiaDriverVersion < 100.0;
|
|
||||||
}
|
|
||||||
nvidia_workaround_needs_init = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef QT_OPENGL_ES
|
#ifndef QT_OPENGL_ES
|
||||||
if (!ctx->d_ptr->internal_context) {
|
if (!ctx->d_ptr->internal_context) {
|
||||||
glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]);
|
glGetDoublev(GL_PROJECTION_MATRIX, &d->projection_matrix[0][0]);
|
||||||
|
@ -1459,10 +1419,7 @@ void QOpenGLPaintEngine::updateState(const QPaintEngineState &state)
|
||||||
Q_D(QOpenGLPaintEngine);
|
Q_D(QOpenGLPaintEngine);
|
||||||
QPaintEngine::DirtyFlags flags = state.state();
|
QPaintEngine::DirtyFlags flags = state.state();
|
||||||
|
|
||||||
bool update_fast_pen = false;
|
|
||||||
|
|
||||||
if (flags & DirtyOpacity) {
|
if (flags & DirtyOpacity) {
|
||||||
update_fast_pen = true;
|
|
||||||
d->opacity = state.opacity();
|
d->opacity = state.opacity();
|
||||||
if (d->opacity > 1.0f)
|
if (d->opacity > 1.0f)
|
||||||
d->opacity = 1.0f;
|
d->opacity = 1.0f;
|
||||||
|
@ -1474,7 +1431,6 @@ void QOpenGLPaintEngine::updateState(const QPaintEngineState &state)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DirtyTransform) {
|
if (flags & DirtyTransform) {
|
||||||
update_fast_pen = true;
|
|
||||||
updateMatrix(state.transform());
|
updateMatrix(state.transform());
|
||||||
// brush setup depends on transform state
|
// brush setup depends on transform state
|
||||||
if (state.brush().style() != Qt::NoBrush)
|
if (state.brush().style() != Qt::NoBrush)
|
||||||
|
@ -1482,7 +1438,6 @@ void QOpenGLPaintEngine::updateState(const QPaintEngineState &state)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & DirtyPen) {
|
if (flags & DirtyPen) {
|
||||||
update_fast_pen = true;
|
|
||||||
updatePen(state.pen());
|
updatePen(state.pen());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,16 +1473,6 @@ void QOpenGLPaintEngine::updateState(const QPaintEngineState &state)
|
||||||
if (flags & DirtyCompositionMode) {
|
if (flags & DirtyCompositionMode) {
|
||||||
updateCompositionMode(state.compositionMode());
|
updateCompositionMode(state.compositionMode());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_fast_pen) {
|
|
||||||
Q_D(QOpenGLPaintEngine);
|
|
||||||
qreal pen_width = d->cpen.widthF();
|
|
||||||
d->has_fast_pen =
|
|
||||||
((pen_width == 0 || (pen_width <= 1 && d->txop <= QTransform::TxTranslate))
|
|
||||||
|| d->cpen.isCosmetic())
|
|
||||||
&& d->cpen.style() == Qt::SolidLine
|
|
||||||
&& d->cpen.isSolid();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2151,8 +2096,6 @@ void QOpenGLPaintEngine::updatePen(const QPen &pen)
|
||||||
} else {
|
} else {
|
||||||
d->setGLPen(pen.color());
|
d->setGLPen(pen.color());
|
||||||
}
|
}
|
||||||
|
|
||||||
d->updateFastPen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QOpenGLPaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
|
void QOpenGLPaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
|
||||||
|
@ -2204,7 +2147,6 @@ void QOpenGLPaintEngine::updateMatrix(const QTransform &mtx)
|
||||||
qreal(0.0001));
|
qreal(0.0001));
|
||||||
|
|
||||||
d->updateGLMatrix();
|
d->updateGLMatrix();
|
||||||
d->updateFastPen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QOpenGLPaintEnginePrivate::updateGLMatrix() const
|
void QOpenGLPaintEnginePrivate::updateGLMatrix() const
|
||||||
|
@ -3428,33 +3370,21 @@ void QOpenGLPaintEnginePrivate::drawFastRect(const QRectF &r)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_pen) {
|
if (has_pen) {
|
||||||
if (has_fast_pen && !high_quality_antialiasing) {
|
QPainterPath path;
|
||||||
setGradientOps(cpen.brush(), r);
|
path.setFillRule(Qt::WindingFill);
|
||||||
|
|
||||||
vertexArray[8] = vertexArray[0];
|
qreal left = r.left();
|
||||||
vertexArray[9] = vertexArray[1];
|
qreal right = r.right();
|
||||||
|
qreal top = r.top();
|
||||||
|
qreal bottom = r.bottom();
|
||||||
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, vertexArray);
|
path.moveTo(left, top);
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
path.lineTo(right, top);
|
||||||
glDrawArrays(GL_LINE_STRIP, 0, 5);
|
path.lineTo(right, bottom);
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
path.lineTo(left, bottom);
|
||||||
} else {
|
path.lineTo(left, top);
|
||||||
QPainterPath path;
|
|
||||||
path.setFillRule(Qt::WindingFill);
|
|
||||||
|
|
||||||
qreal left = r.left();
|
strokePath(path, false);
|
||||||
qreal right = r.right();
|
|
||||||
qreal top = r.top();
|
|
||||||
qreal bottom = r.bottom();
|
|
||||||
|
|
||||||
path.moveTo(left, top);
|
|
||||||
path.lineTo(right, top);
|
|
||||||
path.lineTo(right, bottom);
|
|
||||||
path.lineTo(left, bottom);
|
|
||||||
path.lineTo(left, top);
|
|
||||||
|
|
||||||
strokePath(path, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
QOpenGLCoordinateOffset::disableOffset(this);
|
QOpenGLCoordinateOffset::disableOffset(this);
|
||||||
}
|
}
|
||||||
|
@ -3532,36 +3462,12 @@ void QOpenGLPaintEngine::drawRects(const QRectF *rects, int rectCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->has_pen) {
|
if (d->has_pen) {
|
||||||
if (d->has_fast_pen)
|
d->strokePath(path, false);
|
||||||
d->strokeLines(path);
|
|
||||||
else
|
|
||||||
d->strokePath(path, false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void addQuadAsTriangle(GLfloat *quad, GLfloat *triangle)
|
|
||||||
{
|
|
||||||
triangle[0] = quad[0];
|
|
||||||
triangle[1] = quad[1];
|
|
||||||
|
|
||||||
triangle[2] = quad[2];
|
|
||||||
triangle[3] = quad[3];
|
|
||||||
|
|
||||||
triangle[4] = quad[4];
|
|
||||||
triangle[5] = quad[5];
|
|
||||||
|
|
||||||
triangle[6] = quad[4];
|
|
||||||
triangle[7] = quad[5];
|
|
||||||
|
|
||||||
triangle[8] = quad[6];
|
|
||||||
triangle[9] = quad[7];
|
|
||||||
|
|
||||||
triangle[10] = quad[0];
|
|
||||||
triangle[11] = quad[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
void QOpenGLPaintEngine::drawPoints(const QPoint *points, int pointCount)
|
void QOpenGLPaintEngine::drawPoints(const QPoint *points, int pointCount)
|
||||||
{
|
{
|
||||||
Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
|
Q_ASSERT(sizeof(QT_PointF) == sizeof(QPointF));
|
||||||
|
@ -3601,41 +3507,6 @@ void QOpenGLPaintEngine::drawPoints(const QPointF *points, int pointCount)
|
||||||
|
|
||||||
d->flushDrawQueue();
|
d->flushDrawQueue();
|
||||||
|
|
||||||
if (d->has_fast_pen) {
|
|
||||||
QVarLengthArray<GLfloat> vertexArray(6 * pointCount);
|
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
int j = 0;
|
|
||||||
for (int i = 0; i < pointCount; ++i) {
|
|
||||||
QPointF mapped = d->matrix.map(points[i]);
|
|
||||||
|
|
||||||
GLfloat x = GLfloat(qRound(mapped.x()));
|
|
||||||
GLfloat y = GLfloat(qRound(mapped.y()));
|
|
||||||
|
|
||||||
vertexArray[j++] = x;
|
|
||||||
vertexArray[j++] = y - 0.5f;
|
|
||||||
|
|
||||||
vertexArray[j++] = x + 1.5f;
|
|
||||||
vertexArray[j++] = y + 1.0f;
|
|
||||||
|
|
||||||
vertexArray[j++] = x;
|
|
||||||
vertexArray[j++] = y + 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, pointCount*3);
|
|
||||||
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
glPopMatrix();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const qreal *vertexArray = reinterpret_cast<const qreal*>(&points[0]);
|
const qreal *vertexArray = reinterpret_cast<const qreal*>(&points[0]);
|
||||||
|
|
||||||
if (sizeof(qreal) == sizeof(double)) {
|
if (sizeof(qreal) == sizeof(double)) {
|
||||||
|
@ -3690,122 +3561,24 @@ void QOpenGLPaintEngine::drawLines(const QLineF *lines, int lineCount)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->has_pen) {
|
if (d->has_pen) {
|
||||||
QOpenGLCoordinateOffset offset(d);
|
QPainterPath path;
|
||||||
if (d->has_fast_pen && !d->high_quality_antialiasing) {
|
path.setFillRule(Qt::WindingFill);
|
||||||
//### gradient resolving on lines isn't correct
|
for (int i=0; i<lineCount; ++i) {
|
||||||
d->setGradientOps(d->cpen.brush(), QRectF());
|
const QLineF &l = lines[i];
|
||||||
|
|
||||||
bool useRects = false;
|
if (l.p1() == l.p2()) {
|
||||||
// scale or 90 degree rotation?
|
if (d->cpen.capStyle() != Qt::FlatCap) {
|
||||||
if (d->matrix.type() <= QTransform::TxTranslate
|
QPointF p = l.p1();
|
||||||
|| (!d->cpen.isCosmetic()
|
drawPoints(&p, 1);
|
||||||
&& (d->matrix.type() <= QTransform::TxScale
|
|
||||||
|| (d->matrix.type() == QTransform::TxRotate
|
|
||||||
&& d->matrix.m11() == 0 && d->matrix.m22() == 0)))) {
|
|
||||||
useRects = true;
|
|
||||||
for (int i = 0; i < lineCount; ++i) {
|
|
||||||
if (lines[i].p1().x() != lines[i].p2().x()
|
|
||||||
&& lines[i].p1().y() != lines[i].p2().y()) {
|
|
||||||
useRects = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLfloat endCap = d->cpen.capStyle() == Qt::FlatCap ? 0.0f : 0.5f;
|
path.moveTo(l.x1(), l.y1());
|
||||||
if (useRects) {
|
path.lineTo(l.x2(), l.y2());
|
||||||
QVarLengthArray<GLfloat> vertexArray(12 * lineCount);
|
|
||||||
|
|
||||||
GLfloat quad[8];
|
|
||||||
for (int i = 0; i < lineCount; ++i) {
|
|
||||||
GLfloat x1 = lines[i].x1();
|
|
||||||
GLfloat x2 = lines[i].x2();
|
|
||||||
GLfloat y1 = lines[i].y1();
|
|
||||||
GLfloat y2 = lines[i].y2();
|
|
||||||
|
|
||||||
if (x1 == x2) {
|
|
||||||
if (y1 > y2)
|
|
||||||
qSwap(y1, y2);
|
|
||||||
|
|
||||||
quad[0] = x1 - 0.5f;
|
|
||||||
quad[1] = y1 - endCap;
|
|
||||||
|
|
||||||
quad[2] = x1 + 0.5f;
|
|
||||||
quad[3] = y1 - endCap;
|
|
||||||
|
|
||||||
quad[4] = x1 + 0.5f;
|
|
||||||
quad[5] = y2 + endCap;
|
|
||||||
|
|
||||||
quad[6] = x1 - 0.5f;
|
|
||||||
quad[7] = y2 + endCap;
|
|
||||||
} else {
|
|
||||||
if (x1 > x2)
|
|
||||||
qSwap(x1, x2);
|
|
||||||
|
|
||||||
quad[0] = x1 - endCap;
|
|
||||||
quad[1] = y1 + 0.5f;
|
|
||||||
|
|
||||||
quad[2] = x1 - endCap;
|
|
||||||
quad[3] = y1 - 0.5f;
|
|
||||||
|
|
||||||
quad[4] = x2 + endCap;
|
|
||||||
quad[5] = y1 - 0.5f;
|
|
||||||
|
|
||||||
quad[6] = x2 + endCap;
|
|
||||||
quad[7] = y1 + 0.5f;
|
|
||||||
}
|
|
||||||
|
|
||||||
addQuadAsTriangle(quad, &vertexArray[12*i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, lineCount*6);
|
|
||||||
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
} else {
|
|
||||||
QVarLengthArray<GLfloat> vertexArray(4 * lineCount);
|
|
||||||
for (int i = 0; i < lineCount; ++i) {
|
|
||||||
vertexArray[4*i] = lines[i].x1();
|
|
||||||
vertexArray[4*i+1] = lines[i].y1();
|
|
||||||
vertexArray[4*i+2] = lines[i].x2();
|
|
||||||
vertexArray[4*i+3] = lines[i].y2();
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
|
|
||||||
glDrawArrays(GL_LINES, 0, lineCount*2);
|
|
||||||
|
|
||||||
glVertexPointer(2, GL_FLOAT, 4*sizeof(GLfloat), vertexArray.constData() + 2);
|
|
||||||
glDrawArrays(GL_POINTS, 0, lineCount);
|
|
||||||
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QPainterPath path;
|
|
||||||
path.setFillRule(Qt::WindingFill);
|
|
||||||
for (int i=0; i<lineCount; ++i) {
|
|
||||||
const QLineF &l = lines[i];
|
|
||||||
|
|
||||||
if (l.p1() == l.p2()) {
|
|
||||||
if (d->cpen.capStyle() != Qt::FlatCap) {
|
|
||||||
QPointF p = l.p1();
|
|
||||||
drawPoints(&p, 1);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.moveTo(l.x1(), l.y1());
|
|
||||||
path.lineTo(l.x2(), l.y2());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d->has_fast_pen && d->high_quality_antialiasing)
|
|
||||||
d->strokeLines(path);
|
|
||||||
else
|
|
||||||
d->strokePath(path, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->strokePath(path, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3832,8 +3605,7 @@ void QOpenGLPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF bounds;
|
QRectF bounds;
|
||||||
if ((mode == ConvexMode && !d->high_quality_antialiasing && state()->brushNeedsResolving()) ||
|
if (mode == ConvexMode && !d->high_quality_antialiasing && state()->brushNeedsResolving()) {
|
||||||
((d->has_fast_pen && !d->high_quality_antialiasing) && state()->penNeedsResolving())) {
|
|
||||||
qreal minx = points[0].x(), miny = points[0].y(),
|
qreal minx = points[0].x(), miny = points[0].y(),
|
||||||
maxx = points[0].x(), maxy = points[0].y();
|
maxx = points[0].x(), maxy = points[0].y();
|
||||||
for (int i = 1; i < pointCount; ++i) {
|
for (int i = 1; i < pointCount; ++i) {
|
||||||
|
@ -3882,38 +3654,13 @@ void QOpenGLPaintEngine::drawPolygon(const QPointF *points, int pointCount, Poly
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->has_pen) {
|
if (d->has_pen) {
|
||||||
if (d->has_fast_pen && !d->high_quality_antialiasing) {
|
QPainterPath path(points[0]);
|
||||||
d->setGradientOps(d->cpen.brush(), bounds);
|
for (int i = 1; i < pointCount; ++i)
|
||||||
QVarLengthArray<GLfloat> vertexArray(pointCount*2 + 2);
|
path.lineTo(points[i]);
|
||||||
glVertexPointer(2, GL_FLOAT, 0, vertexArray.constData());
|
if (mode != PolylineMode)
|
||||||
int i;
|
path.lineTo(points[0]);
|
||||||
for (i=0; i<pointCount; ++i) {
|
|
||||||
vertexArray[i*2] = points[i].x();
|
|
||||||
vertexArray[i*2+1] = points[i].y();
|
|
||||||
}
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
d->strokePath(path, true);
|
||||||
if (mode != PolylineMode) {
|
|
||||||
vertexArray[i*2] = vertexArray[0];
|
|
||||||
vertexArray[i*2+1] = vertexArray[1];
|
|
||||||
glDrawArrays(GL_LINE_STRIP, 0, pointCount+1);
|
|
||||||
} else {
|
|
||||||
glDrawArrays(GL_LINE_STRIP, 0, pointCount);
|
|
||||||
glDrawArrays(GL_POINTS, pointCount-1, 1);
|
|
||||||
}
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
} else {
|
|
||||||
QPainterPath path(points[0]);
|
|
||||||
for (int i = 1; i < pointCount; ++i)
|
|
||||||
path.lineTo(points[i]);
|
|
||||||
if (mode != PolylineMode)
|
|
||||||
path.lineTo(points[0]);
|
|
||||||
|
|
||||||
if (d->has_fast_pen)
|
|
||||||
d->strokeLines(path);
|
|
||||||
else
|
|
||||||
d->strokePath(path, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3987,140 +3734,6 @@ void QOpenGLPaintEnginePrivate::strokePath(const QPainterPath &path, bool use_ca
|
||||||
cbrush = old_brush;
|
cbrush = old_brush;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QOpenGLPaintEnginePrivate::strokePathFastPen(const QPainterPath &path, bool needsResolving)
|
|
||||||
{
|
|
||||||
#ifndef QT_OPENGL_ES
|
|
||||||
QRectF bounds;
|
|
||||||
if (needsResolving)
|
|
||||||
bounds = path.controlPointRect();
|
|
||||||
setGradientOps(cpen.brush(), bounds);
|
|
||||||
|
|
||||||
QBezier beziers[32];
|
|
||||||
for (int i=0; i<path.elementCount(); ++i) {
|
|
||||||
const QPainterPath::Element &e = path.elementAt(i);
|
|
||||||
switch (e.type) {
|
|
||||||
case QPainterPath::MoveToElement:
|
|
||||||
if (i != 0)
|
|
||||||
glEnd(); // GL_LINE_STRIP
|
|
||||||
glBegin(GL_LINE_STRIP);
|
|
||||||
glVertex2d(e.x, e.y);
|
|
||||||
|
|
||||||
break;
|
|
||||||
case QPainterPath::LineToElement:
|
|
||||||
glVertex2d(e.x, e.y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QPainterPath::CurveToElement:
|
|
||||||
{
|
|
||||||
QPointF sp = path.elementAt(i-1);
|
|
||||||
QPointF cp2 = path.elementAt(i+1);
|
|
||||||
QPointF ep = path.elementAt(i+2);
|
|
||||||
i+=2;
|
|
||||||
|
|
||||||
qreal inverseScaleHalf = inverseScale / 2;
|
|
||||||
beziers[0] = QBezier::fromPoints(sp, e, cp2, ep);
|
|
||||||
QBezier *b = beziers;
|
|
||||||
while (b >= beziers) {
|
|
||||||
// check if we can pop the top bezier curve from the stack
|
|
||||||
qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
|
|
||||||
qreal d;
|
|
||||||
if (l > inverseScale) {
|
|
||||||
d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2)
|
|
||||||
- (b->y4 - b->y1)*(b->x1 - b->x2) )
|
|
||||||
+ qAbs( (b->x4 - b->x1)*(b->y1 - b->y3)
|
|
||||||
- (b->y4 - b->y1)*(b->x1 - b->x3) );
|
|
||||||
d /= l;
|
|
||||||
} else {
|
|
||||||
d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
|
|
||||||
qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
|
|
||||||
}
|
|
||||||
if (d < inverseScaleHalf || b == beziers + 31) {
|
|
||||||
// good enough, we pop it off and add the endpoint
|
|
||||||
glVertex2d(b->x4, b->y4);
|
|
||||||
--b;
|
|
||||||
} else {
|
|
||||||
// split, second half of the polygon goes lower into the stack
|
|
||||||
b->split(b+1, b);
|
|
||||||
++b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // case CurveToElement
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
} // end of switch
|
|
||||||
}
|
|
||||||
glEnd(); // GL_LINE_STRIP
|
|
||||||
#else
|
|
||||||
// have to use vertex arrays on embedded
|
|
||||||
QRectF bounds;
|
|
||||||
if (needsResolving)
|
|
||||||
bounds = path.controlPointRect();
|
|
||||||
setGradientOps(cpen.brush(), bounds);
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
|
||||||
tess_points.reset();
|
|
||||||
QBezier beziers[32];
|
|
||||||
for (int i=0; i<path.elementCount(); ++i) {
|
|
||||||
const QPainterPath::Element &e = path.elementAt(i);
|
|
||||||
switch (e.type) {
|
|
||||||
case QPainterPath::MoveToElement:
|
|
||||||
if (i != 0) {
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
|
|
||||||
glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
|
|
||||||
tess_points.reset();
|
|
||||||
}
|
|
||||||
tess_points.add(QPointF(e.x, e.y));
|
|
||||||
|
|
||||||
break;
|
|
||||||
case QPainterPath::LineToElement:
|
|
||||||
tess_points.add(QPointF(e.x, e.y));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QPainterPath::CurveToElement:
|
|
||||||
{
|
|
||||||
QPointF sp = path.elementAt(i-1);
|
|
||||||
QPointF cp2 = path.elementAt(i+1);
|
|
||||||
QPointF ep = path.elementAt(i+2);
|
|
||||||
i+=2;
|
|
||||||
|
|
||||||
qreal inverseScaleHalf = inverseScale / 2;
|
|
||||||
beziers[0] = QBezier::fromPoints(sp, e, cp2, ep);
|
|
||||||
QBezier *b = beziers;
|
|
||||||
while (b >= beziers) {
|
|
||||||
// check if we can pop the top bezier curve from the stack
|
|
||||||
qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
|
|
||||||
qreal d;
|
|
||||||
if (l > inverseScale) {
|
|
||||||
d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2)
|
|
||||||
- (b->y4 - b->y1)*(b->x1 - b->x2) )
|
|
||||||
+ qAbs( (b->x4 - b->x1)*(b->y1 - b->y3)
|
|
||||||
- (b->y4 - b->y1)*(b->x1 - b->x3) );
|
|
||||||
d /= l;
|
|
||||||
} else {
|
|
||||||
d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
|
|
||||||
qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
|
|
||||||
}
|
|
||||||
if (d < inverseScaleHalf || b == beziers + 31) {
|
|
||||||
// good enough, we pop it off and add the endpoint
|
|
||||||
tess_points.add(QPointF(b->x4, b->y4));
|
|
||||||
--b;
|
|
||||||
} else {
|
|
||||||
// split, second half of the polygon goes lower into the stack
|
|
||||||
b->split(b+1, b);
|
|
||||||
++b;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // case CurveToElement
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
} // end of switch
|
|
||||||
}
|
|
||||||
glVertexPointer(2, GL_FLOAT, 0, tess_points.data());
|
|
||||||
glDrawArrays(GL_LINE_STRIP, 0, tess_points.size());
|
|
||||||
glDisableClientState(GL_VERTEX_ARRAY);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool pathClosed(const QPainterPath &path)
|
static bool pathClosed(const QPainterPath &path)
|
||||||
{
|
{
|
||||||
QPointF lastMoveTo = path.elementAt(0);
|
QPointF lastMoveTo = path.elementAt(0);
|
||||||
|
@ -4198,10 +3811,7 @@ void QOpenGLPaintEngine::drawPath(const QPainterPath &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->has_pen) {
|
if (d->has_pen) {
|
||||||
if (d->has_fast_pen && !d->high_quality_antialiasing)
|
d->strokePath(path, true);
|
||||||
d->strokePathFastPen(path, state()->penNeedsResolving());
|
|
||||||
else
|
|
||||||
d->strokePath(path, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5436,18 +5046,6 @@ void QOpenGLPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
|
||||||
updateBrush(old_brush, state()->brushOrigin);
|
updateBrush(old_brush, state()->brushOrigin);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> static inline bool isRect(const T *pts, int elementCount) {
|
|
||||||
return (elementCount == 5 // 5-point polygon, check for closed rect
|
|
||||||
&& pts[0] == pts[8] && pts[1] == pts[9] // last point == first point
|
|
||||||
&& pts[0] == pts[6] && pts[2] == pts[4] // x values equal
|
|
||||||
&& pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
|
|
||||||
) ||
|
|
||||||
(elementCount == 4 // 4-point polygon, check for unclosed rect
|
|
||||||
&& pts[0] == pts[6] && pts[2] == pts[4] // x values equal
|
|
||||||
&& pts[1] == pts[3] && pts[5] == pts[7] // y values equal...
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QOpenGLPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
|
void QOpenGLPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
|
||||||
{
|
{
|
||||||
const qreal *points = path.points();
|
const qreal *points = path.points();
|
||||||
|
|
Loading…
Add table
Reference in a new issue