Beispiel #1
0
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();
}
Beispiel #2
0
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();
}
Beispiel #4
0
  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 ) );
  }
Beispiel #5
0
		/**
		* 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());
    }
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
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 );
}
Beispiel #10
0
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;
}
Beispiel #12
0
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();
    }
  }
}
Beispiel #13
0
///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);
}
Beispiel #14
0
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;
    }
}
Beispiel #16
0
///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();
}
Beispiel #17
0
///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");
}
Beispiel #18
0
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;
}
Beispiel #19
0
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;
}
Beispiel #20
0
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();
}