📄 qpaintengine_x11.cpp
字号:
// eliminate shared edges for (int i = 0; i < et.size(); ++i) { for (int k = i+1; k < et.size(); ++k) { const QEdge *edgeI = et.at(i); const QEdge *edgeK = et.at(k); if (edgeK->p1.y > edgeI->p1.y) break; if (edgeI->winding != edgeK->winding && isEqual(edgeI->p1, edgeK->p1) && isEqual(edgeI->p2, edgeK->p2) ) { et.removeAt(k); et.removeAt(i); --i; break; } } } if (ymax <= ymin) return; QList<const QEdge *> aet; // edges that intersects the current scanline// if (ymin < 0)// ymin = 0;// if (paintEventClipRegion) // don't scan more lines than we have to// ymax = paintEventClipRegion->boundingRect().height();#ifdef QT_DEBUG_TESSELATOR qDebug("==> ymin = %f, ymax = %f", ymin, ymax);#endif // QT_DEBUG_TESSELATOR currentY = ymin; // used by the less than op for (qreal y = ymin; y < ymax;) { // fill active edge table with edges that intersect the current line for (int i = 0; i < et.size(); ++i) { const QEdge *edge = et.at(i); if (edge->p1.y > XDoubleToFixed(y)) break; aet.append(edge); et.removeAt(i); --i; } // remove processed edges from active edge table for (int i = 0; i < aet.size(); ++i) { if (aet.at(i)->p2.y <= XDoubleToFixed(y)) { aet.removeAt(i); --i; } } if (aet.size()%2 != 0) {#ifndef QT_NO_DEBUG qWarning("QX11PaintEngine: aet out of sync - this should not happen.");#endif return; } // done? if (!aet.size()) { if (!et.size()) { break; } else { y = XFixedToDouble(et.at(0)->p1.y); continue; } } // calculate the next y where we have to start a new set of trapezoids qreal next_y(INT_MAX/256); for (int i = 0; i < aet.size(); ++i) { const QEdge *edge = aet.at(i); if (XFixedToDouble(edge->p2.y) < next_y) next_y = XFixedToDouble(edge->p2.y); } if (et.size() && next_y > XFixedToDouble(et.at(0)->p1.y)) next_y = XFixedToDouble(et.at(0)->p1.y); int aetSize = aet.size(); for (int i = 0; i < aetSize; ++i) { for (int k = i+1; k < aetSize; ++k) { const QEdge *edgeI = aet.at(i); const QEdge *edgeK = aet.at(k); qreal m1 = edgeI->m; qreal b1 = edgeI->b; qreal m2 = edgeK->m; qreal b2 = edgeK->b; if (qAbs(m1 - m2) < 0.001) continue; // ### intersect is not calculated correctly when optimized with -O2 (gcc) volatile qreal intersect; if (!qIsFinite(b1)) intersect = (1.f / m2) * XFixedToDouble(edgeI->p1.x) + b2; else if (!qIsFinite(b2)) intersect = (1.f / m1) * XFixedToDouble(edgeK->p1.x) + b1; else intersect = (b1*m1 - b2*m2) / (m1 - m2); if (intersect > y && intersect < next_y) next_y = intersect; } } XFixed yf, next_yf; yf = qrealToXFixed(y); next_yf = qrealToXFixed(next_y); if (yf == next_yf) { y = currentY = next_y; continue; }#ifdef QT_DEBUG_TESSELATOR qDebug("###> y = %f, next_y = %f, %d active edges", y, next_y, aet.size()); qDebug("===> edges"); dump_edges(et); qDebug("===> active edges"); dump_edges(aet);#endif // calc intersection points QVarLengthArray<QIntersectionPoint> isects(aet.size()+1); for (int i = 0; i < isects.size()-1; ++i) { const QEdge *edge = aet.at(i); isects[i].x = (edge->p1.x != edge->p2.x) ? ((y - edge->b)*edge->m) : XFixedToDouble(edge->p1.x); isects[i].edge = edge; } Q_ASSERT(isects.size()%2 == 1); // sort intersection points qSort(&isects[0], &isects[isects.size()-1], compareIntersections); if (winding) { // winding fill rule for (int i = 0; i < isects.size()-1;) { int winding = 0; const QEdge *left = isects[i].edge; const QEdge *right = 0; winding += isects[i].edge->winding; for (++i; i < isects.size()-1 && winding != 0; ++i) { winding += isects[i].edge->winding; right = isects[i].edge; } if (!left || !right) break; traps->append(toXTrapezoid(yf, next_yf, *left, *right)); } } else { // odd-even fill rule for (int i = 0; i < isects.size()-2; i += 2) traps->append(toXTrapezoid(yf, next_yf, *isects[i].edge, *isects[i+1].edge)); } y = currentY = next_y; }#ifdef QT_DEBUG_TESSELATOR qDebug("==> number of trapezoids: %d - edge table size: %d\n", traps->size(), et.size()); for (int i = 0; i < traps->size(); ++i) dump_trap(traps->at(i));#endif // optimize by unifying trapezoids that share left/right lines // and have a common top/bottom edge// for (int i = 0; i < tps.size(); ++i) {// for (int k = i+1; k < tps.size(); ++k) {// if (i != k && tps.at(i).right == tps.at(k).right// && tps.at(i).left == tps.at(k).left// && (tps.at(i).top == tps.at(k).bottom// || tps.at(i).bottom == tps.at(k).top))// {// tps[i].bottom = tps.at(k).bottom;// tps.removeAt(k);// i = 0;// break;// }// }// }}#endif // !defined(QT_NO_XRENDER)#ifndef QT_NO_XRENDERstatic Picture getPatternFill(int screen, const QBrush &b, const QBrush &bg, bool opaque_bg){ if (!X11->use_xrender) return XNone; XRenderColor color = X11->preMultiply(b.color()); XRenderColor bg_color; if (opaque_bg) bg_color = X11->preMultiply(bg.color()); else bg_color = X11->preMultiply(QColor(0, 0, 0, 0)); for (int i = 0; i < X11->pattern_fill_count; ++i) { if (X11->pattern_fills[i].screen == screen && X11->pattern_fills[i].opaque == opaque_bg && X11->pattern_fills[i].style == b.style() && X11->pattern_fills[i].color.alpha == color.alpha && X11->pattern_fills[i].color.red == color.red && X11->pattern_fills[i].color.green == color.green && X11->pattern_fills[i].color.blue == color.blue && X11->pattern_fills[i].bg_color.alpha == bg_color.alpha && X11->pattern_fills[i].bg_color.red == bg_color.red && X11->pattern_fills[i].bg_color.green == bg_color.green && X11->pattern_fills[i].bg_color.blue == bg_color.blue) return X11->pattern_fills[i].picture; } // none found, replace one int i = rand() % 16; if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) { XRenderFreePicture (X11->display, X11->pattern_fills[i].picture); X11->pattern_fills[i].picture = 0; } if (!X11->pattern_fills[i].picture) { Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 8, 8, 32); XRenderPictureAttributes attrs; attrs.repeat = True; X11->pattern_fills[i].picture = XRenderCreatePicture (X11->display, pixmap, XRenderFindStandardFormat(X11->display, PictStandardARGB32), CPRepeat, &attrs); XFreePixmap (X11->display, pixmap); } X11->pattern_fills[i].screen = screen; X11->pattern_fills[i].color = color; X11->pattern_fills[i].bg_color = bg_color; X11->pattern_fills[i].opaque = opaque_bg; X11->pattern_fills[i].style = b.style(); XRenderFillRectangle(X11->display, PictOpSrc, X11->pattern_fills[i].picture, &bg_color, 0, 0, 8, 8); QPixmap pattern(qt_pixmapForBrush(b.style(), true)); XRenderPictureAttributes attrs; attrs.repeat = true; XRenderChangePicture(X11->display, pattern.x11PictureHandle(), CPRepeat, &attrs); Picture fill_fg = X11->getSolidFill(screen, b.color()); XRenderComposite(X11->display, PictOpOver, fill_fg, pattern.x11PictureHandle(), X11->pattern_fills[i].picture, 0, 0, 0, 0, 0, 0, 8, 8); return X11->pattern_fills[i].picture;}static void qt_render_bitmap(Display *dpy, int scrn, Picture src, Picture dst, int sx, int sy, int x, int y, int sw, int sh, const QPen &pen, const QBrush &brush, bool opaque_bg){ if (opaque_bg) { Picture fill_bg = X11->getSolidFill(scrn, brush.color()); XRenderComposite(dpy, PictOpOver, fill_bg, 0, dst, sx, sy, sx, sy, x, y, sw, sh); } Picture fill_fg = X11->getSolidFill(scrn, pen.color()); XRenderComposite(dpy, PictOpOver, fill_fg, src, dst, sx, sy, sx, sy, x, y, sw, sh);}#endifvoid QX11PaintEnginePrivate::init(){ dpy = 0; scrn = 0; hd = 0; picture = 0; xinfo = 0;#ifndef QT_NO_XRENDER current_brush = 0; composition_mode = PictOpOver;#endif}void QX11PaintEnginePrivate::setupAdaptedOrigin(const QPoint &p){ if (adapted_pen_origin) XSetTSOrigin(dpy, gc, p.x(), p.y()); if (adapted_brush_origin) XSetTSOrigin(dpy, gc_brush, p.x(), p.y());}void QX11PaintEnginePrivate::resetAdaptedOrigin(){ if (adapted_pen_origin) XSetTSOrigin(dpy, gc, 0, 0); if (adapted_brush_origin) XSetTSOrigin(dpy, gc_brush, 0, 0);}void QX11PaintEnginePrivate::clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly){ int clipped_count = 0; qt_float_point *clipped_points = 0; polygonClipper.clipPolygon((qt_float_point *) poly.data(), poly.size(), &clipped_points, &clipped_count); clipped_poly->resize(clipped_count); for (int i=0; i<clipped_count; ++i) (*clipped_poly)[i] = *((QPointF *)(&clipped_points[i]));}static QPaintEngine::PaintEngineFeatures qt_decide_features(){ QPaintEngine::PaintEngineFeatures features = QPaintEngine::PrimitiveTransform | QPaintEngine::PatternBrush | QPaintEngine::AlphaBlend | QPaintEngine::PainterPaths; if (X11->use_xrender) { features |= QPaintEngine::Antialiasing; features |= QPaintEngine::PorterDuff; } return features;}/* * QX11PaintEngine members */QX11PaintEngine::QX11PaintEngine() : QPaintEngine(*(new QX11PaintEnginePrivate), qt_decide_features()){ d_func()->init();}QX11PaintEngine::QX11PaintEngine(QX11PaintEnginePrivate &dptr) : QPaintEngine(dptr, qt_decide_features()){ d_func()->init();}QX11PaintEngine::~QX11PaintEngine(){}bool QX11PaintEngine::begin(QPaintDevice *pdev){ Q_D(QX11PaintEngine); d->xinfo = qt_x11Info(pdev);#ifndef QT_NO_XRENDER if (pdev->devType() == QInternal::Widget) { d->picture = (::Picture)static_cast<const QWidget *>(pdev)->x11PictureHandle(); } else if (pdev->devType() == QInternal::Pixmap) { const QPixmap *pm = static_cast<const QPixmap *>(pdev); if (X11->use_xrender && pm->data->d != 32 && pm->data->x11_mask) pm->data->convertToARGB32(); d->picture = (::Picture)static_cast<const QPixmap *>(pdev)->x11PictureHandle(); }#else d->picture = 0;#endif d->hd = qt_x11Handle(pdev); Q_ASSERT(d->xinfo != 0); d->dpy = d->xinfo->display(); // get display variable d->scrn = d->xinfo->screen(); // get screen variable d->bg_col = Qt::white; d->bg_mode = Qt::TransparentMode; d->crgn = QRegion(); d->gc = XCreateGC(d->dpy, d->hd, 0, 0); d->gc_brush = XCreateGC(d->dpy, d->hd, 0, 0); d->has_alpha_brush = false; d->has_alpha_pen = false; d->has_clipping = false; d->has_complex_xform = false; d->has_custom_pen = false; d->matrix = QMatrix(); d->pdev_depth = d->pdev->depth(); d->render_hints = 0; d->txop = QPainterPrivate::TxNone; d->use_path_fallback = false;#if !defined(QT_NO_XRENDER) d->composition_mode = PictOpOver;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -