void KisColorSelector::drawRing(QPainter& painter, KisColorSelector::ColorRing& ring, const QRect& rect) { painter.setRenderHint(QPainter::Antialiasing, false); painter.resetTransform(); painter.translate(rect.width()/2, rect.height()/2); if (ring.pieced.size() > 1) { painter.rotate(-ring.getShift().degrees()); painter.scale(rect.width()/2, rect.height()/2); painter.setPen(Qt::NoPen); QBrush brush(Qt::SolidPattern); for(int i=0; i<ring.pieced.size(); ++i) { float hue = float(i) / float(ring.pieced.size()) + ring.getShift().scaled(0.0f, 1.0f); hue = (hue >= 1.0f) ? (hue - 1.0f) : hue; hue = (hue < 0.0f) ? (hue + 1.0f) : hue; KisColor color(hue, 1.0f, m_colorSpace); color.setS(ring.saturation); color.setX(getLight(m_light, hue, m_relativeLight)); brush.setColor(color.getQColor()); painter.fillPath(ring.pieced[i], brush); } } else { KisColor colors[7] = { KisColor(Qt::red , m_colorSpace), KisColor(Qt::yellow , m_colorSpace), KisColor(Qt::green , m_colorSpace), KisColor(Qt::cyan , m_colorSpace), KisColor(Qt::blue , m_colorSpace), KisColor(Qt::magenta, m_colorSpace), KisColor(Qt::red , m_colorSpace) }; QConicalGradient gradient(0, 0, 0); for(int i=0; i<=6; ++i) { qreal hue = float(i) / 6.0f; colors[i].setS(ring.saturation); colors[i].setX(getLight(m_light, hue, m_relativeLight)); gradient.setColorAt(hue, colors[i].getQColor()); } painter.scale(rect.width()/2, rect.height()/2); painter.fillPath(ring.pieced[0], QBrush(gradient)); } painter.resetTransform(); }
void KisColorSelector::drawOutline(QPainter& painter, const QRect& rect) { painter.setRenderHint(QPainter::Antialiasing, true); painter.resetTransform(); painter.translate(rect.x() + rect.width()/2, rect.y() + rect.height()/2); painter.scale(rect.width()/2, rect.height()/2); painter.setPen(QPen(QBrush(Qt::gray), 0.005)); if (getNumPieces() > 1) { for(int i=0; i<getNumRings(); ++i) { painter.resetTransform(); painter.translate(rect.x() + rect.width()/2, rect.y() + rect.height()/2); painter.scale(rect.width()/2, rect.height()/2); painter.rotate(-m_colorRings[i].getShift().degrees()); for(int j=0; j<m_colorRings[i].pieced.size(); ++j) painter.drawPath(m_colorRings[i].pieced[j]); } if (m_selectedRing >= 0 && m_selectedPiece >= 0) { painter.resetTransform(); painter.translate(rect.x() + rect.width()/2, rect.y() + rect.height()/2); painter.rotate(-m_colorRings[m_selectedRing].getShift().degrees()); painter.scale(rect.width()/2, rect.height()/2); painter.setPen(QPen(QBrush(Qt::red), 0.01)); painter.drawPath(m_colorRings[m_selectedRing].pieced[m_selectedPiece]); } } else { for(int i=0; i<getNumRings(); ++i) { qreal rad = m_colorRings[i].outerRadius; painter.drawEllipse(QRectF(-rad, -rad, rad*2.0, rad*2.0)); } } if (m_selectedRing >= 0) { qreal iRad = m_colorRings[m_selectedRing].innerRadius; qreal oRad = m_colorRings[m_selectedRing].outerRadius; painter.setPen(QPen(QBrush(Qt::red), 0.005)); painter.drawEllipse(QRectF(-iRad, -iRad, iRad*2.0, iRad*2.0)); painter.drawEllipse(QRectF(-oRad, -oRad, oRad*2.0, oRad*2.0)); if (getNumPieces() <= 1) { float c = std::cos(-m_selectedColor.getH() * PI2); float s = std::sin(-m_selectedColor.getH() * PI2); painter.drawLine(QPointF(c*iRad, s*iRad), QPointF(c*oRad, s*oRad)); } } }
void ImageBufferDataPrivateAccelerated::platformTransformColorSpace(const Vector<int>& lookUpTable) { QPainter* painter = paintDevice()->paintEngine()->painter(); QImage image = toQImage().convertToFormat(QImage::Format_ARGB32); ASSERT(!image.isNull()); uchar* bits = image.bits(); const int bytesPerLine = image.bytesPerLine(); for (int y = 0; y < image.height(); ++y) { quint32* scanLine = reinterpret_cast_ptr<quint32*>(bits + y * bytesPerLine); for (int x = 0; x < image.width(); ++x) { QRgb& pixel = scanLine[x]; pixel = qRgba(lookUpTable[qRed(pixel)], lookUpTable[qGreen(pixel)], lookUpTable[qBlue(pixel)], qAlpha(pixel)); } } painter->save(); painter->resetTransform(); painter->setOpacity(1.0); painter->setClipping(false); painter->setCompositionMode(QPainter::CompositionMode_Source); // Should coordinates be flipped? painter->drawImage(QPoint(0,0), image); painter->restore(); }
void DrawMana( QPainter& painter, int x, int y, int width, int height, int mana ) const { // Draw mana QPen origPen = painter.pen(); QPen pen( QColor( 0, 52, 113 ) ); pen.setCosmetic( true ); pen.setWidth( 1 ); painter.setPen( pen ); QBrush brush( QColor( 40, 119, 238 ) ); painter.setBrush( brush ); QTransform transform; painter.translate( x + width * 0.5, y + height * 0.5 ); painter.scale( width * 0.8, height * 0.8 ); static const QPointF points[5] = { QPointF( 0.0, -1.0 ), QPointF( 1.0, -0.2 ), QPointF( 0.6, 1.0 ), QPointF( -0.6, 1.0 ), QPointF( -1.0, -0.2 ), }; painter.drawConvexPolygon( points, 5 ); painter.resetTransform(); painter.setPen( origPen ); painter.drawText( x, y, width, height, Qt::AlignCenter | Qt::AlignVCenter, QString::number( mana ) ); }
/** * Calls virtual drawShape() method to draw the actial shape. * Draws bounding rect and control points if the shape is selected. * * @param painter :: QPainter used for drawing. */ void Shape2D::draw(QPainter& painter) const { if (!m_visible) return; painter.setPen(m_color); this->drawShape(painter); if (m_editing || m_selected) { QColor c(255, 255, 255, 100); painter.setPen(c); painter.drawRect(m_boundingRect.toQRectF()); size_t np = NCommonCP; double rsize = 2; int alpha = 100; if (m_editing) { // if editing show all CP, make them bigger and opaque np = getNControlPoints(); rsize = sizeCP; alpha = 255; } for (size_t i = 0; i < np; ++i) { QPointF p = painter.transform().map(getControlPoint(i)); QRectF r(p - QPointF(rsize, rsize), p + QPointF(rsize, rsize)); painter.save(); painter.resetTransform(); QColor c(255, 255, 255, alpha); painter.fillRect(r, c); r.adjust(-1, -1, 0, 0); painter.setPen(QColor(0, 0, 0, alpha)); painter.drawRect(r); painter.restore(); } } }
void MaxFlowVisualizer::drawEdge(const Edge &edge, QPainter &painter) const { QPen pen; pen.setWidth(3); // Ребро, которое считается "допустимым" по алгоритму, выделяем черным. if (relabelToFrontAlgo.getVertexHeight(edge.getFirstVertexIndex()) == relabelToFrontAlgo.getVertexHeight(edge.getSecondVertexIndex()) + 1) { pen.setColor(Qt::black); } else { pen.setColor(Qt::gray); } if (edge.getFlow() != 0) { pen.setColor(Qt::darkBlue); } // Если в последнем действии алгоритма произошло проталкивание по этому ребру, // то выделим его красным. if (lastAlgoAction.getType() == AlgoAction::ACTION_PUSH && lastAlgoAction.getEdgeInfo() == edge) { pen.setColor(Qt::red); } painter.setPen(pen); QPoint pointFrom(verteciesList[edge.getFirstVertexIndex()].getCenterCoordX(), verteciesList[edge.getFirstVertexIndex()].getCenterCoordY()); QPoint pointTo(verteciesList[edge.getSecondVertexIndex()].getCenterCoordX(), verteciesList[edge.getSecondVertexIndex()].getCenterCoordY()); double length = sqrt(pow(pointFrom.x() - pointTo.x(), 2) + pow(pointFrom.y() - pointTo.y(), 2)); long vertexRaduis = verteciesList[edge.getSecondVertexIndex()].getRadius(); QPoint offsetVector((pointFrom.x() - pointTo.x()) * vertexRaduis / length, (pointFrom.y() - pointTo.y()) * vertexRaduis / length); QPoint arrow((pointFrom.x() - pointTo.x()) * 20 / length, (pointFrom.y() - pointTo.y()) * 20 / length); // Рисование стрелки (самих маленьких боковых линий). // Перенесем систему координат в точку конца ребра (ориенированного). // Возьмем маленький отрезок ребра, и нарисуем его, повернув при этом систуму координат // на +30 и -30 градусов соответственно относительно исходного ребра. // Получилась стрелка -> // После этого восстановим систему координат. painter.setPen(pen); painter.drawLine(pointFrom, pointTo); painter.translate(pointTo.x(), pointTo.y()); // Еще нужно отступить от конца ребра на радиус вершины // (т.к. ребро идет от центра к центру). painter.translate(offsetVector.x(), offsetVector.y()); painter.rotate(30); painter.drawLine(QPoint(0, 0), arrow); painter.rotate(-60); painter.drawLine(QPoint(0, 0), arrow); painter.resetTransform(); // Выводим информацию о ребре (flow | capacity) по середине ребра. if (state == ALGORITHM_RUN || (state == ALGORITHM_TERM && edge.flow != 0)) { QPen penForEdgeInfo; penForEdgeInfo.setColor(Qt::darkGreen); painter.setPen(penForEdgeInfo); std::string edgeInfo = "(" + std::to_string(edge.getFlow()) + " | " + std::to_string(edge.getCapacity()) + ")"; painter.drawText(pointFrom.x() + (pointTo.x() - pointFrom.x()) / 2, pointFrom.y() + (pointTo.y() - pointFrom.y()) / 2, edgeInfo.c_str()); } }
void QSplineEdit::paintControlHandles(QPainter & pnt) { QBrush br(Qt::lightGray); QPen pn(Qt::black); pnt.setPen(pn); pnt.setBrush(br); QRectF square(-4,-4,8,8); pnt.translate(toDrawSpace(0, m_startValue)); pnt.drawRect(square); pnt.resetTransform(); pnt.translate(toDrawSpace(1, m_endValue)); pnt.drawRect(square); pnt.resetTransform(); pnt.translate(toDrawSpace(m_startCvx, m_startCvy)); pnt.drawEllipse(square); pnt.resetTransform(); pnt.translate(toDrawSpace(m_endCvx, m_endCvy)); pnt.drawEllipse(square); }
void OGSprite::Paint(QPainter& p, const QRectF& a_target) { if (!m_visible) return; p.setOpacity(m_alpha); p.resetTransform(); if (GetAngle() != 0) p.rotate(GetAngle()); m_source->Render(p, a_target, m_clipRect); }
void PHISurfaceEffect::draw( QPainter *painter ) { /* QPoint offset; QPixmap pixmap; if ( sourceIsPixmap() ) { // No point in drawing in device coordinates (pixmap will be scaled anyways). pixmap=sourcePixmap( Qt::LogicalCoordinates, &offset ); } else { // Draw pixmap in device coordinates to avoid pixmap scaling; pixmap=sourcePixmap( Qt::DeviceCoordinates, &offset ); painter->setWorldTransform( QTransform() ); } QImage img=pixmap.toImage(); img=PHI::getSurfacedImage( img, _yOff, _size ); painter->drawImage( offset, img ); */ QRectF brect=sourceBoundingRect( Qt::LogicalCoordinates ); QImage img( static_cast<int>(brect.width()+1), static_cast<int>(brect.height()+_size+_yOff), QImage::Format_ARGB32_Premultiplied ); QPainter pixPainter; pixPainter.begin( &img ); pixPainter.setRenderHints( painter->renderHints() ); pixPainter.setCompositionMode( QPainter::CompositionMode_Clear ); pixPainter.fillRect( 0., 0., brect.width()+1., brect.height()+_size+_yOff+1, Qt::transparent ); pixPainter.setCompositionMode( QPainter::CompositionMode_SourceOver ); drawSource( &pixPainter ); QTransform t; t.rotate( 180., Qt::XAxis ); t.translate( 0., (-brect.height()*2.)-_yOff+1. ); pixPainter.setTransform( t ); drawSource( &pixPainter ); pixPainter.resetTransform(); pixPainter.translate( 0., brect.height()+_yOff ); QLinearGradient gradient( 0., 0., 0., 1.0 ); gradient.setColorAt( 0., QColor( 0, 0, 0, 220 ) ); gradient.setColorAt( 0.78, QColor( 0, 0, 0, 30 ) ); gradient.setColorAt( 1., Qt::transparent ); gradient.setCoordinateMode( QGradient::ObjectBoundingMode ); pixPainter.setCompositionMode( QPainter::CompositionMode_DestinationIn ); pixPainter.fillRect( 0., 0., brect.width()+1, _size, gradient ); pixPainter.end(); painter->drawImage( 0, 0, img ); }
void Hruler::drawMarker(QPainter& p) { QPolygon cr; #ifdef OPTION_SMOOTH_MARKERS // draw new marker to pixmap static const int SCALE = 16; static const QColor BACKGROUND(255, 255, 255); static QPixmap pix( 4*SCALE, 16*SCALE ); static bool initpix = true; if (initpix) { initpix = false; QPainter pp( &pix ); pp.setBrush( BACKGROUND ); pp.drawRect( 0, 0, 4*SCALE, 16*SCALE ); pp.setPen(Qt::red); pp.setBrush(Qt::red); cr.setPoints(3, 2*SCALE, 16*SCALE, 4*SCALE, 0, 0, 0); pp.drawPolygon(cr); } // draw pixmap p.save(); p.translate(-m_view->contentsX(), 0); p.scale(1.0/SCALE, 1.0/(SCALE+1)); p.drawPixmap((where-2)*SCALE, 1, pix); p.restore(); // restore marks p.setBrush(Qt::black); p.setPen(Qt::black); p.setFont(font()); double sc = m_view->getScale(); double cc = width() / sc; double firstMark = ceil(offs / iter) * iter - offs; while (firstMark < cc) { p.drawLine(qRound(firstMark * sc), 10, qRound(firstMark * sc), 16); firstMark += iter; } #else // draw slim marker p.resetTransform(); p.translate(-m_view->contentsX(), 0); p.setPen(Qt::red); p.setBrush(Qt::red); cr.setPoints(5, whereToDraw, 5, whereToDraw, 16, whereToDraw, 5, whereToDraw+2, 0, whereToDraw-2, 0); p.drawPolygon(cr); #endif }
void GraphicsContext::endTransparencyLayer() { if (paintingDisabled()) return; TransparencyLayer *layer = m_data->layers.pop(); layer->painter.end(); QPainter *p = m_data->p(); p->save(); p->resetTransform(); p->setOpacity(layer->opacity); p->drawPixmap(layer->offset, layer->pixmap); p->restore(); delete layer; }
void Shape2D::draw(QPainter& painter) const { painter.setPen(m_color); this->drawShape(painter); if (m_editing) { QColor c(255,255,255,100); painter.setPen(c); painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.drawRect(m_boundingRect.toQRectF()); for(size_t i = 0; i < getNControlPoints(); ++i) { QPointF p = painter.transform().map(getControlPoint(i)); QRectF r(p - QPointF(sizeCP,sizeCP),p + QPointF(sizeCP,sizeCP)); painter.save(); painter.resetTransform(); painter.fillRect(r,c); painter.restore(); } } }
///write a polygon on a PNG file, format of the polygon is vector of vector of contours...nested contours are holes ///takes the name of the image in input, the set of polygons, the set of per polygons transformation, ///the label to be written and the global parameter for drawing style void PolyDumper::dumpPolySetPNG(const char * imageName, vector< vector< vector<Point2f> > > &polyVecVec, vector<Similarity2f> &trVec, vector<string> &labelVec, PolyDumperParam &pp) { ///SET THE FONT assert(polyVecVec.size() == trVec.size()); int fontSize=ceil(std::max(pp.width,pp.height)/100.0); QFont qf("courier",fontSize); ///SET THE DRAWING SIZE QImage img(pp.width,pp.height,QImage::Format_RGB32); img.fill(vcg::ColorConverter::ToQColor( pp.backgroundColor).rgb()); ///SETUP OF DRAWING PROCEDURE QPainter painter; painter.begin(&img); QBrush bb; if (pp.fill) bb.setStyle(Qt::SolidPattern); QPen qp; qp.setWidthF(0); for(size_t i=0;i<polyVecVec.size();++i) { ///SET THE CURRENT TRANSFORMATION painter.resetTransform(); painter.translate(trVec[i].tra[0],trVec[i].tra[1]); painter.rotate(math::ToDeg(trVec[i].rotRad)); painter.scale(trVec[i].sca,trVec[i].sca); QPainterPath QPP; for(size_t jj=0;jj<polyVecVec[i].size();++jj) { QVector<QPointF> ppQ; for(size_t j=0;j<polyVecVec[i][jj].size();++j) { Point2f pp=polyVecVec[i][jj][j]; ppQ.push_back(QPointF(pp[0],pp[1])); } ppQ.push_back(QPointF(polyVecVec[i][jj][0][0],polyVecVec[i][jj][0][1])); QPP.addPolygon(QPolygonF(ppQ)); } ///FIND THE BARYCENTER int radius; Point2f bc; bc=GetIncenter(polyVecVec[i],trVec[i],radius,100); if (pp.randomColor) bb.setColor(vcg::ColorConverter::ToQColor(Color4b::Scatter(polyVecVec.size(),i))); else bb.setColor(vcg::ColorConverter::ToQColor(pp.FillColor)); painter.setBrush(bb); painter.setPen(qp); painter.drawPath(QPP); ///DRAW THE TEXT painter.setFont(qf); painter.resetTransform(); painter.translate(trVec[i].tra[0],trVec[i].tra[1]); painter.drawText(bc[0]-radius,bc[1]-radius,radius*2,radius*2,Qt::AlignHCenter|Qt::AlignCenter,QString(labelVec[i].c_str())); } painter.end(); img.save(imageName); }
void NaZStackWidget::paintIntensityNumerals(QPainter& painter) { if (cur_z < 0) return; if (! zSliceColors) return; ZSliceColors::Reader zReader(*zSliceColors); if (! zReader.hasReadLock()) return; const QImage * displayImage = zReader.getImage(); if (! displayImage) return; if (! volumeData) return; NaVolumeData::Reader volumeReader(*volumeData); if (! volumeReader.hasReadLock()) return; const Image4DProxy<My4DImage>& imgProxy = volumeReader.getOriginalImageProxy(); // qDebug() << "numerals"; QPointF v_img_upleft = X_img_view * painter.viewport().topLeft(); QPointF v_img_downright = X_img_view * painter.viewport().bottomRight(); // qDebug() << v_img_upleft; // qDebug() << v_img_downright; // clear transform for text rendering, otherwise font size is harder to manage painter.resetTransform(); QFont font = painter.font(); float scale = defaultScale * cameraModel.scale(); font.setPixelSize(scale/4.0); font.setStyleStrategy(QFont::NoAntialias); // text rendering can be slow painter.setFont(font); // qDebug() << "nColumns = " << mipImage->originalData.nColumns(); // qDebug() << "nRows = " << mipImage->originalData.nRows(); // Iterate over only the image pixels that are visible int nC = imgProxy.sc; float lineHeight = scale / (nC + 1.0); for (int x = int(v_img_upleft.x() - 0.5); x <= int(v_img_downright.x() + 0.5); ++x) { // qDebug() << "x = " << x; if (x < 0) continue; if (x >= displayImage->width()) continue; for (int y = int(v_img_upleft.y() - 0.5); y <= int(v_img_downright.y() + 0.5); ++y) { // qDebug() << "y = " << y; if (y < 0) continue; if (y >= displayImage->height()) continue; // Transform image pixel coordinates back to viewport coordinates QPointF v = X_view_img * QPointF(x, y); // qDebug() << x << ", " << y << "; " << v.x() << ", " << v.y(); // Print original data intensity, not displayed intensity // But choose font color based on displayed intensity. unsigned int red = qRed(displayImage->pixel(x, y)); unsigned int green = qGreen(displayImage->pixel(x, y)); unsigned int blue = qBlue(displayImage->pixel(x, y)); // human color perception is important here float displayIntensity = 0.30 * red + 0.58 * green + 0.12 * blue; if (displayIntensity < 128) painter.setPen(Qt::white); else painter.setPen(Qt::black); // Write a neat little column of numbers inside each pixel for (int c = 0; c < nC; ++c) { double val = imgProxy.value_at(x, y, cur_z, c); painter.drawText(QRectF(v.x(), v.y() + (c + 0.5) * lineHeight, scale, lineHeight), Qt::AlignHCenter | Qt::AlignVCenter, QString("%1").arg(val)); } } } // restore coordinate system transformPainterToCurrentCamera(painter); }
void PaintMethods::paintDebugDrawing(QPainter& painter, const DebugDrawing& debugDrawing, const QTransform& baseTrans) { static QBrush brush(Qt::SolidPattern); static QBrush noBrush(Qt::NoBrush); static QPen pen; static QPen noPen(Qt::NoPen); for(const DebugDrawing::Element* e = debugDrawing.getFirst(); e; e = debugDrawing.getNext(e)) switch(e->type) { case DebugDrawing::Element::POLYGON: { const DebugDrawing::Polygon& element = *(const DebugDrawing::Polygon*) e; // select brush if(element.fillStyle == Drawings::bs_solid) { brush.setColor(QColor(element.fillColor.r, element.fillColor.g, element.fillColor.b, element.fillColor.a)); painter.setBrush(brush); } else painter.setBrush(noBrush); // select pen if(element.penStyle != Drawings::ps_null) { pen.setColor(QColor(element.penColor.r, element.penColor.g, element.penColor.b, element.penColor.a)); // A line width of zero indicates a cosmetic pen. This means that the pen width is always drawn one pixel wide, independent of the transformation set on the painter. pen.setWidth(element.width); switch(element.penStyle) { case Drawings::ps_dash: pen.setStyle(Qt::DashLine); break; case Drawings::ps_dot: pen.setStyle(Qt::DotLine); break; case Drawings::ps_solid: default: pen.setStyle(Qt::SolidLine); } painter.setPen(pen); } else painter.setPen(noPen); // copy vector2 to QPoints static QPoint points[16]; for(int n = element.nCount - 1; n >= 0 ; --n) points[n] = QPoint(element.points[n].x, element.points[n].y); painter.drawPolygon(points, element.nCount); break; } case DebugDrawing::Element::GRID_RGBA: { const DebugDrawing::GridRGBA& element = *(const DebugDrawing::GridRGBA*) e; const int totalWidth(element.cellsX * element.cellSize); const int totalHeight(element.cellsY * element.cellSize); for(int y = 0; y < element.cellsY; ++y) { for(int x = 0; x < element.cellsX; ++x) { int startX(x * element.cellSize - totalWidth / 2); int startY(y * element.cellSize - totalHeight / 2); int c(y * element.cellsX + x); brush.setColor(QColor(element.cells[c].r, element.cells[c].g, element.cells[c].b, element.cells[c].a)); pen.setColor(QColor(element.cells[c].r, element.cells[c].g, element.cells[c].b, element.cells[c].a)); pen.setWidth(1); painter.setBrush(brush); painter.setPen(pen); painter.drawRect(startX, startY, element.cellSize - 1, element.cellSize - 1); } } break; } case DebugDrawing::Element::GRID_MONO: { const DebugDrawing::GridMono& element = *(const DebugDrawing::GridMono*) e; const int totalWidth(element.cellsX * element.cellSize); const int totalHeight(element.cellsY * element.cellSize); for(int y = 0; y < element.cellsY; ++y) { for(int x = 0; x < element.cellsX; ++x) { int startX(x * element.cellSize - totalWidth / 2); int startY(y * element.cellSize - totalHeight / 2); int c(y * element.cellsX + x); ColorRGBA col(element.baseColor * (1.0f - (static_cast<float>(element.cells[c]) / 255.0))); brush.setColor(QColor(col.r, col.g, col.b, element.baseColor.a)); pen.setColor(QColor(col.r, col.g, col.b, element.baseColor.a)); pen.setWidth(1); painter.setBrush(brush); painter.setPen(pen); painter.drawRect(startX, startY, element.cellSize - 1, element.cellSize - 1); } } break; } case DebugDrawing::Element::ELLIPSE: { const DebugDrawing::Ellipse& element = *(const DebugDrawing::Ellipse*) e; // select brush if(element.fillStyle == Drawings::bs_solid) { brush.setColor(QColor(element.fillColor.r, element.fillColor.g, element.fillColor.b, element.fillColor.a)); painter.setBrush(brush); } else painter.setBrush(noBrush); // select pen if(element.penStyle != Drawings::ps_null) { pen.setColor(QColor(element.penColor.r, element.penColor.g, element.penColor.b, element.penColor.a)); // A line width of zero indicates a cosmetic pen. This means that the pen width is always drawn one pixel wide, independent of the transformation set on the painter. pen.setWidth(element.width); switch(element.penStyle) { case Drawings::ps_dash: pen.setStyle(Qt::DashLine); break; case Drawings::ps_dot: pen.setStyle(Qt::DotLine); break; case Drawings::ps_solid: default: pen.setStyle(Qt::SolidLine); } painter.setPen(pen); } else painter.setPen(noPen); if(element.rotation != 0.0f) { QTransform trans(painter.transform()); QTransform transBack(painter.transform()); trans.translate(qreal(element.x), qreal(element.y)); trans.rotateRadians(qreal(element.rotation)); painter.setTransform(trans); painter.drawEllipse(-element.radiusX, -element.radiusY, 2 * element.radiusX, 2 * element.radiusY); painter.setTransform(transBack); } else { painter.drawEllipse(element.x - element.radiusX, element.y - element.radiusY, 2 * element.radiusX, 2 * element.radiusY); } break; } case DebugDrawing::Element::LINE: { const DebugDrawing::Line& element = *(const DebugDrawing::Line*) e; if(element.penStyle != Drawings::ps_null) { pen.setColor(QColor(element.penColor.r, element.penColor.g, element.penColor.b, element.penColor.a)); // A line width of zero indicates a cosmetic pen. This means that the pen width is always drawn one pixel wide, independent of the transformation set on the painter. pen.setWidth(element.width); switch(element.penStyle) { case Drawings::ps_dash: pen.setStyle(Qt::DashLine); break; case Drawings::ps_dot: pen.setStyle(Qt::DotLine); break; case Drawings::ps_solid: default: pen.setStyle(Qt::SolidLine); } painter.setPen(pen); painter.drawLine(element.xStart, element.yStart, element.xEnd, element.yEnd); } break; } case DebugDrawing::Element::ORIGIN: { const DebugDrawing::Origin& element = *(const DebugDrawing::Origin*) e; QTransform trans(baseTrans); trans.translate(qreal(element.x), qreal(element.y)); trans.rotateRadians(qreal(element.angle)); painter.setTransform(trans); break; } case DebugDrawing::Element::TEXT: { const DebugDrawing::Text& element = *(const DebugDrawing::Text*) e; pen.setColor(QColor(element.penColor.r, element.penColor.g, element.penColor.b, element.penColor.a)); painter.setPen(pen); QTransform trans(painter.transform()); const QPoint& pos(trans.map(QPoint(element.x, element.y))); painter.resetTransform(); painter.drawText(pos, (const char*)(&element + 1)); painter.setTransform(trans); break; } default: break; } }
///write a polygon on a SVG file, format of the polygon is vector of vector of contours...nested contours are holes ///takes the name of the image in input, the set of polygons, the set of per polygons transformation, ///the label to be written and the global parameter for drawing style void PolyDumper::dumpPolySetSVG(const char * imageName, vector< vector< vector<Point2f> > > &polyVecVec, vector<Similarity2f> &trVec, vector< vector< string> > &labelVecVec, vector<vector<Point2f> > &labelPosVecVec, vector<vector<float> >&labelRadVecVec, PolyDumperParam &pp) { assert(polyVecVec.size() == trVec.size()); ///SET THE FONT int fontSize; if(pp.fontSize==0) fontSize=ceil(std::max(pp.width,pp.height)/200.0); else fontSize=pp.fontSize; QFont qf("courier",fontSize); QSvgGenerator svg; svg.setFileName(imageName); ///SET THE DRAWING SIZE svg.setSize(QSize(pp.width,pp.height)); svg.setViewBox(QRect(0, 0, pp.width,pp.height)); svg.setResolution(int(pp.dpi));// ///SETUP OF DRAWING PROCEDURE QPainter painter; painter.begin(&svg); QBrush bb; if (pp.fill) bb.setStyle(Qt::SolidPattern); QPen qp; ///SET THE GLOBAL SCALING FACTOR float Scalesvg=1.f/(float)trVec[0].sca; qp.setWidthF(Scalesvg); for(size_t i=0;i<polyVecVec.size();++i) { ///SET THE CURRENT TRANSFORMATION painter.resetTransform(); painter.translate(trVec[i].tra[0],trVec[i].tra[1]); painter.rotate(math::ToDeg(trVec[i].rotRad)); painter.scale(trVec[i].sca,trVec[i].sca); QPainterPath QPP; for(size_t jj=0;jj<polyVecVec[i].size();++jj) { QVector<QPointF> ppQ; for(size_t j=0;j<polyVecVec[i][jj].size();++j) { Point2f pp=polyVecVec[i][jj][j]; ppQ.push_back(QPointF(pp[0],pp[1])); } ppQ.push_back(QPointF(polyVecVec[i][jj][0][0],polyVecVec[i][jj][0][1])); QPP.addPolygon(QPolygonF(ppQ)); } ///FIND THE INCENTER if (pp.randomColor) bb.setColor(vcg::ColorConverter::ToQColor(Color4b::Scatter(polyVecVec.size(),i))); else bb.setColor(vcg::ColorConverter::ToQColor(pp.FillColor)); ///DRAW THE POLYGON painter.setBrush(bb); painter.setPen(qp); painter.drawPath(QPP); ///DRAW THE TEXT painter.setFont(qf); float radius; int radiusInt; Point2f bc; // if we do not have labelPos use the old method of empty disk. if(labelPosVecVec.empty()) bc=GetIncenter(polyVecVec[i],trVec[i],radiusInt); radius = radiusInt; for(size_t labelInd=0;labelInd<labelVecVec[i].size();++labelInd) { if(!labelPosVecVec.empty()) { bc= labelPosVecVec[i][labelInd]; bc.Rotate(trVec[i].rotRad); bc *= trVec[i].sca; radius=labelRadVecVec[i][labelInd]; radius *= trVec[i].sca; } painter.resetTransform(); painter.translate(trVec[i].tra[0],trVec[i].tra[1]); painter.drawText(bc[0]-radius,bc[1]-radius,radius*2,radius*2,Qt::AlignHCenter|Qt::AlignCenter,QString(labelVecVec[i][labelInd].c_str())); } } painter.end(); }
///this class draw a black mask fora given polygon, cenetered and scaled to fit with ///the image size, it return the transformation to tranform back the polygon to 2D space void PolyDumper::DrawPolygonMask(const vector< vector<Point2f> > &polyVec, QImage &img, Similarity2f &ret, const Similarity2f &trans) { ///RASTERIZE THE POLYGON QPainter painter; painter.begin(&img); QBrush bb; bb.setStyle(Qt::SolidPattern); int resolution=img.width(); QPen qp; qp.setWidthF(0); ///find the BB vcg::Box2f bbox; for(size_t i=0;i<polyVec.size();++i) for(size_t j=0;j<polyVec[i].size();++j) { Point2f pp=polyVec[i][j]; pp.Rotate(trans.rotRad); bbox.Add(pp); } vcg::Point2f pos=bbox.Center(); float scaleFact=(resolution/bbox.Diag()); ///SET THE TRANSFORMATION TO CENTER WRT BBOX painter.resetTransform(); painter.translate(resolution/2,resolution/2); painter.rotate(math::ToDeg(trans.rotRad)); painter.scale(scaleFact,scaleFact); painter.translate(-pos.V(0),-pos.V(1)); ///SET TO RETURN BACK ret.rotRad=0; ret.sca=scaleFact; ret.tra[0]=-pos.V(0)*scaleFact + resolution/2; ret.tra[1]=-pos.V(1)*scaleFact + resolution/2; ///DRAW THE POLYGON QPainterPath QPP; for(size_t i=0;i<polyVec.size();++i) { QVector<QPointF> ppQ; for(size_t j=0;j<polyVec[i].size();++j) { Point2f pp=polyVec[i][j]; //pp.Rotate(trans.rotRad); ppQ.push_back(QPointF(pp[0],pp[1])); } ppQ.push_back(QPointF(polyVec[i][0][0],polyVec[i][0][1])); QPP.addPolygon(QPolygonF(ppQ)); } painter.setBrush(bb); painter.setPen(qp); painter.drawPath(QPP); painter.end(); //img.save("test.png"); }
void MainWindow::renderBoardCompleteGame(std::vector<MoveHistoryEntry> history, QString outDir, bool renderOpenTiles, bool renderFrames, bool renderPlayers, bool renderNextTile, int playerCount) { //TODO correct backgrounds QDir(outDir).mkpath("."); jcz::TileFactory tileFactory(false); TileImageFactory imgFactory(&tileFactory); QImage image; QPainter * painter = 0; RandomNextTileProvider rntp; HistoryProvider hp(&rntp, history, 0); Game g(&hp, false); for (int i = 0; i < playerCount; ++i) g.addPlayer(&RandomPlayer::instance); BoardGraphicsScene bgs(&tileFactory, &imgFactory); bgs.setRenderOpenTiles(renderOpenTiles); bgs.setRenderFrames(renderFrames); bgs.setGame(&g); g.addWatchingPlayer(&bgs); g.newGame(Tile::BaseGame, &tileFactory, history, true); bgs.clearSelection(); QRectF sceneRect = bgs.itemsBoundingRect(); int const spacing = 50; int constexpr pivScale = 4; QSize sceneSize = sceneRect.size().toSize(); QSize size = sceneSize; if (renderPlayers) { QLabel remainingLabel(QString("%1 tiles left").arg(g.getTileCount() - 1)); remainingLabel.updateGeometry(); int nextTileType = g.getTile(hp.nextTile(&g))->tileType; QSize pivSize; { PlayerInfoView piv(0, &g, &imgFactory); piv.updateView(); if (renderNextTile) piv.displayTile(g.getNextPlayer(), nextTileType); piv.updateGeometry(); pivSize = piv.size() * pivScale; pivSize.rheight() *= g.getPlayerCount(); QSize remSize = remainingLabel.sizeHint() * pivScale; size.rwidth() += pivSize.width() + spacing; size.rheight() = qMax(size.height(), pivSize.height() + spacing + remSize.height()); } } std::vector<MoveHistoryEntry> applyHistory; for (int i = -1; i < (int)history.size(); ++i) { // oh well, this is ugly. If only there was a Game::step(MoveHistoryEntry)... if (i >= 0) applyHistory.push_back(history[i]); g.newGame(Tile::BaseGame, &tileFactory, applyHistory, true); delete painter; image = QImage(size, QImage::Format_ARGB32); image.fill(Qt::transparent); painter = new QPainter(&image); painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); QPoint offset(0, 0); if (renderPlayers) { QLabel remainingLabel(QString("%1 tiles left").arg(g.getTileCount() - 1)); remainingLabel.updateGeometry(); int nextTileType = g.getTile(hp.nextTile(&g))->tileType; QSize pivSize; painter->scale(pivScale, pivScale); for (uint p = 0; p < g.getPlayerCount(); ++p) { PlayerInfoView piv(p, &g, &imgFactory); piv.updateView(); if (renderNextTile) piv.displayTile(g.getNextPlayer(), nextTileType); piv.updateGeometry(); piv.render(painter, offset); offset.ry() += piv.size().height(); } offset.setX(0); offset.setY((pivSize.height() + spacing) / pivScale); remainingLabel.render(painter, offset); offset.setX(pivSize.width() + spacing); offset.setY(0); painter->resetTransform(); } bgs.setSceneRect(sceneRect); bgs.render(painter, QRectF(offset, size)); image.save(QString("%1/%2.png").arg(outDir).arg(i+1, 3, 10, QLatin1Char('0'))); } delete painter; }
void MainWindow::renderBoard(std::vector<MoveHistoryEntry> history, QString outFile, int removeLast, bool renderOpenTiles, bool renderFrames, bool renderPlayers, bool renderNextTile) { //TODO correct backgrounds jcz::TileFactory tileFactory(false); TileImageFactory imgFactory(&tileFactory); QImage image; QPainter * painter = 0; RandomNextTileProvider rntp; HistoryProvider hp(&rntp, history, history.size() - removeLast); Game g(&hp, false); g.addPlayer(&RandomPlayer::instance); g.addPlayer(&RandomPlayer::instance); BoardGraphicsScene bgs(&tileFactory, &imgFactory); bgs.setRenderOpenTiles(renderOpenTiles); bgs.setRenderFrames(renderFrames); bgs.setGame(&g); g.addWatchingPlayer(&bgs); history.erase(history.end() - removeLast, history.end()); g.newGame(Tile::BaseGame, &tileFactory, history, true); bgs.clearSelection(); bgs.setSceneRect(bgs.itemsBoundingRect()); int const spacing = 50; int constexpr pivScale = 4; QSize sceneSize = bgs.sceneRect().size().toSize(); QSize size = sceneSize; QPoint offset(0, 0); if (renderPlayers) { QLabel remainingLabel(QString("%1 tiles left").arg(g.getTileCount() - 1)); remainingLabel.updateGeometry(); int nextTileType = g.getTile(hp.nextTile(&g))->tileType; QSize pivSize; for (uint p = 0; p < g.getPlayerCount(); ++p) { PlayerInfoView piv(p, &g, &imgFactory); piv.updateView(); if (renderNextTile) piv.displayTile(g.getNextPlayer(), nextTileType); piv.updateGeometry(); if (p == 0) { pivSize = piv.size() * pivScale; pivSize.rheight() *= g.getPlayerCount(); QSize remSize = remainingLabel.sizeHint() * pivScale; size.rwidth() += pivSize.width() + spacing; size.rheight() = qMax(size.height(), pivSize.height() + spacing + remSize.height()); image = QImage(size, QImage::Format_ARGB32); image.fill(Qt::transparent); painter = new QPainter(&image); painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); painter->scale(pivScale, pivScale); } piv.render(painter, offset); offset.ry() += piv.size().height(); } offset.setX(0); offset.setY((pivSize.height() + spacing) / pivScale); remainingLabel.render(painter, offset); offset.setX(pivSize.width() + spacing); offset.setY(0); painter->resetTransform(); } else { image = QImage(size, QImage::Format_ARGB32); image.fill(Qt::transparent); painter = new QPainter(&image); painter->setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing); } bgs.render(painter, QRectF(offset, size)); image.save(outFile); delete painter; }
void KisColorSelector::drawLightStrip(QPainter& painter, const QRect& rect) { bool isVertical = true; qreal penSize = qreal(qMin(QWidget::width(), QWidget::height())) / 200.0; KisColor color(m_selectedColor); painter.resetTransform(); if (getNumLightPieces() > 1) { painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(QPen(QBrush(Qt::red), penSize)); QTransform matrix; matrix.translate(rect.x(), rect.y()); matrix.scale(rect.width(), rect.height()); for(int i=0; i<getNumLightPieces(); ++i) { float t1 = float(i) / float(getNumLightPieces()); float t2 = float(i+1) / float(getNumLightPieces()); float light = 1.0f - (float(i) / float(getNumLightPieces()-1)); float diff = t2 - t1;// + 0.001; QRectF r = isVertical ? QRectF(0.0, t1, 1.0, diff) : QRect(t1, 0.0, diff, 1.0); color.setX(getLight(light, color.getH(), m_relativeLight)); r = matrix.mapRect(r); painter.fillRect(r, color.getQColor()); if (i == m_selectedLightPiece) painter.drawRect(r); } } else { int size = isVertical ? rect.height() : rect.width(); painter.setRenderHint(QPainter::Antialiasing, false); if (isVertical) { for(int i=0; i<size; ++i) { int y = rect.y() + i; float light = 1.0f - (float(i) / float(size-1)); color.setX(getLight(light, color.getH(), m_relativeLight)); painter.setPen(color.getQColor()); painter.drawLine(rect.left(), y, rect.right(), y); } } else { for(int i=0; i<size; ++i) { int x = rect.x() + i; float light = 1.0f - (float(i) / float(size-1)); color.setX(getLight(light, color.getH(), m_relativeLight)); painter.setPen(color.getQColor()); painter.drawLine(x, rect.top(), x, rect.bottom()); } } painter.setRenderHint(QPainter::Antialiasing, true); painter.setPen(QPen(QBrush(Qt::red), penSize)); float t = 1.0f - m_light; if (isVertical) { int y = rect.y() + int(size * t); painter.drawLine(rect.left(), y, rect.right(), y); } else { int x = rect.x() + int(size * t); painter.drawLine(x, rect.top(), x, rect.bottom()); } } }
void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly, float scale, int rast_i, int rotationNum, int cellSize) { float rotRad = M_PI*2.0f*float(rast_i) / float(rotationNum); //get polygon's BB, rotated according to the input parameter Box2f bb; vector<Point2f> pointvec = poly.getPoints(); for(size_t i=0;i<pointvec.size();++i) { Point2f pp=pointvec[i]; pp.Rotate(rotRad); bb.Add(pp); } ///CREATE ITS GRID. The grid has to be a multiple of CELLSIZE because this grid's cells have size CELLSIZE //we'll make so that sizeX and sizeY are multiples of CELLSIZE: //1) we round it to the next integer //2) add the number which makes it a multiple of CELLSIZE (only if it's not multiple already) int sizeX = (int)ceil(bb.DimX()*scale); int sizeY = (int)ceil(bb.DimY()*scale); if (sizeX % cellSize != 0) sizeX += (cellSize - ((int)ceil(bb.DimX()*scale) % cellSize)); if (sizeY % cellSize != 0) sizeY += (cellSize - ((int)ceil(bb.DimY()*scale) % cellSize)); //security measure: add a dummy column/row thus making the image bigger, and crop it afterwards //(if it hasn't been filled with anything) //this is due to the fact that if we have a rectangle which has bb 39.xxx wide, then it won't fit in a 40px wide QImage!! The right side will go outside of the image!! :/ sizeX+=cellSize; sizeY+=cellSize; QImage img(sizeX,sizeY,QImage::Format_RGB32); QColor backgroundColor(Qt::transparent); img.fill(backgroundColor); ///SETUP OF DRAWING PROCEDURE QPainter painter; painter.begin(&img); QBrush br; br.setStyle(Qt::SolidPattern); QPen qp; qp.setWidthF(0); qp.setColor(Qt::yellow); painter.setBrush(br); painter.setPen(qp); painter.resetTransform(); painter.translate(QPointF(-(bb.min.X()*scale) , -(bb.min.Y()*scale) )); painter.rotate(math::ToDeg(rotRad)); painter.scale(scale,scale); //create the polygon to print it QVector<QPointF> points; vector<Point2f> newpoints = poly.getPoints(); for (size_t i = 0; i < newpoints.size(); i++) { points.push_back(QPointF(newpoints[i].X(), newpoints[i].Y())); } painter.drawPolygon(QPolygonF(points)); //CROPPING: it is enough to check for the (end - cellSize - 1)th row/col of pixels, if they're all black we can eliminate the last 8columns/rows of pixels bool cropX = true; bool cropY = true; for (int j=0; j<img.height(); j++) { const uchar* line = img.scanLine(j); if (j == img.height() - (cellSize - 1) - 1 ) { for (int x=0; x<img.width(); x++) { if (((QRgb*)line)[x] != backgroundColor.rgb()) { cropY = false; break; } } } else { if (((QRgb*)line)[img.width() - (cellSize - 1) - 1] != backgroundColor.rgb()) { cropX = false; break; } } if (!cropY) break; } if (cropX || cropY) { painter.end(); img = img.copy(0, 0, img.width() - cellSize * cropX, img.height() - cellSize * cropY); painter.begin(&img); painter.setBrush(br); painter.setPen(qp); } //draw the poly for the second time, this time it is centered to the image img.fill(backgroundColor); painter.resetTransform(); painter.translate(QPointF(-(bb.min.X()*scale) + (img.width() - ceil(bb.DimX()*scale))/2.0, -(bb.min.Y()*scale) + (img.height() - ceil(bb.DimY()*scale))/2.0)); painter.rotate(math::ToDeg(rotRad)); painter.scale(scale,scale); //create the polygon to print it QVector<QPointF> points2; vector<Point2f> newpoints2 = poly.getPoints(); for (size_t i = 0; i < newpoints2.size(); i++) { points2.push_back(QPointF(newpoints2[i].X(), newpoints2[i].Y())); } painter.drawPolygon(QPolygonF(points2)); //create the first grid, which will then be rotated 3 times. //we will reuse this grid to create the rasterizations corresponding to this one rotated by 90/180/270° vector<vector<int> > tetrisGrid; QRgb yellow = QColor(Qt::yellow).rgb(); int gridWidth = img.width() / cellSize; int gridHeight = img.height() / cellSize; int x = 0; tetrisGrid.resize(gridHeight); for (int k = 0; k < gridHeight; k++) { tetrisGrid[k].resize(gridWidth, 0); } for (int y = 0; y < img.height(); y++) { int gridY = y / cellSize; const uchar* line = img.scanLine(y); x = 0; int gridX = 0; while(x < img.width()) { gridX = x/cellSize; if (tetrisGrid[gridY][gridX] == 1) { x+= cellSize - (x % cellSize); //align with the next x continue; } if (((QRgb*)line)[x] == yellow) tetrisGrid[gridY][gridX] = 1; ++x; } } //create the 4 rasterizations (one every 90°) using the discrete representation grid we've just created int rotationOffset = rotationNum/4; for (int j = 0; j < 4; j++) { if (j != 0) { tetrisGrid = rotateGridCWise(tetrisGrid); } //add the grid to the poly's vector of grids poly.getGrids(rast_i + rotationOffset*j) = tetrisGrid; //initializes bottom/left/deltaX/deltaY vectors of the poly, for the current rasterization poly.initFromGrid(rast_i + rotationOffset*j); } painter.end(); }