void xf_draw_screen_scaled(xfInfo* xfi) { XTransform transform; Picture windowPicture; Picture primaryPicture; XRenderPictureAttributes pa; XRenderPictFormat* picFormat; picFormat = XRenderFindStandardFormat(xfi->display, PictStandardRGB24); pa.subwindow_mode = IncludeInferiors; primaryPicture = XRenderCreatePicture(xfi->display, xfi->primary, picFormat, CPSubwindowMode, &pa); windowPicture = XRenderCreatePicture(xfi->display, xfi->window->handle, picFormat, CPSubwindowMode, &pa); transform.matrix[0][0] = XDoubleToFixed(1); transform.matrix[0][1] = XDoubleToFixed(0); transform.matrix[0][2] = XDoubleToFixed(0); transform.matrix[1][0] = XDoubleToFixed(0); transform.matrix[1][1] = XDoubleToFixed(1); transform.matrix[1][2] = XDoubleToFixed(0); transform.matrix[2][0] = XDoubleToFixed(0); transform.matrix[2][1] = XDoubleToFixed(0); transform.matrix[2][2] = XDoubleToFixed(xfi->scale); XRenderSetPictureTransform(xfi->display, primaryPicture, &transform); XRenderComposite(xfi->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, 0, 0, xfi->currentWidth, xfi->currentHeight); }
void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale) { #ifdef WITH_XRENDER XTransform transform; Picture windowPicture; Picture primaryPicture; XRenderPictureAttributes pa; XRenderPictFormat* picFormat; XRectangle xr; picFormat = XRenderFindStandardFormat(xfc->display, PictStandardRGB24); pa.subwindow_mode = IncludeInferiors; primaryPicture = XRenderCreatePicture(xfc->display, xfc->primary, picFormat, CPSubwindowMode, &pa); windowPicture = XRenderCreatePicture(xfc->display, xfc->window->handle, picFormat, CPSubwindowMode, &pa); transform.matrix[0][0] = XDoubleToFixed(1); transform.matrix[0][1] = XDoubleToFixed(0); transform.matrix[0][2] = XDoubleToFixed(0); transform.matrix[1][0] = XDoubleToFixed(0); transform.matrix[1][1] = XDoubleToFixed(1); transform.matrix[1][2] = XDoubleToFixed(0); transform.matrix[2][0] = XDoubleToFixed(0); transform.matrix[2][1] = XDoubleToFixed(0); transform.matrix[2][2] = XDoubleToFixed(xfc->settings->ScalingFactor); if( (w != 0) && (h != 0) ) { if(scale == TRUE) { xr.x = x * xfc->settings->ScalingFactor; xr.y = y * xfc->settings->ScalingFactor; xr.width = (w+1) * xfc->settings->ScalingFactor; xr.height = (h+1) * xfc->settings->ScalingFactor; } else { xr.x = x; xr.y = y; xr.width = w; xr.height = h; } XRenderSetPictureClipRectangles(xfc->display, primaryPicture, 0, 0, &xr, 1); } XRenderSetPictureTransform(xfc->display, primaryPicture, &transform); XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, 0, 0, 0, 0, xfc->offset_x, xfc->offset_y, xfc->currentWidth, xfc->currentHeight); XRenderFreePicture(xfc->display, primaryPicture); XRenderFreePicture(xfc->display, windowPicture); #endif }
inline QEdge(const QPointF &pt1, const QPointF &pt2) { p1.x = XDoubleToFixed(pt1.x()); p1.y = XDoubleToFixed(pt1.y()); p2.x = XDoubleToFixed(pt2.x()); p2.y = XDoubleToFixed(pt2.y()); m = (pt1.x() - pt2.x()) ? (pt1.y() - pt2.y()) / (pt1.x() - pt2.x()) : 0; im = m ? 1/m : 0; b = pt1.y() - m * pt1.x(); vertical = p1.x == p2.x; horizontal = p1.y == p2.y; }
inline qreal xAt(const qreal &y) const { Q_ASSERT(p1.y != p2.y); XFixed yf = XDoubleToFixed(y); if (yf == p1.y) return XFixedToDouble(p1.x); else if (yf == p2.y) return XFixedToDouble(p2.x); return (!vertical) ? (((y - b)*im)) : pf1.x(); }
static XFixed XRenderComputeIntersect (XLineFixed *l1, XLineFixed *l2) { /* * x = m1y + b1 * x = m2y + b2 * m1y + b1 = m2y + b2 * y * (m1 - m2) = b2 - b1 * y = (b2 - b1) / (m1 - m2) */ double m1 = XRenderComputeInverseSlope (l1); double b1 = XRenderComputeXIntercept (l1, m1); double m2 = XRenderComputeInverseSlope (l2); double b2 = XRenderComputeXIntercept (l2, m2); return XDoubleToFixed ((b2 - b1) / (m1 - m2)); }
static void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h) { XTransform transform; Picture windowPicture; Picture primaryPicture; XRenderPictureAttributes pa; XRenderPictFormat* picFormat; double xScalingFactor; double yScalingFactor; int x2; int y2; if (xfc->scaledWidth <= 0 || xfc->scaledHeight <= 0) { WLog_ERR(TAG, "the current window dimensions are invalid"); return; } if (xfc->sessionWidth <= 0 || xfc->sessionHeight <= 0) { WLog_ERR(TAG, "the window dimensions are invalid"); return; } xScalingFactor = xfc->sessionWidth / (double)xfc->scaledWidth; yScalingFactor = xfc->sessionHeight / (double)xfc->scaledHeight; XSetFillStyle(xfc->display, xfc->gc, FillSolid); XSetForeground(xfc->display, xfc->gc, 0); /* Black out possible space between desktop and window borders */ { XRectangle box1 = { 0, 0, xfc->window->width, xfc->window->height }; XRectangle box2 = { xfc->offset_x, xfc->offset_y, xfc->scaledWidth, xfc->scaledHeight }; Region reg1 = XCreateRegion(); Region reg2 = XCreateRegion(); XUnionRectWithRegion(&box1, reg1, reg1); XUnionRectWithRegion(&box2, reg2, reg2); if (XSubtractRegion(reg1, reg2, reg1) && !XEmptyRegion(reg1)) { XSetRegion(xfc->display, xfc->gc, reg1); XFillRectangle(xfc->display, xfc->window->handle, xfc->gc, 0, 0, xfc->window->width, xfc->window->height); XSetClipMask(xfc->display, xfc->gc, None); } XDestroyRegion(reg1); XDestroyRegion(reg2); } picFormat = XRenderFindVisualFormat(xfc->display, xfc->visual); pa.subwindow_mode = IncludeInferiors; primaryPicture = XRenderCreatePicture(xfc->display, xfc->primary, picFormat, CPSubwindowMode, &pa); windowPicture = XRenderCreatePicture(xfc->display, xfc->window->handle, picFormat, CPSubwindowMode, &pa); XRenderSetPictureFilter(xfc->display, primaryPicture, FilterBilinear, 0, 0); transform.matrix[0][0] = XDoubleToFixed(xScalingFactor); transform.matrix[0][1] = XDoubleToFixed(0.0); transform.matrix[0][2] = XDoubleToFixed(0.0); transform.matrix[1][0] = XDoubleToFixed(0.0); transform.matrix[1][1] = XDoubleToFixed(yScalingFactor); transform.matrix[1][2] = XDoubleToFixed(0.0); transform.matrix[2][0] = XDoubleToFixed(0.0); transform.matrix[2][1] = XDoubleToFixed(0.0); transform.matrix[2][2] = XDoubleToFixed(1.0); /* calculate and fix up scaled coordinates */ x2 = x + w; y2 = y + h; x = floor(x / xScalingFactor) - 1; y = floor(y / yScalingFactor) - 1; w = ceil(x2 / xScalingFactor) + 1 - x; h = ceil(y2 / yScalingFactor) + 1 - y; XRenderSetPictureTransform(xfc->display, primaryPicture, &transform); XRenderComposite(xfc->display, PictOpSrc, primaryPicture, 0, windowPicture, x, y, 0, 0, xfc->offset_x + x, xfc->offset_y + y, w, h); XRenderFreePicture(xfc->display, primaryPicture); XRenderFreePicture(xfc->display, windowPicture); }
static gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event, gpointer data) { GdkGC *gc; XTransform transform; double scale; int wx, wy, ww, wh; int frame_left, frame_right, frame_top, frame_bottom; int thumbnail_width, thumbnail_height; int offset_x, offset_y; SSWindow *window; SSThumbnailer *thumbnailer; Display *display; display = gdk_x11_get_default_xdisplay (); thumbnailer = (SSThumbnailer *) data; window = thumbnailer->window; if (thumbnailer->thumbnail_pixmap == NULL) { initialize_thumbnailer_pictures (thumbnailer); } gc = gdk_gc_new (thumbnailer->thumbnail_pixmap); ss_xinerama_get_frame_extents ( // TODO - should we cut out the ->workspace in the line below? window->workspace->screen->xinerama, window, &frame_left, &frame_right, &frame_top, &frame_bottom); wnck_window_get_geometry (window->wnck_window, &wx, &wy, &ww, &wh); scale = ww > wh ? ww : wh; scale /= (double) THUMBNAIL_SIZE; thumbnail_width = thumbnail_height = THUMBNAIL_SIZE; if (ww > wh) { thumbnail_height = wh * THUMBNAIL_SIZE / ww; } else { thumbnail_width = ww * THUMBNAIL_SIZE / wh; } transform.matrix[0][0] = XDoubleToFixed (scale); transform.matrix[0][1] = XDoubleToFixed (0.0); transform.matrix[0][2] = XDoubleToFixed (-frame_left * (scale - 1.0)); transform.matrix[1][0] = XDoubleToFixed (0.0); transform.matrix[1][1] = XDoubleToFixed (scale); transform.matrix[1][2] = XDoubleToFixed (-frame_top * (scale - 1.0)); transform.matrix[2][0] = XDoubleToFixed (0.0); transform.matrix[2][1] = XDoubleToFixed (0.0); transform.matrix[2][2] = XDoubleToFixed (1.0); XRenderSetPictureTransform (display, thumbnailer->window_picture, &transform); XRenderComposite (display, PictOpSrc, thumbnailer->window_picture, None, thumbnailer->thumbnail_picture, 0, 0, 0, 0, 0, 0, THUMBNAIL_SIZE, THUMBNAIL_SIZE); offset_x = widget->allocation.x + (THUMBNAIL_SIZE - thumbnail_width) / 2; offset_y = widget->allocation.y + (THUMBNAIL_SIZE - thumbnail_height) / 2; gdk_draw_drawable (thumbnailer->drawing_area->window, gc, thumbnailer->thumbnail_pixmap, 0, 0, offset_x, offset_y, thumbnail_width, thumbnail_height); gdk_draw_rectangle (thumbnailer->drawing_area->window, thumbnailer->drawing_area->style->black_gc, FALSE, offset_x, offset_y, thumbnail_width - 1, thumbnail_height - 1); g_object_unref (gc); return FALSE; }
void old_tesselate_polygon(QVector<XTrapezoid> *traps, const QPointF *pg, int pgSize, bool winding) { QVector<QEdge> edges; edges.reserve(128); qreal ymin(INT_MAX/256); qreal ymax(INT_MIN/256); //painter.begin(pg, pgSize); if (pg[0] != pg[pgSize-1]) qWarning() << Q_FUNC_INFO << "Malformed polygon (first and last points must be identical)"; // generate edge table // qDebug() << "POINTS:"; for (int x = 0; x < pgSize-1; ++x) { QEdge edge; QPointF p1(Q27Dot5ToDouble(FloatToQ27Dot5(pg[x].x())), Q27Dot5ToDouble(FloatToQ27Dot5(pg[x].y()))); QPointF p2(Q27Dot5ToDouble(FloatToQ27Dot5(pg[x+1].x())), Q27Dot5ToDouble(FloatToQ27Dot5(pg[x+1].y()))); // qDebug() << " " // << p1; edge.winding = p1.y() > p2.y() ? 1 : -1; if (edge.winding > 0) qSwap(p1, p2); edge.p1.x = XDoubleToFixed(p1.x()); edge.p1.y = XDoubleToFixed(p1.y()); edge.p2.x = XDoubleToFixed(p2.x()); edge.p2.y = XDoubleToFixed(p2.y()); edge.m = (p1.y() - p2.y()) / (p1.x() - p2.x()); // line derivative edge.b = p1.y() - edge.m * p1.x(); // intersection with y axis edge.m = edge.m != 0.0 ? 1.0 / edge.m : 0.0; // inverted derivative edges.append(edge); ymin = qMin(ymin, qreal(XFixedToDouble(edge.p1.y))); ymax = qMax(ymax, qreal(XFixedToDouble(edge.p2.y))); } QList<const QEdge *> et; // edge list for (int i = 0; i < edges.size(); ++i) et.append(&edges.at(i)); // sort edge table by min y value qSort(et.begin(), et.end(), compareEdges); // 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 = currentY = 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 = 0; 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; } if (isects.size()%2 != 1) qFatal("%s: number of intersection points must be odd", Q_FUNC_INFO); // sort intersection points qSort(&isects[0], &isects[isects.size()-1], compareIntersections); // qDebug() << "INTERSECTION_POINTS:"; // for (int i = 0; i < isects.size(); ++i) // qDebug() << isects[i].edge << isects[i].x; 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; //painter.addTrapezoid(&toXTrapezoid(yf, next_yf, *left, *right)); traps->append(toXTrapezoid(yf, next_yf, *left, *right)); } } else { // odd-even fill rule for (int i = 0; i < isects.size()-2; i += 2) { //painter.addTrapezoid(&toXTrapezoid(yf, next_yf, *isects[i].edge, *isects[i+1].edge)); 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; // } // } // } //static int i = 0; //QImage img = painter.end(); //img.save(QString("res%1.png").arg(i++), "PNG"); }
void PixmapRenderer::drawPixmap( QPainter& painter, QPixmap const& pixmap) { #if !defined(Q_WS_X11) drawPixmapNoXRender(painter, pixmap); #else QPaintDevice* const dev = painter.device(); QPoint offset; // Both x and y will be either zero or negative. QPaintDevice* const redir_dev = QPainter::redirected(painter.device(), &offset); QPaintDevice* const paint_dev = redir_dev ? redir_dev : dev; #if defined(ENABLE_OPENGL) if (dynamic_cast<QGLWidget*>(paint_dev)) { drawPixmapNoXRender(painter, pixmap); return; } #endif QRect const device_rect( QRect(0, 0, dev->width(), dev->height()).translated(-offset) ); QRectF const src_rect(pixmap.rect()); Display* const dpy = QX11Info::display(); Picture const src_pict = pixmap.x11PictureHandle(); Picture dst_pict = 0; if (QWidget* widget = dynamic_cast<QWidget*>(paint_dev)) { dst_pict = widget->x11PictureHandle(); } else if (QPixmap* pixmap = dynamic_cast<QPixmap*>(paint_dev)) { dst_pict = pixmap->x11PictureHandle(); } if (!dst_pict) { drawPixmapNoXRender(painter, pixmap); return; } // Note that device transform already accounts for offset // within a destination surface. QTransform const src_to_dst(painter.deviceTransform()); QTransform const dst_to_src(src_to_dst.inverted()); QPolygonF const dst_poly(src_to_dst.map(src_rect)); XTransform xform = {{ { XDoubleToFixed(dst_to_src.m11()), XDoubleToFixed(dst_to_src.m21()), XDoubleToFixed(dst_to_src.m31()) }, { XDoubleToFixed(dst_to_src.m12()), XDoubleToFixed(dst_to_src.m22()), XDoubleToFixed(dst_to_src.m32()) }, { XDoubleToFixed(dst_to_src.m13()), XDoubleToFixed(dst_to_src.m23()), XDoubleToFixed(dst_to_src.m33()) } }}; XRenderSetPictureTransform(dpy, src_pict, &xform); char const* filter = "fast"; if (painter.testRenderHint(QPainter::SmoothPixmapTransform)) { filter = "good"; } XRenderSetPictureFilter(dpy, src_pict, filter, 0, 0); QRectF const dst_rect_precise(dst_poly.boundingRect()); QRect const dst_rect_fitting( QPoint( int(ceil(dst_rect_precise.left())), int(ceil(dst_rect_precise.top())) ), QPoint( int(floor(dst_rect_precise.right())) - 1, int(floor(dst_rect_precise.bottom())) - 1 ) ); QRect dst_bounding_rect(device_rect); if (painter.hasClipping()) { QRect const clip_rect( src_to_dst.map(painter.clipPath()).boundingRect().toRect() ); dst_bounding_rect = dst_bounding_rect.intersected(clip_rect); } QRect const dst_rect(dst_rect_fitting.intersect(dst_bounding_rect)); // Note that XRenderComposite() expects destination coordinates // everywhere, even for source picture origin. XRenderComposite( dpy, PictOpSrc, src_pict, 0, dst_pict, dst_rect.left(), dst_rect.top(), 0, 0, dst_rect.left(), dst_rect.top(), dst_rect.width(), dst_rect.height() ); #endif }
pictw_t * simg_postprocess(session_t *ps, pictw_t *src, enum pict_posp_mode mode, int twidth, int theight, enum align alg, enum align valg, const XRenderColor *pc) { static const XRenderColor XRC_TRANS = { .red = 0, .green = 0, .blue = 0, .alpha = 0 }; if (!pc) pc = &XRC_TRANS; const int depth = 32; pictw_t *dest = NULL; bool transformed = false; if (!src) { if (twidth && theight) { if (!(dest = create_pictw(ps, twidth, theight, depth))) printfef("(): Failed to create Picture."); else XRenderFillRectangle(ps->dpy, PictOpSrc, dest->pict, pc, 0, 0, twidth, theight); } goto simg_postprocess_end; } if (!(twidth || theight) || (twidth == src->width && theight == src->height)) return src; // Determine composite paramaters. We have to do this before create // Picture because the width/height may need to be calculated. int width = src->width, height = src->height; if (!twidth) twidth = (double) theight / height * width; else if (!theight) theight = (double) twidth / width * height; double ratio_x = 1.0, ratio_y = 1.0; switch (mode) { case PICTPOSP_ORIG: break; case PICTPOSP_TILE: break; case PICTPOSP_SCALE: case PICTPOSP_SCALEK: case PICTPOSP_SCALEE: case PICTPOSP_SCALEEK: { if (twidth) ratio_x = (double) twidth / width; if (theight) ratio_y = (double) theight / height; if (PICTPOSP_SCALEK == mode || PICTPOSP_SCALEEK == mode) ratio_x = ratio_y = MIN(ratio_x, ratio_y); if (PICTPOSP_SCALEE == mode || PICTPOSP_SCALEEK == mode) { ratio_x = MAX(1.0f, ratio_x); ratio_y = MAX(1.0f, ratio_y); } width *= ratio_x; height *= ratio_y; } break; default: assert(0); break; } if (!(dest = create_pictw(ps, twidth, theight, depth))) { printfef("(): Failed to create Picture."); goto simg_postprocess_end; } int x = 0, y = 0; int num_x = 1, num_y = 1; if (PICTPOSP_TILE == mode) { // num_x = ceil((float) twidth / width); // num_y = ceil((float) theight / height); num_x = twidth / width; num_y = theight / height; } switch (alg) { case ALIGN_LEFT: break; case ALIGN_RIGHT: x = twidth - width * num_x; break; case ALIGN_MID: x = (twidth - width * num_x) / 2; break; }; switch (valg) { case ALIGN_LEFT: break; case ALIGN_RIGHT: y = theight - height * num_y; break; case ALIGN_MID: y = (theight - height * num_y) / 2; break; }; x = MAX(x, 0); y = MAX(y, 0); int x2 = MIN(x + width * num_x, twidth), y2 = MIN(y + height * num_y, theight); /* if (pc->alpha) */ { if (src->depth >= 32) XRenderFillRectangle(ps->dpy, PictOpSrc, dest->pict, pc, 0, 0, twidth, theight); else { XRenderFillRectangle(ps->dpy, PictOpSrc, dest->pict, pc, 0, 0, twidth, y); XRenderFillRectangle(ps->dpy, PictOpSrc, dest->pict, pc, 0, y2, twidth, theight - y2); XRenderFillRectangle(ps->dpy, PictOpSrc, dest->pict, pc, 0, y, x, y2 - y); XRenderFillRectangle(ps->dpy, PictOpSrc, dest->pict, pc, x2, y, twidth - x2, y2 - y); } } if (src->pict) { if (1.0 != ratio_x || 1.0 != ratio_y) { XTransform transform = { .matrix = { { XDoubleToFixed(1.0 / ratio_x), XDoubleToFixed(0.0), XDoubleToFixed(0.0) }, { XDoubleToFixed(0.0), XDoubleToFixed(1.0 / ratio_y), XDoubleToFixed(0.0) }, { XDoubleToFixed(0.0), XDoubleToFixed(0.0), XDoubleToFixed(1.0) }, } }; transformed = true; XRenderSetPictureTransform(ps->dpy, src->pict, &transform); }
int X11Grabber::grabFrame(Image<ColorRgb> & image) { if (_XRenderAvailable && !_useXGetImage) { double scale_x = static_cast<double>(_windowAttr.width / _horizontalDecimation) / static_cast<double>(_windowAttr.width); double scale_y = static_cast<double>(_windowAttr.height / _verticalDecimation) / static_cast<double>(_windowAttr.height); double scale = std::min(scale_y, scale_x); _transform = { { { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(scale) } } }; XRenderSetPictureTransform (_x11Display, _srcPicture, &_transform); XRenderComposite( _x11Display, // dpy PictOpSrc, // op _srcPicture, // src None, // mask _dstPicture, // dst _cropLeft / _horizontalDecimation, // src_x _cropLeft _cropTop / _verticalDecimation, // src_y _cropTop 0, // mask_x 0, // mask_y 0, // dst_x 0, // dst_y _croppedWidth, // width _croppedHeight); // height XSync(_x11Display, False); if (_XShmAvailable) { XShmGetImage(_x11Display, _pixmap, _xImage, 0, 0, AllPlanes); } else { _xImage = XGetImage(_x11Display, _pixmap, 0, 0, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); } } else { if (_XShmAvailable && !_useXGetImage) { XShmGetImage(_x11Display, _window, _xImage, _cropLeft, _cropTop, AllPlanes); } else { _xImage = XGetImage(_x11Display, _window, _cropLeft, _cropTop, _croppedWidth, _croppedHeight, AllPlanes, ZPixmap); } } if (_xImage == nullptr) { Error(_log, "Grab Failed!"); return -1; } _imageResampler.processImage(reinterpret_cast<const uint8_t *>(_xImage->data), _xImage->width, _xImage->height, _xImage->bytes_per_line, PIXELFORMAT_BGR32, image); return 0; }
void Canvas::copyScaleCanvas(const Canvas* canvas, const Rect& src, const Rect& dst) { if (src.size == dst.size) { copyCanvas(canvas, src, dst.origin); return; } if (dst.size.w <= 0 || dst.size.h <= 0) return; XTransform xform = {{ { XDoubleToFixed((double)src.size.w / dst.size.w), XDoubleToFixed(0), XDoubleToFixed(src.origin.x) }, { XDoubleToFixed(0), XDoubleToFixed((double)src.size.h / dst.size.h), XDoubleToFixed(src.origin.y) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }, }}; XRenderSetPictureTransform(display()->xdisplay(), canvas->xpicture(), &xform); Point offset = absolutePosition(); XRenderComposite( display()->xdisplay(), PictOpOver, canvas->xpicture(), None, xpicture(), 0, 0, 0, 0, dst.origin.x + offset.x, dst.origin.y + offset.y, dst.size.w, dst.size.h ); XTransform identity = {{ { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }, }}; XRenderSetPictureTransform(display()->xdisplay(), canvas->xpicture(), &identity); }
void Canvas::copyRotatedCanvas(const Canvas* canvas, const Rect& src, const Point& origin) { XTransform xform = {{ { XDoubleToFixed(0), XDoubleToFixed(-1), XDoubleToFixed(0) }, { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }, }}; XRenderSetPictureTransform(display()->xdisplay(), canvas->xpicture(), &xform); Point offset = absolutePosition(); XRenderComposite( display()->xdisplay(), PictOpOver, canvas->xpicture(), None, xpicture(), // src.origin.x, src.origin.y, // 0, 0, // origin.x + offset.x, origin.y + offset.y, // src.size.w, src.size.h src.origin.x, -src.size.w, 0, 0, origin.x + offset.x, origin.y + offset.y, src.size.w, src.size.h ); XTransform identity = {{ { XDoubleToFixed(1), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(1), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }, }}; XRenderSetPictureTransform(display()->xdisplay(), canvas->xpicture(), &identity); }
int InitFixedTrapezoids(XParms xp, Parms p, int reps) { int i, numTraps; int rows; int x, y; int size, skew; XTrapezoid *curTrap; XRenderColor color; pgc = xp->fggc; size = p->special; numTraps = p->objects; traps = (XTrapezoid *)malloc(numTraps * sizeof(XTrapezoid)); curTrap = traps; x = size; y = 0; rows = 0; skew = size; aadraw = XftDrawCreate (xp->d, xp->w, xp->vinfo.visual, xp->cmap); if (p->font && !strcmp (p->font, "add")) { XRenderPictFormat templ; templ.type = PictTypeDirect; templ.depth = 8; templ.direct.alpha = 0; templ.direct.alphaMask = 0xff; maskFormat = XRenderFindFormat (xp->d, PictFormatType | PictFormatDepth | PictFormatAlpha | PictFormatAlphaMask, &templ, 0); } else maskFormat = 0; color.red = 0; color.green = 0; color.blue = 0; color.alpha = 0xffff; if (!XftColorAllocValue (xp->d, xp->vinfo.visual, xp->cmap, &color, &aablack)) { XftDrawDestroy (aadraw); aadraw = 0; return 0; } color.red = 0xffff; color.green = 0xffff; color.blue = 0xffff; color.alpha = 0xffff; if (!XftColorAllocValue (xp->d, xp->vinfo.visual, xp->cmap, &color, &aawhite)) { XftDrawDestroy (aadraw); aadraw = 0; return 0; } for (i = 0; i != p->objects; i++, curTrap ++) { curTrap->top = XDoubleToFixed (y); curTrap->bottom = XDoubleToFixed (y + size); curTrap->left.p1.x = XDoubleToFixed (x - skew); curTrap->left.p1.y = XDoubleToFixed (y); curTrap->left.p2.x = XDoubleToFixed (x + skew - size); curTrap->left.p2.y = XDoubleToFixed (y + size); curTrap->right.p1.x = XDoubleToFixed (x - skew + size); curTrap->right.p1.y = XDoubleToFixed (y); curTrap->right.p2.x = XDoubleToFixed (x + skew); curTrap->right.p2.y = XDoubleToFixed (y + size); skew--; if (skew < 0) skew = size; y += size; rows++; if (y + size > HEIGHT || rows == MAXROWS) { rows = 0; y = 0; x += 2 * size; if (x + size > WIDTH) { x = size; } } } SetFillStyle(xp, p); return reps; }
void XRenderCompositeDoublePoly (Display *dpy, int op, Picture src, Picture dst, _Xconst XRenderPictFormat *maskFormat, int xSrc, int ySrc, int xDst, int yDst, _Xconst XPointDouble *fpoints, int npoints, int winding) { Edge *edges; XTrapezoid *traps; int i, nedges, ntraps; XFixed x, y, prevx = 0, prevy = 0, firstx = 0, firsty = 0; XFixed top = 0, bottom = 0; /* GCCism */ edges = (Edge *) Xmalloc (npoints * sizeof (Edge) + (npoints * npoints * sizeof (XTrapezoid))); if (!edges) return; traps = (XTrapezoid *) (edges + npoints); nedges = 0; for (i = 0; i <= npoints; i++) { if (i == npoints) { x = firstx; y = firsty; } else { x = XDoubleToFixed (fpoints[i].x); y = XDoubleToFixed (fpoints[i].y); } if (i) { if (y < top) top = y; else if (y > bottom) bottom = y; if (prevy < y) { edges[nedges].edge.p1.x = prevx; edges[nedges].edge.p1.y = prevy; edges[nedges].edge.p2.x = x; edges[nedges].edge.p2.y = y; edges[nedges].clockWise = True; nedges++; } else if (prevy > y) { edges[nedges].edge.p1.x = x; edges[nedges].edge.p1.y = y; edges[nedges].edge.p2.x = prevx; edges[nedges].edge.p2.y = prevy; edges[nedges].clockWise = False; nedges++; } /* drop horizontal edges */ } else { top = y; bottom = y; firstx = x; firsty = y; } prevx = x; prevy = y; } ntraps = XRenderComputeTrapezoids (edges, nedges, winding, traps); /* XXX adjust xSrc/xDst */ XRenderCompositeTrapezoids (dpy, op, src, dst, maskFormat, xSrc, ySrc, traps, ntraps); Xfree (edges); }
void Thumbnail::onResize() { Image* oldImage = _image; if (_image) { XftDrawDestroy(_xftDraw); XFreeGC(_dpy, _gc); } _image = new Image(_dpy, _width, _height); _gc = XCreateGC(_dpy, _image->pixmap(), 0, 0); XSetGraphicsExposures(_dpy, _gc, false); _xftDraw = XftDrawCreate(_dpy, _image->pixmap(), XTools::rgbaVisual()->visual, DefaultColormap(_dpy, DefaultScreen(_dpy))); XWindowAttributes attrs; XGetWindowAttributes(_dpy, _clientWindow, &attrs); _clientWidth = attrs.width; _clientHeight= attrs.height; #ifdef MAEMO4 _clientDecoX = attrs.x; _clientDecoY = attrs.y; #endif int borderWidth = Settings::instance()->borderWidth(); int headerHeight = Resources::instance()->headerMiddle()->height(); int oldClientScaledWidth = _clientScaledWidth; int oldClientScaledHeight= _clientScaledHeight; _clientScaledWidth = _width - 2 * borderWidth; _clientScaledHeight = _height - headerHeight - borderWidth; double scale = _clientScaledWidth; scale /= _clientWidth; _clientDecoXScaled = (int)round(scale * _clientDecoX); _clientDecoYScaled = (int)round(scale * _clientDecoY); _clientOffsetX = borderWidth; _clientOffsetY = headerHeight; XTransform xform = {{ { XDoubleToFixed(1.0/scale), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(1.0/scale), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) }, } }; XRenderSetPictureTransform(_dpy, _clientPict, &xform); if (_minimized && oldImage != 0) { // Workaround for corner case: if this function is called when // client is minimized, we need to rescale cached pixmap, because // can't grab new picture from window // Yes, this function MAY be called when client is minimised - for // example when thumbnail needs to be resized because number of // windows changed Image* temp = new Image(_dpy, _clientScaledWidth, _clientScaledHeight, 32); XTransform xform = {{ { XDoubleToFixed(((double)oldClientScaledWidth)/_clientScaledWidth), XDoubleToFixed(0), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(((double)oldClientScaledHeight)/_clientScaledHeight), XDoubleToFixed(0) }, { XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(1) } } }; XRenderSetPictureTransform(_dpy, oldImage->picture(), &xform); XRenderComposite(_dpy, PictOpSrc, oldImage->picture(), 0, temp->picture(), _clientOffsetX*_clientScaledWidth/oldClientScaledWidth, _clientOffsetY*_clientScaledHeight/oldClientScaledHeight, 0, 0, 0, 0, _clientScaledWidth, _clientScaledHeight ); XCopyArea(_dpy, temp->pixmap(), _image->pixmap(), _gc, 0, 0, _clientScaledWidth, _clientScaledHeight, _clientOffsetX, _clientOffsetY ); delete temp; } _previewValid = false; delete oldImage; redraw(); }
void PreviewCursor::load(const QString &name, const QString &theme) { Display *dpy = QPaintDevice::x11AppDisplay(); if(m_pict) XRenderFreePicture(dpy, m_pict); if(m_handle) XFreeCursor(dpy, m_handle); m_pict = 0; m_handle = 0; m_width = m_height = 0; // Load the preview cursor image XcursorImage *image = XcursorLibraryLoadImage(name.latin1(), theme.latin1(), previewSize); // If the theme doesn't have this cursor, load the default cursor for now if(!image) image = XcursorLibraryLoadImage("left_ptr", theme.latin1(), previewSize); // TODO The old classic X cursors if(!image) return; // Auto-crop the image (some cursor themes use a fixed image size // for all cursors, and doing this results in correctly centered images) cropCursorImage(image); m_pict = createPicture(image); m_width = image->width; m_height = image->height; // Scale the image if its height is greater than 2x the requested size if(m_height > previewSize * 2.0) { double factor = double(previewSize * 2.0 / m_height); XTransform xform = {{{XDoubleToFixed(1.0), XDoubleToFixed(0), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(1.0), XDoubleToFixed(0)}, {XDoubleToFixed(0), XDoubleToFixed(0), XDoubleToFixed(factor)}}}; XRenderSetPictureTransform(dpy, m_pict, &xform); m_width = int(m_width * factor); m_height = int(m_height * factor); } // We don't need this image anymore XcursorImageDestroy(image); // Load the actual cursor we will use int size = XcursorGetDefaultSize(dpy); XcursorImages *images = XcursorLibraryLoadImages(name.latin1(), theme.latin1(), size); if(images) { m_handle = XcursorImagesLoadCursor(dpy, images); XcursorImagesDestroy(images); } else { images = XcursorLibraryLoadImages("left_ptr", theme.latin1(), size); m_handle = XcursorImagesLoadCursor(dpy, images); XcursorImagesDestroy(images); } }