bool RS_ActionPolylineEquidistant::makeContour() { if (container==NULL) { RS_DEBUG->print("RS_ActionPolylineEquidistant::makeContour: no valid container", RS_Debug::D_WARNING); return false; } RS_Vector offset(false); QList<RS_Entity*> addList; if (document!=NULL) { document->startUndoCycle(); } double neg = 1.0; if(bRightSide) neg = -1.0; // Create new entites RS_Line line1(NULL, RS_LineData(RS_Vector(true), RS_Vector(true))); RS_Line line2(NULL, RS_LineData(RS_Vector(true), RS_Vector(true))); for (int num=1; num<=number || (number==0 && num<=1); num++) { RS_Polyline* newPolyline = new RS_Polyline(container); newPolyline->setClosed(((RS_Polyline*)originalEntity)->isClosed()); // newPolyline->setSelected((RS_Polyline*)originalEntity)->isSelected()); newPolyline->setLayer(((RS_Polyline*)originalEntity)->getLayer()); newPolyline->setPen(((RS_Polyline*)originalEntity)->getPen()); bool first = true; RS_Entity* lastEntity = ((RS_Polyline*)originalEntity)->lastEntity(); for (RS_Entity* en=((RS_Polyline*)originalEntity)->firstEntity(); en!=NULL; en=((RS_Polyline*)originalEntity)->nextEntity()) { double bulge = 0.0; if (en->rtti()==RS2::EntityArc) { double r0 = ((RS_Arc*)en)->getRadius(); double r = r0 - dist*neg; if(r < 0) break; ((RS_Arc*)en)->setRadius(r); bulge = ((RS_Arc*)en)->getBulge(); ((RS_Arc*)en)->setRadius(r0); } else { bulge = 0.0; } RS_Vector v1 = ((RS_AtomicEntity*)en)->getStartpoint(); RS_Vector v2 = ((RS_AtomicEntity*)en)->getEndpoint(); offset.set(dist * cos(v1.angleTo(v2)+M_PI*0.5*neg), dist * sin(v1.angleTo(v2)+M_PI*0.5*neg)); v1.move(offset*num); v2.move(offset*num); if (first) { line1.setStartpoint(v1); line1.setEndpoint(v2); if(newPolyline->isClosed()){ RS_Vector v01 = ((RS_AtomicEntity*)lastEntity)->getStartpoint(); RS_Vector v02 = ((RS_AtomicEntity*)en)->getStartpoint(); offset.set(dist * cos(v01.angleTo(v02)+M_PI*0.5*neg), dist * sin(v01.angleTo(v02)+M_PI*0.5*neg)); v01.move(offset*num); v02.move(offset*num); line2.setStartpoint(v01); line2.setEndpoint(v02); RS_VectorSolutions vsol = RS_Information::getIntersection(&line1, &line2, false); v1 = vsol.get(0); } newPolyline->setStartpoint(v1); newPolyline->addVertex(v1, bulge); first = false; }else{ line2.setStartpoint(v1); line2.setEndpoint(v2); RS_VectorSolutions vsol = RS_Information::getIntersection(&line1, &line2, false); RS_Vector v = vsol.get(0); newPolyline->addVertex(v, bulge); newPolyline->setEndpoint(v); line1.setStartpoint(v1); line1.setEndpoint(v2); if (en==lastEntity/* && newPolyline->isClosed()==false*/){ newPolyline->addVertex(v2, bulge); } } } double bulge = lastEntity->rtti() == RS2::EntityArc? ((RS_Arc*)lastEntity)->getBulge():0.0; // newPolyline->setNextBulge(bulge); newPolyline->endPolyline(); container->addEntity(newPolyline); document->addUndoable(newPolyline); } if (document!=NULL) { document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->redraw(); } return true; }
/** * Loads the font into memory. * * @retval true font was already loaded or is loaded now. * @retval false font could not be loaded. */ bool RS_Font::loadFont() { RS_DEBUG->print("RS_Font::loadFont"); if (loaded) { return true; } QString path; // Search for the appropriate font if we have only the name of the font: if (!fileName.toLower().contains(".cxf") && !fileName.toLower().contains(".lff")) { QStringList fonts = RS_SYSTEM->getNewFontList(); #if QT_VERSION < 0x040500 emu_qt45_QList_append(fonts, RS_SYSTEM->getFontList()); #else fonts.append(RS_SYSTEM->getFontList()); #endif QFileInfo file; for (QStringList::Iterator it = fonts.begin(); it!=fonts.end(); it++) { if (QFileInfo(*it).baseName().toLower()==fileName.toLower()) { path = *it; break; } } } // We have the full path of the font: else { path = fileName; } // No font paths found: if (path.isEmpty()) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Font::loadFont: No fonts available."); return false; } // Open cxf file: QFile f(path); if (!f.open(QIODevice::ReadOnly)) { RS_DEBUG->print(RS_Debug::D_WARNING, "RS_Font::loadFont: Cannot open font file: %s", path.toLatin1().data()); return false; } else { RS_DEBUG->print("RS_Font::loadFont: " "Successfully opened font file: %s", path.toLatin1().data()); } f.close(); if (path.contains(".cxf")) readCXF(path); if (path.contains(".lff")) readLFF(path); RS_Block* bk = letterList.find(QChar(0xfffd)); if (!bk) { // create new letter: RS_FontChar* letter = new RS_FontChar(nullptr, QChar(0xfffd), RS_Vector(0.0, 0.0)); RS_Polyline* pline = new RS_Polyline(letter, RS_PolylineData()); pline->setPen(RS_Pen(RS2::FlagInvalid)); pline->setLayer(nullptr); pline->addVertex(RS_Vector(1, 0), 0); pline->addVertex(RS_Vector(0, 2), 0); pline->addVertex(RS_Vector(1, 4), 0); pline->addVertex(RS_Vector(2, 2), 0); pline->addVertex(RS_Vector(1, 0), 0); letter->addEntity(pline); letter->calculateBorders(); letterList.add(letter); } loaded = true; RS_DEBUG->print("RS_Font::loadFont OK"); return true; }
bool RS_ActionPolylineEquidistant::makeContour() { if (container==NULL) { RS_DEBUG->print("RS_ActionPolylineEquidistant::makeContour: no valid container", RS_Debug::D_WARNING); return false; } RS_Polyline* originalPolyline = (RS_Polyline*)originalEntity; //create a list of entities to offset without length = 0 QList<RS_Entity*> entities; for (RS_Entity* en=originalPolyline->firstEntity(); en!=NULL; en=originalPolyline->nextEntity()) { if (en->getLength() > 1.0e-12) entities.append(en); } if (entities.isEmpty()) { return false; } if (document!=NULL) { document->startUndoCycle(); } double neg = 1.0; if(bRightSide) neg = -1.0; // Create new helper entities RS_Line line1(NULL, RS_LineData(RS_Vector(true), RS_Vector(true)));//current line RS_Line lineFirst(NULL, RS_LineData(RS_Vector(true), RS_Vector(true)));//previous line RS_Arc arc1(NULL, RS_ArcData(RS_Vector(true), 0,0,0,false));//current arc RS_Arc arcFirst(NULL, RS_ArcData(RS_Vector(true), 0,0,0,false));//previous arc for (int num=1; num<=number || (number==0 && num<=1); num++) { RS_Polyline* newPolyline = new RS_Polyline(container); newPolyline->setLayer(((RS_Polyline*)originalEntity)->getLayer()); newPolyline->setPen(((RS_Polyline*)originalEntity)->getPen()); bool first = true; bool closed = originalPolyline->isClosed(); double bulge = 0.0; RS_Entity* en; RS_Entity* prevEntity = entities.last(); RS_Entity* currEntity; for (int i = 0; i < entities.size(); ++i) { en = entities.at(i); RS_Vector v(false); if (en->rtti()==RS2::EntityArc) { currEntity = &arc1; calculateOffset(currEntity, en, dist*num*neg); bulge = arc1.getBulge(); } else { currEntity = &line1; bulge = 0.0; calculateOffset(currEntity, en, dist*num*neg); } if (first) { if (closed) { if (prevEntity->rtti()==RS2::EntityArc) { prevEntity = calculateOffset(&arcFirst, prevEntity, dist*num*neg); } else { prevEntity = calculateOffset(&lineFirst, prevEntity, dist*num*neg); } v = calculateIntersection(prevEntity, currEntity); } if (!v.valid) { v = currEntity->getStartpoint(); closed = false; } else if (currEntity->rtti()==RS2::EntityArc) { //update bulge arc1.setAngle1(arc1.getCenter().angleTo(v)); arc1.calculateEndpoints(); bulge = arc1.getBulge(); } first = false; if (!prevEntity) break; //prevent crash if not exist offset for prevEntity } else { v = calculateIntersection(prevEntity, currEntity); if (!v.valid) { v= prevEntity->getEndpoint(); double dess = currEntity->getStartpoint().distanceTo(prevEntity->getEndpoint()); if (dess > 1.0e-12) { newPolyline->addVertex(v, bulge); prevEntity = NULL; break; } } double startAngle = prevEntity->getStartpoint().angleTo(prevEntity->getEndpoint()); if (prevEntity->rtti()==RS2::EntityArc) { arcFirst.setAngle2(arcFirst.getCenter().angleTo(v)); arcFirst.calculateEndpoints(); newPolyline->setNextBulge(arcFirst.getBulge()); } //check if the entity are reverted if (abs (prevEntity->getStartpoint().angleTo(prevEntity->getEndpoint())- startAngle) > 0.785) { prevEntity = newPolyline->lastEntity(); RS_Vector v0 = calculateIntersection(prevEntity, currEntity); if (prevEntity->rtti()==RS2::EntityArc) { ((RS_Arc*)prevEntity)->setAngle2(arcFirst.getCenter().angleTo(v0)); ((RS_Arc*)prevEntity)->calculateEndpoints(); newPolyline->setNextBulge( ((RS_Arc*)prevEntity)->getBulge() ); } else { ((RS_Line*)prevEntity)->setEndpoint(v0); newPolyline->setNextBulge( 0.0 ); } newPolyline->setEndpoint(v0); } if (currEntity->rtti()==RS2::EntityArc) { arc1.setAngle1(arc1.getCenter().angleTo(v)); arc1.calculateEndpoints(); bulge = arc1.getBulge(); } else bulge = 0.0; } if (prevEntity) { newPolyline->addVertex(v, bulge, false); if (currEntity->rtti()==RS2::EntityArc) { arcFirst.setData(arc1.getData()); arcFirst.calculateEndpoints(); prevEntity = &arcFirst; } else { lineFirst.setStartpoint(line1.getStartpoint()); lineFirst.setEndpoint(line1.getEndpoint()); prevEntity = &lineFirst; } } } //properly terminated, check closed if (prevEntity) { if (closed) { if (currEntity->rtti()==RS2::EntityArc) { arc1.setAngle2(arc1.getCenter().angleTo(newPolyline->getStartpoint())); arc1.calculateEndpoints(); newPolyline->setNextBulge(arc1.getBulge()); bulge = arc1.getBulge(); } newPolyline->setClosed(true, bulge); } else { newPolyline->addVertex(currEntity->getEndpoint(), bulge); } } if (!newPolyline->isEmpty()) { container->addEntity(newPolyline); document->addUndoable(newPolyline); } } if (document!=NULL) { document->endUndoCycle(); } if (graphicView!=NULL) { graphicView->redraw(); } return true; }
RS_Block* RS_Font::generateLffFont(const QString& ch){ if(rawLffFontList.contains(ch) == false ){ RS_DEBUG->print("RS_Font::generateLffFont(QChar %s ) : can not find the letter in given lff font file",qPrintable(ch)); return nullptr; } // create new letter: RS_FontChar* letter = new RS_FontChar(nullptr, ch, RS_Vector(0.0, 0.0)); // Read entities of this letter: QStringList vertex; QStringList coords; QStringList fontData=rawLffFontList[ch]; QString line; while(fontData.isEmpty() == false) { line = fontData.takeFirst(); if (line.isEmpty()) { continue; } // Defined char: if (line.at(0)=='C') { line.remove(0,1); int uCode = line.toInt(nullptr, 16); QChar ch = QChar(uCode); RS_Block* bk = letterList.find(ch); if (!bk && rawLffFontList.contains(ch)) { generateLffFont(ch); bk = letterList.find(ch); } if (bk) { RS_Entity* bk2 = bk->clone(); bk2->setPen(RS_Pen(RS2::FlagInvalid)); bk2->setLayer(nullptr); letter->addEntity(bk2); } } //sequence: else { vertex = line.split(';', QString::SkipEmptyParts); //at least is required two vertex if (vertex.size()<2) continue; RS_Polyline* pline = new RS_Polyline(letter, RS_PolylineData()); pline->setPen(RS_Pen(RS2::FlagInvalid)); pline->setLayer(nullptr); for (int i = 0; i < vertex.size(); ++i) { double x1, y1; double bulge = 0; coords = vertex.at(i).split(',', QString::SkipEmptyParts); //at least X,Y is required if (coords.size()<2) continue; x1 = coords.at(0).toDouble(); y1 = coords.at(1).toDouble(); //check presence of bulge if (coords.size() == 3 && coords.at(2).at(0) == QChar('A')){ QString bulgeStr = coords.at(2); bulge = bulgeStr.remove(0,1).toDouble(); } pline->setNextBulge(bulge); pline->addVertex(RS_Vector(x1, y1), bulge); } letter->addEntity(pline); } } if (letter->isEmpty()) { delete letter; return nullptr; } else { letter->calculateBorders(); letterList.add(letter); return letter; } }
void RS_Font::readLFF(QString path) { QString line; QFile f(path); encoding = "UTF-8"; f.open(QIODevice::ReadOnly); QTextStream ts(&f); // Read line by line until we find a new letter: while (!ts.atEnd()) { line = ts.readLine(); if (line.isEmpty()) continue; // Read font settings: if (line.at(0)=='#') { QStringList lst =line.remove(0,1).split(':', QString::SkipEmptyParts); //if size is < 2 is a comentary not parameter if (lst.size()<2) continue; QString identifier = lst.at(0).trimmed(); QString value = lst.at(1).trimmed(); if (identifier.toLower()=="letterspacing") { letterSpacing = value.toDouble(); } else if (identifier.toLower()=="wordspacing") { wordSpacing = value.toDouble(); } else if (identifier.toLower()=="linespacingfactor") { lineSpacingFactor = value.toDouble(); } else if (identifier.toLower()=="author") { authors.append(value); } else if (identifier.toLower()=="name") { names.append(value); } else if (identifier.toLower()=="license") { fileLicense = value; } else if (identifier.toLower()=="encoding") { ts.setCodec(QTextCodec::codecForName(value.toLatin1())); encoding = value; } } // Add another letter to this font: else if (line.at(0)=='[') { // uniode character: QChar ch; // read unicode: QRegExp regexp("[0-9A-Fa-f]{4,4}"); regexp.indexIn(line); QString cap = regexp.cap(); if (!cap.isNull()) { int uCode = cap.toInt(NULL, 16); ch = QChar(uCode); } // only unicode allowed else { continue; } // create new letter: RS_FontChar* letter = new RS_FontChar(NULL, ch, RS_Vector(0.0, 0.0)); // Read entities of this letter: QStringList vertex; QStringList coords; do { line = ts.readLine(); if (line.isEmpty()) { continue; } // Defined char: if (line.at(0)=='C') { line.remove(0,1); int uCode = line.toInt(NULL, 16); QChar ch = QChar(uCode); RS_Block* bk = letterList.find(ch); if (bk != NULL) { RS_Entity* bk2 = bk->clone(); bk2->setPen(RS_Pen(RS2::FlagInvalid)); bk2->setLayer(NULL); letter->addEntity(bk2); } } //sequence: else { vertex = line.split(';', QString::SkipEmptyParts); //at least is required two vertex if (vertex.size()<2) continue; RS_Polyline* pline = new RS_Polyline(letter, RS_PolylineData()); pline->setPen(RS_Pen(RS2::FlagInvalid)); pline->setLayer(NULL); for (int i = 0; i < vertex.size(); ++i) { double x1, y1; double bulge = 0; coords = vertex.at(i).split(',', QString::SkipEmptyParts); //at least X,Y is required if (coords.size()<2) continue; x1 = coords.at(0).toDouble(); y1 = coords.at(1).toDouble(); //check presence of bulge if (coords.size() == 3 && coords.at(2).at(0) == QChar('A')){ QString bulgeStr = coords.at(2); bulge = bulgeStr.remove(0,1).toDouble(); pline->setNextBulge(bulge); } pline->addVertex(RS_Vector(x1, y1), bulge); } letter->addEntity(pline); } } while (!line.isEmpty()); letter->calculateBorders(); letterList.add(letter); } } f.close(); }