Esempio n. 1
0
Dirty::Dirty(Image* image, Image* image_diff)
  : m_imgtype(image->imgtype)
  , m_x1(0), m_y1(0)
  , m_x2(image->w-1), m_y2(image->h-1)
{
  int x, y, x1, x2;

  for (y=0; y<image->h; y++) {
    x1 = -1;
    for (x=0; x<image->w; x++) {
      if (image_getpixel(image, x, y) != image_getpixel(image_diff, x, y)) {
	x1 = x;
	break;
      }
    }
    if (x1 < 0)
      continue;

    for (x2=image->w-1; x2>x1; x2--) {
      if (image_getpixel(image, x2, y) != image_getpixel(image_diff, x2, y))
	break;
    }

    Col* col = new Col(x1, x2-x1+1);
    col->data.resize(getLineSize(col->w));

    Row* row = new Row(y);
    row->cols.push_back(col);

    m_rows.push_back(row);
  }
}
Esempio n. 2
0
void rectangle::paintEvent( QPaintEvent *event )
{
    Q_UNUSED(event);
    QPainter p( this );
    p.setPen( QPen( getLineColor(), getLineSize(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
    p.setBrush(readFG());
    p.drawRect(0, 0, width()-1, height()-1 );
}
Esempio n. 3
0
LiveCache::LiveCache() {
  cacheBank = CacheType::create("LiveCache", "", "LL");
  lineSize  = cacheBank->getLineSize();
  lineSizeBits = log2i(lineSize);

  I(getLineSize() < 4096); // To avoid bank selection conflict (insane LiveCache line)

  lineCount = (uint64_t) cacheBank->getNumLines();
  maxOrder = 0;
}
Esempio n. 4
0
void Dirty::swapImagePixels(Image* image)
{
  RowsList::iterator row_it = m_rows.begin();
  RowsList::iterator row_end = m_rows.end();
  for (; row_it != row_end; ++row_it) {
    Row* row = *row_it;

    ColsList::iterator col_it = (*row_it)->cols.begin();
    ColsList::iterator col_end = (*row_it)->cols.end();
    for (; col_it != col_end; ++col_it) {
      Col* col = *col_it;

      uint8_t* address = (uint8_t*)image_address(image, col->x, row->y);
      std::swap_ranges(address, address+getLineSize(col->w), col->data.begin());
    }
  }
}
Esempio n. 5
0
int Dirty::getMemSize() const
{
  int size = 4+1+2*4+2;		// DWORD+BYTE+WORD[4]+WORD

  RowsList::const_iterator row_it = m_rows.begin();
  RowsList::const_iterator row_end = m_rows.end();
  for (; row_it != row_end; ++row_it) {
    size += 4;			// y, cols (WORD[2])

    ColsList::const_iterator col_it = (*row_it)->cols.begin();
    ColsList::const_iterator col_end = (*row_it)->cols.end();
    for (; col_it != col_end; ++col_it) {
      size += 4;		// x, w (WORD[2])
      size += getLineSize((*col_it)->w);
    }
  }

  return size;
}
Esempio n. 6
0
Dirty::Dirty(Image* image, Image* image_diff, const gfx::Rect& bounds)
  : m_format(image->getPixelFormat())
  , m_x1(bounds.x), m_y1(bounds.y)
  , m_x2(bounds.x2()-1), m_y2(bounds.y2()-1)
{
  int y, x1, x2;

  for (y=m_y1; y<=m_y2; y++) {
    x1 = m_x1;
    x2 = m_x2;

    bool res;
    switch (image->getPixelFormat()) {
      case IMAGE_RGB:
        res = shrink_row<RgbTraits>(image, image_diff, x1, y, x2);
        break;

      case IMAGE_GRAYSCALE:
        res = shrink_row<GrayscaleTraits>(image, image_diff, x1, y, x2);
        break;

      case IMAGE_INDEXED:
        res = shrink_row<IndexedTraits>(image, image_diff, x1, y, x2);
        break;

      default:
        ASSERT(false && "Not implemented for bitmaps");
        return;
    }
    if (!res)
      continue;

    Col* col = new Col(x1, x2-x1+1);
    col->data.resize(getLineSize(col->w));

    Row* row = new Row(y);
    row->cols.push_back(col);

    m_rows.push_back(row);
  }
}
Esempio n. 7
0
	void VScroll::updateTrack()
	{
		if (mWidgetTrack == nullptr)
			return;

		_forcePeek(mWidgetTrack);
		// размер диапазана в пикселях
		int pos = getLineSize();

		// скрываем если диапазан маленький или места мало
		if ((mScrollRange < 2) || (pos <= mWidgetTrack->getHeight()))
		{
			mWidgetTrack->setVisible(false);
			if ( nullptr != mWidgetFirstPart ) mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), pos / 2);
			if ( nullptr != mWidgetSecondPart ) mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), pos / 2 + (int)mSkinRangeStart, mWidgetSecondPart->getWidth(), pos - pos / 2);
			return;
		}
		// если скрыт то покажем
		if (!mWidgetTrack->getVisible())
		{
			mWidgetTrack->setVisible(true);
		}

		// и обновляем позицию
		pos = (int)(((size_t)(pos - getTrackSize()) * mScrollPosition) / (mScrollRange - 1) + mSkinRangeStart);

		mWidgetTrack->setPosition(mWidgetTrack->getLeft(), pos);
		if ( nullptr != mWidgetFirstPart )
		{
			int height = pos + mWidgetTrack->getHeight() / 2 - mWidgetFirstPart->getTop();
			mWidgetFirstPart->setSize(mWidgetFirstPart->getWidth(), height);
		}
		if ( nullptr != mWidgetSecondPart )
		{
			int top = pos + mWidgetTrack->getHeight() / 2;
			int height = mWidgetSecondPart->getHeight() + mWidgetSecondPart->getTop() - top;
			mWidgetSecondPart->setCoord(mWidgetSecondPart->getLeft(), top, mWidgetSecondPart->getWidth(), height);
		}
	}
