/** * Gets the pen needed to draw this entity. * The attributes can also come from the layer this entity is on * if the flags are set accordingly. * * @param resolve true: Resolve the pen to a drawable pen (e.g. the pen * from the layer or parent..) * false: Don't resolve and return a pen or ByLayer, ByBlock, ... * * @return Pen for this entity. */ RS_Pen RS_Entity::getPen(bool resolve) const { if (!resolve) { return pen; } else { RS_Pen p = pen; RS_Layer* l = getLayer(true); // use parental attributes (e.g. vertex of a polyline, block // entities when they are drawn in block documents): if (!p.isValid() || p.getColor().isByBlock()) { if (parent!=NULL) { p = parent->getPen(); } } // use layer attributes: else if (l!=NULL) { // layer is "ByBlock": /*if (layer->getName()=="ByBlock" && getBlockOrInsert()!=NULL) { p = getBlockOrInsert()->getPen(); } else {*/ // use layer's color: if (p.getColor().isByLayer()) { p.setColor(l->getPen().getColor()); } // use layer's width: if (p.getWidth()==RS2::WidthByLayer) { p.setWidth(l->getPen().getWidth()); } // use layer's linetype: if (p.getLineType()==RS2::LineByLayer) { p.setLineType(l->getPen().getLineType()); } //} } return p; } }
void RS_GraphicView::setPenForEntity(RS_Painter *painter,RS_Entity *e) { if (draftMode) { painter->setPen(RS_Pen(foreground, RS2::Width00, RS2::SolidLine)); } // Getting pen from entity (or layer) RS_Pen pen = e->getPen(true); int w = pen.getWidth(); if (w<0) { w = 0; } #if 1 /*TRUE*/ // - Scale pen width. // - Notes: pen width is not scaled on print and print preview. // This is the standard (AutoCAD like) behaviour. // bug# 3437941 // ------------------------------------------------------------ if (!draftMode) { double uf = 1.0; // Unit factor. double wf = 1.0; // Width factor. RS_Graphic* graphic = container->getGraphic(); if (graphic) { uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit()); if ( (isPrinting() || isPrintPreview()) && graphic->getPaperScale() > RS_TOLERANCE ) { wf = 1.0 / graphic->getPaperScale(); } } pen.setScreenWidth(toGuiDX(w / 100.0 * uf * wf)); } else { // pen.setWidth(RS2::Width00); pen.setScreenWidth(0); } #else // - Scale pen width. // - Notes: pen width is scaled on print and print preview. // This is not the standard (AutoCAD like) behaviour. // -------------------------------------------------------- if (!draftMode) { double uf = 1.0; // Unit factor. RS_Graphic* graphic = container->getGraphic(); if (graphic) uf = RS_Units::convert(1.0, RS2::Millimeter, graphic->getUnit()); pen.setScreenWidth(toGuiDX(w / 100.0 * uf)); } else pen.setScreenWidth(0); #endif // prevent drawing with 1-width which is slow: if (RS_Math::round(pen.getScreenWidth())==1) { pen.setScreenWidth(0.0); } // prevent background color on background drawing: if (pen.getColor().stripFlags()==background.stripFlags()) { pen.setColor(foreground); } // this entity is selected: if (e->isSelected()) { pen.setLineType(RS2::DotLine); pen.setColor(selectedColor); } // this entity is highlighted: if (e->isHighlighted()) { pen.setColor(highlightedColor); } // deleting not drawing: if (getDeleteMode()) { pen.setColor(background); } painter->setPen(pen); }
/** * Updates the entity buffer of this insert entity. This method * needs to be called whenever the block this insert is based on changes. */ void RS_Insert::update() { RS_DEBUG->print("RS_Insert::update"); RS_DEBUG->print("RS_Insert::update: name: %s", data.name.toLatin1().data()); // RS_DEBUG->print("RS_Insert::update: insertionPoint: %f/%f", // data.insertionPoint.x, data.insertionPoint.y); if (updateEnabled==false) { return; } clear(); RS_Block* blk = getBlockForInsert(); if (blk==nullptr) { //return nullptr; RS_DEBUG->print("RS_Insert::update: Block is nullptr"); return; } if (isUndone()) { RS_DEBUG->print("RS_Insert::update: Insert is in undo list"); return; } if (fabs(data.scaleFactor.x)<1.0e-6 || fabs(data.scaleFactor.y)<1.0e-6) { RS_DEBUG->print("RS_Insert::update: scale factor is 0"); return; } RS_Pen tmpPen; /*QListIterator<RS_Entity> it = createIterator(); RS_Entity* e; while ( (e = it.current()) != nullptr ) { ++it;*/ RS_DEBUG->print("RS_Insert::update: cols: %d, rows: %d", data.cols, data.rows); RS_DEBUG->print("RS_Insert::update: block has %d entities", blk->count()); //int i_en_counts=0; for(auto e: *blk){ for (int c=0; c<data.cols; ++c) { // RS_DEBUG->print("RS_Insert::update: col %d", c); for (int r=0; r<data.rows; ++r) { // i_en_counts++; // RS_DEBUG->print("RS_Insert::update: row %d", r); if (e->rtti()==RS2::EntityInsert && data.updateMode!=RS2::PreviewUpdate) { // RS_DEBUG->print("RS_Insert::update: updating sub-insert"); ((RS_Insert*)e)->update(); } // RS_DEBUG->print("RS_Insert::update: cloning entity"); RS_Entity* ne; if ( (data.scaleFactor.x - data.scaleFactor.y)>1.0e-6) { if (e->rtti()== RS2::EntityArc) { RS_Arc* a= (RS_Arc*)e; ne = new RS_Ellipse(this, RS_EllipseData(a->getCenter(), RS_Vector(a->getRadius(), 0), 1, a->getAngle1(), a->getAngle2(), a->isReversed() )); ne->setLayer(e->getLayer()); ne->setPen(e->getPen(false)); } else if (e->rtti()== RS2::EntityCircle) { RS_Circle* a= (RS_Circle*)e; ne = new RS_Ellipse(this, RS_EllipseData(a->getCenter(), RS_Vector(a->getRadius(), 0), 1, 0.0,2.0*M_PI, false)); ne->setLayer(e->getLayer()); ne->setPen(e->getPen(false)); } else ne = e->clone(); } else ne = e->clone(); ne->initId(); ne->setUpdateEnabled(false); // if entity layer are 0 set to insert layer to allow "1 layer control" bug ID #3602152 RS_Layer *l= ne->getLayer();//special fontchar block don't have if (l != nullptr && ne->getLayer()->getName() == "0") ne->setLayer(this->getLayer()); ne->setParent(this); ne->setVisible(getFlag(RS2::FlagVisible)); // RS_DEBUG->print("RS_Insert::update: transforming entity"); // Move: // RS_DEBUG->print("RS_Insert::update: move 1"); if (fabs(data.scaleFactor.x)>1.0e-6 && fabs(data.scaleFactor.y)>1.0e-6) { ne->move(data.insertionPoint + RS_Vector(data.spacing.x/data.scaleFactor.x*c, data.spacing.y/data.scaleFactor.y*r)); } else { ne->move(data.insertionPoint); } // Move because of block base point: // RS_DEBUG->print("RS_Insert::update: move 2"); ne->move(blk->getBasePoint()*-1); // Scale: // RS_DEBUG->print("RS_Insert::update: scale"); ne->scale(data.insertionPoint, data.scaleFactor); // Rotate: // RS_DEBUG->print("RS_Insert::update: rotate"); ne->rotate(data.insertionPoint, data.angle); // Select: ne->setSelected(isSelected()); // individual entities can be on indiv. layers tmpPen = ne->getPen(false); // color from block (free floating): if (tmpPen.getColor()==RS_Color(RS2::FlagByBlock)) { tmpPen.setColor(getPen().getColor()); } // line width from block (free floating): if (tmpPen.getWidth()==RS2::WidthByBlock) { tmpPen.setWidth(getPen().getWidth()); } // line type from block (free floating): if (tmpPen.getLineType()==RS2::LineByBlock) { tmpPen.setLineType(getPen().getLineType()); } // now that we've evaluated all flags, let's strip them: // TODO: strip all flags (width, line type) //tmpPen.setColor(tmpPen.getColor().stripFlags()); ne->setPen(tmpPen); ne->setUpdateEnabled(true); if (data.updateMode!=RS2::PreviewUpdate) { // RS_DEBUG->print("RS_Insert::update: updating new entity"); ne->update(); } // RS_DEBUG->print("RS_Insert::update: adding new entity"); appendEntity(ne); // std::cout<<"done # of entity: "<<i_en_counts<<std::endl; } } } calculateBorders(); RS_DEBUG->print("RS_Insert::update: OK"); }
void Plugin_Entity::updateData(QHash<int, QVariant> *data){ if (entity == NULL) return; QHash<int, QVariant> hash = *data; QString str; RS_Vector vec; RS_Pen epen = entity->getPen(); // double num; if (hash.contains(DPI::LAYER)) { str = (hash.take(DPI::LAYER)).toString(); entity->setLayer(str); } if (hash.contains(DPI::LTYPE)) { str = (hash.take(DPI::LTYPE)).toString(); epen.setLineType( Converter.str2lt(str) ); } if (hash.contains(DPI::LWIDTH)) { str = (hash.take(DPI::LWIDTH)).toString(); epen.setWidth( Converter.str2lw(str) ); } if (hash.contains(DPI::COLOR)) { QColor color = hash.take(DPI::COLOR).value<QColor>(); epen.setColor(color); } entity->setPen(epen); RS2::EntityType et = entity->rtti(); switch (et) { //atomicEntity case RS2::EntityLine: { vec = static_cast<RS_Line*>(entity)->getStartpoint(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } static_cast<RS_Line*>(entity)->setStartpoint(vec); vec = static_cast<RS_Line*>(entity)->getEndpoint(); if (hash.contains(DPI::ENDX)) { vec.x = (hash.take(DPI::ENDX)).toDouble(); } if (hash.contains(DPI::ENDY)) { vec.y = (hash.take(DPI::ENDY)).toDouble(); } static_cast<RS_Line*>(entity)->setEndpoint(vec); break;} case RS2::EntityPoint: { vec = static_cast<RS_Point*>(entity)->getPos(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } static_cast<RS_Point*>(entity)->setPos(vec); break; } case RS2::EntityArc: { RS_Arc *arc = static_cast<RS_Arc*>(entity); vec = arc->getCenter(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } arc->setCenter(vec); if (hash.contains(DPI::RADIUS)) { arc->setRadius( (hash.take(DPI::RADIUS)).toDouble() ); } if (hash.contains(DPI::STARTANGLE)) { arc->setAngle1( (hash.take(DPI::STARTANGLE)).toDouble() ); vec.y = (hash.take(DPI::STARTANGLE)).toDouble(); } if (hash.contains(DPI::ENDANGLE)) { arc->setAngle2( (hash.take(DPI::ENDANGLE)).toDouble() ); } break;} case RS2::EntityCircle: { RS_Circle *cir = static_cast<RS_Circle*>(entity); vec = cir->getCenter(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } cir->setCenter(vec); if (hash.contains(DPI::RADIUS)) { cir->setRadius( (hash.take(DPI::RADIUS)).toDouble() ); } break;} case RS2::EntityEllipse: { RS_Ellipse *ellipse = static_cast<RS_Ellipse*>(entity); vec = ellipse->getCenter(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble(); } if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble(); } ellipse->setCenter(vec); vec = ellipse->getMajorP(); if (hash.contains(DPI::ENDX)) { vec.x = (hash.take(DPI::ENDX)).toDouble(); } if (hash.contains(DPI::ENDY)) { vec.y = (hash.take(DPI::ENDY)).toDouble(); } ellipse->setMajorP(vec); if (hash.contains(DPI::STARTANGLE)) { ellipse->setAngle1((hash.take(DPI::STARTANGLE)).toDouble()); } if (hash.contains(DPI::ENDANGLE)) { ellipse->setAngle2((hash.take(DPI::ENDANGLE)).toDouble()); } if (hash.contains(DPI::HEIGHT)) { ellipse->setRatio((hash.take(DPI::HEIGHT)).toDouble()); } if (hash.contains(DPI::REVERSED)) { ellipse->setReversed( (hash.take(DPI::REVERSED)).toBool()); } break;} case RS2::EntitySolid: //TODO //Only used in dimensions ? break; case RS2::EntityConstructionLine: //Unused ? break; case RS2::EntityImage: { break;} case RS2::EntityOverlayBox: //Unused ? break; //EntityContainer case RS2::EntityInsert: { break;} case RS2::EntityText: { RS_Text *txt = static_cast<RS_Text*>(entity); bool move = false; vec = txt->getInsertionPoint(); if (hash.contains(DPI::STARTX)) { vec.x = (hash.take(DPI::STARTX)).toDouble() - vec.x; move = true; } else vec.x = 0; if (hash.contains(DPI::STARTY)) { vec.y = (hash.take(DPI::STARTY)).toDouble() - vec.y; move = true; } else vec.y = 0; if (move) txt->move(vec); if (hash.contains(DPI::TEXTCONTENT)) { txt->setText( (hash.take(DPI::TEXTCONTENT)).toString() ); } if (hash.contains(DPI::STARTANGLE)) { txt->setAngle( (hash.take(DPI::STARTANGLE)).toDouble() ); } if (hash.contains(DPI::HEIGHT)) { txt->setHeight( (hash.take(DPI::HEIGHT)).toDouble() ); } break;} case RS2::EntityHatch: break; case RS2::EntitySpline: break; case RS2::EntityPolyline: { RS_Polyline *pl = static_cast<RS_Polyline*>(entity); if (hash.take(DPI::CLOSEPOLY).toBool()) { pl->setClosed(true); }else{ pl->setClosed(false); } break;} case RS2::EntityVertex: break; case RS2::EntityDimAligned: break; case RS2::EntityDimLinear: break; case RS2::EntityDimRadial: break; case RS2::EntityDimDiametric: break; case RS2::EntityDimAngular: break; case RS2::EntityDimLeader: break; case RS2::EntityUnknown: default: break; } entity->update(); }
/** * Gets the pen needed to draw this entity. * The attributes can also come from the layer this entity is on * if the flags are set accordingly. * * @param resolve true: Resolve the pen to a drawable pen (e.g. the pen * from the layer or parent..) * false: Don't resolve and return a pen or ByLayer, ByBlock, ... * * @return Pen for this entity. */ RS_Pen RS_Entity::getPen(bool resolve) const { if (!resolve) { return pen; } else { RS_Pen p = pen; RS_Layer* l = getLayer(true); // use parental attributes (e.g. vertex of a polyline, block // entities when they are drawn in block documents): if (parent) { //if pen is invalid gets all from parent if (!p.isValid() ) { p = parent->getPen(); } //pen is valid, verify byBlock parts RS_EntityContainer* ep = parent; //If parent is byblock check parent.parent (nested blocks) while (p.getColor().isByBlock()){ if (ep) { p.setColor(parent->getPen().getColor()); ep = ep->parent; } else break; } ep = parent; while (p.getWidth()==RS2::WidthByBlock){ if (ep) { p.setWidth(parent->getPen().getWidth()); ep = ep->parent; } else break; } ep = parent; while (p.getLineType()==RS2::LineByBlock){ if (ep) { p.setLineType(parent->getPen().getLineType()); ep = ep->parent; } else break; } } // check byLayer attributes: if (l) { // use layer's color: if (p.getColor().isByLayer()) { p.setColor(l->getPen().getColor()); } // use layer's width: if (p.getWidth()==RS2::WidthByLayer) { p.setWidth(l->getPen().getWidth()); } // use layer's linetype: if (p.getLineType()==RS2::LineByLayer) { p.setLineType(l->getPen().getLineType()); } //} } return p; } }
/** * Updates the entity buffer of this insert entity. This method * needs to be called whenever the block this insert is based on changes. */ void RS_Insert::update() { RS_DEBUG->print("RS_Insert::update"); RS_DEBUG->print("RS_Insert::update: name: %s", data.name.latin1()); RS_DEBUG->print("RS_Insert::update: insertionPoint: %f/%f", data.insertionPoint.x, data.insertionPoint.y); if (updateEnabled==false) { return; } clear(); RS_Block* blk = getBlockForInsert(); if (blk==NULL) { //return NULL; RS_DEBUG->print("RS_Insert::update: Block is NULL"); return; } if (isUndone()) { RS_DEBUG->print("RS_Insert::update: Insert is in undo list"); return; } if (fabs(data.scaleFactor.x)<1.0e-6 || fabs(data.scaleFactor.y)<1.0e-6) { RS_DEBUG->print("RS_Insert::update: scale factor is 0"); return; } RS_Pen tmpPen; /*RS_PtrListIterator<RS_Entity> it = createIterator(); RS_Entity* e; while ( (e = it.current()) != NULL ) { ++it;*/ RS_DEBUG->print("RS_Insert::update: cols: %d, rows: %d", data.cols, data.rows); RS_DEBUG->print("RS_Insert::update: block has %d entities", blk->count()); for (RS_Entity* e=blk->firstEntity(); e!=NULL; e=blk->nextEntity()) { for (int c=0; c<data.cols; ++c) { RS_DEBUG->print("RS_Insert::update: col %d", c); for (int r=0; r<data.rows; ++r) { RS_DEBUG->print("RS_Insert::update: row %d", r); if (e->rtti()==RS2::EntityInsert && data.updateMode!=RS2::PreviewUpdate) { RS_DEBUG->print("RS_Insert::update: updating sub-insert"); ((RS_Insert*)e)->update(); } RS_DEBUG->print("RS_Insert::update: cloning entity"); RS_Entity* ne = e->clone(); ne->initId(); ne->setUpdateEnabled(false); ne->setParent(this); ne->setVisible(getFlag(RS2::FlagVisible)); RS_DEBUG->print("RS_Insert::update: transforming entity"); // Move: RS_DEBUG->print("RS_Insert::update: move 1"); if (fabs(data.scaleFactor.x)>1.0e-6 && fabs(data.scaleFactor.y)>1.0e-6) { ne->move(data.insertionPoint + RS_Vector(data.spacing.x/data.scaleFactor.x*c, data.spacing.y/data.scaleFactor.y*r)); } else { ne->move(data.insertionPoint); } // Move because of block base point: RS_DEBUG->print("RS_Insert::update: move 2"); ne->move(blk->getBasePoint()*-1); // Scale: RS_DEBUG->print("RS_Insert::update: scale"); ne->scale(data.insertionPoint, data.scaleFactor); // Rotate: RS_DEBUG->print("RS_Insert::update: rotate"); ne->rotate(data.insertionPoint, data.angle); // Select: ne->setSelected(isSelected()); // individual entities can be on indiv. layers tmpPen = ne->getPen(false); // color from block (free floating): if (tmpPen.getColor()==RS_Color(RS2::FlagByBlock)) { tmpPen.setColor(getPen().getColor()); } // line width from block (free floating): if (tmpPen.getWidth()==RS2::WidthByBlock) { tmpPen.setWidth(getPen().getWidth()); } // line type from block (free floating): if (tmpPen.getLineType()==RS2::LineByBlock) { tmpPen.setLineType(getPen().getLineType()); } // now that we've evaluated all flags, let's strip them: // TODO: strip all flags (width, line type) //tmpPen.setColor(tmpPen.getColor().stripFlags()); ne->setPen(tmpPen); ne->setUpdateEnabled(true); if (data.updateMode!=RS2::PreviewUpdate) { RS_DEBUG->print("RS_Insert::update: updating new entity"); ne->update(); } RS_DEBUG->print("RS_Insert::update: adding new entity"); addEntity(ne); } } } calculateBorders(); RS_DEBUG->print("RS_Insert::update: OK"); }
/** * @return Path to the thumbnail of the given DXF file. If no thumbnail exists, one is * created in the user's home. If no thumbnail can be created, an empty string is returned. */ QString QG_LibraryWidget::getPathToPixmap(const QString& dir, const QString& dxfFile, const QString& dxfPath) { // the thumbnail must be created in the user's home. #if QT_VERSION < 0x040400 QString iconCacheLocation = emu_qt44_storageLocationData() + QDir::separator() + "iconCache" + QDir::separator(); #elif QT_VERSION >= 0x050000 QString iconCacheLocation=QStandardPaths::writableLocation(QStandardPaths::DataLocation) + QDir::separator() + "iconCache" + QDir::separator(); #else QString iconCacheLocation=QDesktopServices::storageLocation(QDesktopServices::DataLocation) + QDir::separator() + "iconCache" + QDir::separator(); #endif RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: " "dir: '%s' dxfFile: '%s' dxfPath: '%s'", dir.toLatin1().data(), dxfFile.toLatin1().data(), dxfPath.toLatin1().data()); // List of all directories that contain part libraries: QStringList directoryList = RS_SYSTEM->getDirectoryList("library"); directoryList.prepend(iconCacheLocation); QStringList::Iterator it; QFileInfo fiDxf(dxfPath); QString itemDir; QString pngPath; // look in all possible system directories for PNG files // in the current library path: for (it=directoryList.begin(); it!=directoryList.end(); ++it) { itemDir = (*it)+dir; pngPath = itemDir + QDir::separator() + fiDxf.baseName() + ".png"; RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: checking: '%s'", pngPath.toLatin1().data()); QFileInfo fiPng(pngPath); // the thumbnail exists: if (fiPng.isFile()) { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: dxf date: %s, png date: %s", fiDxf.lastModified().toString().toLatin1().data(), fiPng.lastModified().toString().toLatin1().data()); if (fiPng.lastModified() > fiDxf.lastModified()) { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: thumbnail found: '%s'", pngPath.toLatin1().data()); return pngPath; } else { RS_DEBUG->print("QG_LibraryWidget::getPathToPixmap: thumbnail needs to be updated: '%s'", pngPath.toLatin1().data()); } } } // create all directories needed: RS_SYSTEM->createPaths(iconCacheLocation + dir); // QString foo=iconCacheLocation + dir + QDir::separator() + fiDxf.baseName() + ".png"; pngPath = iconCacheLocation + dir + QDir::separator() + fiDxf.baseName() + ".png"; QPixmap* buffer = new QPixmap(128,128); RS_PainterQt painter(buffer); painter.setBackground(RS_Color(255,255,255)); painter.eraseRect(0,0, 128,128); RS_StaticGraphicView gv(128,128, &painter); RS_Graphic graphic; if (graphic.open(dxfPath, RS2::FormatUnknown)) { gv.setContainer(&graphic); gv.zoomAuto(false); // gv.drawEntity(&graphic, true); for (RS_Entity* e=graphic.firstEntity(RS2::ResolveAll); e; e=graphic.nextEntity(RS2::ResolveAll)) { if (e->rtti() != RS2::EntityHatch){ RS_Pen pen = e->getPen(); pen.setColor(Qt::black); e->setPen(pen); } gv.drawEntity(&painter, e); } QImageWriter iio; QImage img; img = buffer->toImage(); img = img.scaled(64,64, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ); // iio.setImage(img); iio.setFileName(pngPath); iio.setFormat("PNG"); if (!iio.write(img)) { pngPath = ""; RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::getPathToPixmap: Cannot write thumbnail: '%s'", pngPath.toLatin1().data()); } } else { RS_DEBUG->print(RS_Debug::D_ERROR, "QG_LibraryWidget::getPathToPixmap: Cannot open file: '%s'", dxfPath.toLatin1().data()); } // GraphicView deletes painter painter.end(); delete buffer; return pngPath; }