Esempio n. 8
0
void EArrow::paintEvent( QPaintEvent * ) {
    QPointF p1,p2;
    QLineF polyLine;
    QPainter painter( this );

    painter.setRenderHint( QPainter::Antialiasing );
    painter.setPen( QPen( getLineColor(), getLineSize(), Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
    painter.setBrush( getBrushColor() );

    int m_margin = 3;

    if (VERTICAL == getArrowDirection()) {
        p1 = QPointF( width()/2, m_margin );
        p2 = QPointF( width()/2, height()-m_margin );
    } else if (RIGTHBOTTOM == getArrowDirection()) {
        p1 = QPointF( m_margin, m_margin );
        p2 = QPointF( width()-m_margin, height()-m_margin );
    } else if (RIGTHTOP == getArrowDirection()) {
        p1 = QPointF( m_margin, height()-m_margin );
        p2 = QPointF( width()-m_margin, m_margin );
    } else { // HORIZONTAL
        p1 = QPointF( m_margin, height()/2 );
        p2 = QPointF( width()-m_margin, height()/2 );
    }

    polyLine = QLineF( p1, p2 );
    painter.drawLine(polyLine);

    if (LEFT == getArrowMode()) {
        painter.drawPolygon( getHead(p1,p2) );
    } else if (RIGTH == getArrowMode()) {
        painter.drawPolygon(getHead(p2,p1));
    } else if (DOUBLE == getArrowMode()) {
        painter.drawPolygon(getHead(p1,p2));
        painter.drawPolygon(getHead(p2,p1));
    }
}
Esempio n. 9
0
CCache::CCache(MemorySystem *gms, const char *section, const char *name)
  // Constructor {{{1
  :MemObj(section, name)
	 ,hitDelay  (SescConf->getInt(section,"hitDelay"))
	 ,missDelay (SescConf->getInt(section,"missDelay"))
	 ,displaced       ("%s:displaced",       name)
	 ,invAll          ("%s:invAll",          name)
	 ,invOne          ("%s:invOne",          name)
	 ,invNone         ("%s:invNone",         name)
	 ,writeBack       ("%s:writeBack",       name)
	 ,lineFill        ("%s:lineFill",        name)
	 ,avgMissLat      ("%s_avgMissLat",      name)
	 ,avgMemLat       ("%s_avgMemLat",       name)
	 ,capInvalidateHit   ("%s_capInvalidateHit",   name)
	 ,capInvalidateMiss  ("%s_capInvalidateMiss",  name)
	 ,invalidateHit   ("%s_invalidateHit",   name)
	 ,invalidateMiss  ("%s_invalidateMiss",  name)
	 ,writeExclusive  ("%s:writeExclusive",  name)
{
  SescConf->isInt(section, "hitDelay");
  SescConf->isInt(section, "missDelay");
  SescConf->isGT(section, "hitDelay" ,0);
  SescConf->isGT(section, "missDelay",0);

  s_reqHit[ma_setInvalid]   = new GStatsCntr("%s:setInvalidHit",name);
  s_reqHit[ma_setValid]     = new GStatsCntr("%s:readHit",name);
  s_reqHit[ma_setDirty]     = new GStatsCntr("%s:writeHit",name);
  s_reqHit[ma_setShared]    = new GStatsCntr("%s:setSharedHit",name);
  s_reqHit[ma_setExclusive] = new GStatsCntr("%s:setExclusiveHit",name);
  s_reqHit[ma_MMU]          = new GStatsCntr("%s:MMUHit",name);
  s_reqHit[ma_VPCWU]        = new GStatsCntr("%s:VPCMUHit",name);

  s_reqMiss[ma_setInvalid]   = new GStatsCntr("%s:setInvalidMiss",name);
  s_reqMiss[ma_setValid]     = new GStatsCntr("%s:readMiss",name);
  s_reqMiss[ma_setDirty]     = new GStatsCntr("%s:writeMiss",name);
  s_reqMiss[ma_setShared]    = new GStatsCntr("%s:setSharedMiss",name);
  s_reqMiss[ma_setExclusive] = new GStatsCntr("%s:setExclusiveMiss",name);
  s_reqMiss[ma_MMU]          = new GStatsCntr("%s:MMUMiss",name);
  s_reqMiss[ma_VPCWU]        = new GStatsCntr("%s:VPCMUMiss",name);

  s_reqHalfMiss[ma_setInvalid]   = new GStatsCntr("%s:setInvalidHalfMiss",name);
  s_reqHalfMiss[ma_setValid]     = new GStatsCntr("%s:readHalfMiss",name);
  s_reqHalfMiss[ma_setDirty]     = new GStatsCntr("%s:writeHalfMiss",name);
  s_reqHalfMiss[ma_setShared]    = new GStatsCntr("%s:setSharedHalfMiss",name);
  s_reqHalfMiss[ma_setExclusive] = new GStatsCntr("%s:setExclusiveHalfMiss",name);
  s_reqHalfMiss[ma_MMU]          = new GStatsCntr("%s:MMUHalfMiss",name);
  s_reqHalfMiss[ma_VPCWU]        = new GStatsCntr("%s:VPCMUHalfMiss",name);

  s_reqAck[ma_setInvalid]   = new GStatsCntr("%s:setInvalidAck",name);
  s_reqAck[ma_setValid]     = new GStatsCntr("%s:setValidAck",name);
  s_reqAck[ma_setDirty]     = new GStatsCntr("%s:setDirtyAck",name);
  s_reqAck[ma_setShared]    = new GStatsCntr("%s:setSharedAck",name);
  s_reqAck[ma_setExclusive] = new GStatsCntr("%s:setExclusiveAck",name);
  s_reqAck[ma_MMU]          = new GStatsCntr("%s:MMUAck",name);
  s_reqAck[ma_VPCWU]        = new GStatsCntr("%s:VPCMUAck",name);

  s_reqSetState[ma_setInvalid]   = new GStatsCntr("%s:setInvalidsetState",name);
  s_reqSetState[ma_setValid]     = new GStatsCntr("%s:setValidsetState",name);
  s_reqSetState[ma_setDirty]     = new GStatsCntr("%s:setDirtysetState",name);
  s_reqSetState[ma_setShared]    = new GStatsCntr("%s:setSharedsetState",name);
  s_reqSetState[ma_setExclusive] = new GStatsCntr("%s:setExclusivesetState",name);
  s_reqSetState[ma_MMU]          = new GStatsCntr("%s:MMUsetState",name);
  s_reqSetState[ma_VPCWU]        = new GStatsCntr("%s:VPCMUsetState",name);

  dyn_hitDelay    = hitDelay;   // DVFS managed
  dyn_missDelay   = missDelay;

  // TODO: add support for coreCoupledFreq as part of mreq
  //if(SescConf->checkBool(section,"coreCoupledFreq")) {
    //MSG("WARNING: coreCoupledFreq does not work yet");
  //}

  coreCoupledFreq = false;
  //if (coreCoupledFreq) {
  //  BootLoader::getPowerModelPtr()->addTurboCoupledMemory(this);
  //}

  const char* mshrSection = SescConf->getCharPtr(section,"MSHR");

  char tmpName[512];

  sprintf(tmpName, "%s", name);

  cacheBank = CacheType::create(section, "", tmpName);
  lineSize  = cacheBank->getLineSize();
  lineSizeBits = log2i(lineSize);
  mshr      = MSHR::create(tmpName, mshrSection, lineSize);

  I(getLineSize() < 4096); // To avoid bank selection conflict (insane CCache line)
  I(gms);
  
  SescConf->checkBool(section, "inclusive");
  SescConf->checkBool(section, "directory");

  inclusive = SescConf->getBool(section, "inclusive");
  directory = SescConf->getBool(section, "directory");
	if (directory && !inclusive) {
		I(0);
		MSG("ERROR: %s CCache can not have a 'directory' without being 'inclusive'",section);
		SescConf->notCorrect();
	}

  MemObj *lower_level = gms->declareMemoryObj(section, "lowerLevel");
  if(lower_level)
    addLowerLevel(lower_level);

  port = PortManager::create(section, this);
}
Esempio n. 10
0
bool ImagePNG::save(std::string filename, int compression_level)
{

    FILE *file;
#ifndef NDEBUG
    std::cout << "Writing PNG file " << filename << std::endl;
#endif
    /* make sure the file is there and open it read-only (binary) */
    if ((file = fopen(filename.c_str(), "wb")) == NULL)
    {
        std::cerr << "File write access failed : " << filename << std::endl;
        return false;
    }

    png_structp PNG_writer = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (PNG_writer == NULL)
    {
        std::cerr << "png_create_write_struct failed for file "<< filename << std::endl;
        fclose(file);
        return false;
    }

    png_infop PNG_info = png_create_info_struct(PNG_writer);
    if (PNG_info == NULL)
    {
        std::cerr << "png_create_info_struct failed for file " << filename << std::endl;
        png_destroy_write_struct(&PNG_writer, NULL);
        fclose(file);
        return false;
    }

    if (setjmp(png_jmpbuf(PNG_writer)))
    {
        std::cerr << "Writing failed for PNG file " << filename << std::endl;
        png_destroy_write_struct(&PNG_writer, &PNG_info);
        fclose(file);
        return false;
    }

    //png_init_io(PNG_writer, file);
	png_set_write_fn(PNG_writer, file, png_my_write_data, png_default_flush);

    png_uint_32 width, height;
    png_uint_32 bit_depth, channels, color_type;

    width = getWidth();
    height = getHeight();

    bit_depth = getBytesPerChannel() * 8;
    channels = getChannelCount();
    if (channels == 1)
        color_type = PNG_COLOR_TYPE_GRAY;
    else if (channels == 2)
        color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
    else if (channels == 3)
        color_type = PNG_COLOR_TYPE_RGB;
    else
        color_type = PNG_COLOR_TYPE_RGB_ALPHA;

    if (bit_depth != 8)
    {
        std::cerr << "Unsupported bitdepth "<< bit_depth <<" to write to PNG file "<<filename<<std::endl;
        png_destroy_write_struct(&PNG_writer, &PNG_info);
        fclose(file);
        return false;
    }
#ifndef NDEBUG
    std::cout << "PNG image "<<filename<<": "<<width<<"x"<<height<<"x"<<bit_depth*channels<<std::endl;
#endif
    png_set_IHDR(PNG_writer, PNG_info, width, height,
            bit_depth, color_type, PNG_INTERLACE_NONE,
            PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    /* set the zlib compression level */
    if (compression_level!=-1)
    {
        if (compression_level>=0 && compression_level<=9)
            png_set_compression_level(PNG_writer, compression_level);
        else
            std::cerr << "ERROR: compression level must be a value between 0 and 9" << std::endl;
    }

    png_byte** PNG_rows = (png_byte**)malloc(height * sizeof(png_byte*));

    unsigned char *data = getPixels();
    unsigned lineSize = getLineSize(0);
    for (png_uint_32 row = 0; row < height; ++row)
        PNG_rows[height - 1 - row] = data+row*lineSize;

    png_set_rows(PNG_writer, PNG_info, PNG_rows);

    png_write_png(PNG_writer, PNG_info, PNG_TRANSFORM_IDENTITY, NULL);

    free(PNG_rows);

    png_destroy_write_struct(&PNG_writer, &PNG_info);
    fclose(file);
    return true;
}
Esempio n. 11
0
	void ScrollBar::TrackMove(int _left, int _top)
	{
		if (mWidgetTrack == nullptr)
			return;

		const IntPoint& point = InputManager::getInstance().getLastPressedPosition(MouseButton::Left);

		if (mVerticalAlignment)
		{
			// расчитываем позицию виджета
			int start = mPreActionOffset.top + (_top - point.top);
			if (start < (int)mSkinRangeStart)
				start = (int)mSkinRangeStart;
			else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight()))
				start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getHeight());
			if (mWidgetTrack->getTop() != start)
				mWidgetTrack->setPosition(mWidgetTrack->getLeft(), start);

			// расчитываем положение соответствующее позиции
			// плюс пол позиции
			int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
			// высчитываем ближайшее значение и обновляем
			pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());

			// проверяем на выходы и изменения
			if (pos < 0)
				pos = 0;
			else if (pos >= (int)mScrollRange)
				pos = (int)mScrollRange - 1;
			if (pos == (int)mScrollPosition)
				return;

			mScrollPosition = pos;
		}
		else
		{
			// расчитываем позицию виджета
			int start = mPreActionOffset.left + (_left - point.left);
			if (start < (int)mSkinRangeStart)
				start = (int)mSkinRangeStart;
			else if (start > (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth()))
				start = (getTrackPlaceLength() - (int)mSkinRangeEnd - mWidgetTrack->getWidth());
			if (mWidgetTrack->getLeft() != start)
				mWidgetTrack->setPosition(IntPoint(start, mWidgetTrack->getTop()));

			// расчитываем положение соответствующее позиции
			// плюс пол позиции
			int pos = start - (int)mSkinRangeStart + (getLineSize() - getTrackSize()) / (((int)mScrollRange - 1) * 2);
			// высчитываем ближайшее значение и обновляем
			pos = pos * (int)(mScrollRange - 1) / (getLineSize() - getTrackSize());

			// проверяем на выходы и изменения
			if (pos < 0)
				pos = 0;
			else if (pos >= (int)mScrollRange)
				pos = (int)mScrollRange - 1;
			if (pos == (int)mScrollPosition)
				return;

			mScrollPosition = pos;
		}

		updateTrack();

		// отсылаем событие
		eventScrollChangePosition(this, (int)mScrollPosition);
	}
Esempio n. 12
0
void caGraphics::paintEvent( QPaintEvent *event )
{
    Q_UNUSED(event);

    if(thisHide) return;

    int m_margin = 3;
    QPointF p1,p2;
    QPainter painter( this );
    painter.setRenderHint( QPainter::Antialiasing );

    int margin = thisLineSize/2;
    int w = width() - 2 * margin;
    int h = height() - 2 * margin;

// do not increase linesize beyond the canvas size
    if(w <= 0 || h <= 0) {
        setLineSize(thisLineSize-1);
    }
    margin = thisLineSize/2;
    w = width() - 2 * margin;
    h = height() - 2 * margin;
    int x = margin;
    int y = margin;

    if(thisLineStyle == Dash) {
        painter.setPen( QPen( getLineColor(), getLineSize(), Qt::DotLine, Qt::SquareCap) );
    } else if (thisLineStyle == BigDash) {
        painter.setPen( QPen( getLineColor(), getLineSize(), Qt::DashLine, Qt::SquareCap) );
    } else {
        painter.setPen( QPen( getLineColor(), getLineSize(), Qt::SolidLine, Qt::SquareCap) );
    }

    if(thisFillStyle == Filled) {
        painter.setBrush(getForeground());
    }

    if(getForm() == Rectangle) {
        QPolygonF rectangle;
        rectangle.append(QPointF(x,y));
        rectangle.append(QPointF(x+w,y));
        rectangle.append(QPointF(x+w,y+h));
        rectangle.append(QPointF(x,y+h));
        rectangle.append(QPointF(x,y));
        // rotate
        QPolygonF rotated = rotateObject(thisTiltAngle, w, h, thisLineSize, rectangle);
        painter.drawPolygon(rotated);

    } else if(getForm() == Circle) {
        // rotate my calculated ellipse
        QPolygonF rotated = rotateObject(thisTiltAngle, w, h, thisLineSize, drawCircle(x, x+w, y, y+h));
        painter.drawPolygon(rotated);

    } else if(getForm() == Triangle) {
        QPolygonF triangle;
        triangle.append(QPointF(x+w/2,0));
        triangle.append(QPointF(x,y+h));
        triangle.append(QPointF(x+w,y+h));
        triangle.append(QPointF(x+w/2,0));

        // rotate
        QPolygonF rotated = rotateObject(thisTiltAngle, w, h, thisLineSize, triangle);
        painter.drawPolygon(rotated);

    } else if(getForm() == Arc) {
        if(thisFillStyle == Filled) {
            painter.drawPie (x, y, w, h, thisStartAngle * 16, thisSpanAngle * 16);
        } else {
            painter.drawArc (x, y, w, h, thisStartAngle * 16, thisSpanAngle * 16);
        }

    } else if(getForm() == Line) {
        QPolygonF line;
        line.append(QPointF(x,y+h/2));
        line.append(QPointF(x+w,y+h/2));

        // rotate
        QPolygonF rotated = rotateObject(thisTiltAngle, w, h, thisLineSize, line);
        painter.drawPolygon(rotated);

    } else if(getForm() == Arrow) {
        QPolygonF lines;
        QPolygonF head1;
        QPolygonF head2;

        p1 = QPointF( m_margin, height()/2 );
        p2 = QPointF( width()-m_margin, height()/2 );
        lines.append(p1);
        lines.append(p2);

        head1 = getHead(p1,p2);
        if (getArrowMode() == Double) {
            head2 = getHead(p2,p1);
        }

        for(int i=0; i<head1.count(); i++) lines.append(head1.at(i));
        for(int i=0; i<head2.count(); i++) lines.append(head2.at(i));

        // rotate
        QPolygonF rotated = rotateObject(thisTiltAngle, w, h, thisLineSize, lines);
        painter.drawPolygon(rotated);
    }

}
Esempio n. 13
0
void caPolyLine::paintEvent(QPaintEvent * /* event */)
{
    QStringList pairs;
    if(thisHide) return;

    QPainter painter(this);

    painter.setRenderHint( QPainter::Antialiasing );
    int nbPoints = 0;

    if(inEditor) {
      painter.setBrush(QColor(Qt::white));
      painter.drawRect(editSize);
    }

    if(thisLineStyle == Dash) {
        painter.setPen( QPen( getLineColor(), getLineSize(), Qt::DotLine,  Qt::FlatCap));
    } else if (thisLineStyle == BigDash) {
        painter.setPen( QPen( getLineColor(), getLineSize(), Qt::DashLine, Qt::FlatCap ));
    } else {
        painter.setPen( QPen( getLineColor(), getLineSize(), Qt::SolidLine, Qt::FlatCap));
    }

    if(inDesigner) {
        pairs = thisXYpairs.split(";", QString::SkipEmptyParts);
    } else {
        pairs = XYpairs.split(";", QString::SkipEmptyParts);
    }
    QPolygon polygon(pairs.count());

    for(int i=0; i< pairs.count(); i++) {
        QStringList xy = pairs.at(i).split(",", QString::SkipEmptyParts);
        if(xy.count() == 2) {
            polygon.putPoints(i, 1, atoi(qasc(xy.at(0))), atoi(qasc(xy.at(1))));
            lastPosition =  QPointF(atoi(qasc(xy.at(0))), atoi(qasc(xy.at(1))));
            nbPoints++;
        }
    }

    // when polygon, close the line
    if((thisPolyStyle == Polygon) && (nbPoints > 2)) {
        QStringList xy = pairs.at(0).split(",", QString::SkipEmptyParts);
        if(xy.count() == 2) {
            polygon.putPoints(nbPoints, 1, atoi(qasc(xy.at(0))), atoi(qasc(xy.at(1))));
            nbPoints++;
        }
    }

    if(thisFillStyle == Filled) {
        painter.setBrush(getForeground());
    }

    if(nbPoints > 0) {
        if(thisPolyStyle == Polygon) {
            painter.drawPolygon(polygon);
        } else {
            painter.drawPolyline(polygon);
        }
    }

    if(inEditor && mouseMove) {
      painter.setPen( QPen(QColor(Qt::red), getLineSize(), Qt::SolidLine, Qt::FlatCap ) );
      if(actualPosition != lastPosition)
         painter.drawLine(actualPosition, lastPosition);
    }
}