~ubuntu-branches/ubuntu/precise/fritzing/precise

« back to all changes in this revision

Viewing changes to src/fsvgrenderer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Georges Khaznadar
  • Date: 2011-08-26 10:11:05 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110826101105-w5hmn7zcf93ig5v6
Tags: 0.6.3b-1
* upgrapded to the newer upstream version
* parameters of the function GraphicsUtils::distanceFromLine in 
  src/svg/groundplanegenerator.cpp:767 are now declared as doubles,
  which Closes: #636441
* the new version fixes src/utils/folderutils.cpp, which
  Closes: #636061

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
********************************************************************
20
20
 
21
 
$Revision: 5206 $:
 
21
$Revision: 5308 $:
22
22
$Author: cohen@irascible.com $:
23
 
$Date: 2011-07-08 23:59:08 +0200 (Fri, 08 Jul 2011) $
 
23
$Date: 2011-07-30 21:09:56 +0200 (Sat, 30 Jul 2011) $
24
24
 
25
25
********************************************************************/
26
26
 
42
42
QHash<QString, RendererHash * > FSvgRenderer::m_filenameRendererHash;
43
43
QSet<RendererHash * > FSvgRenderer::m_deleted;
44
44
 
45
 
qreal FSvgRenderer::m_printerScale = 90.0;
 
45
double FSvgRenderer::m_printerScale = 90.0;
46
46
 
47
47
static ConnectorInfo VanillaConnectorInfo;
48
48
 
83
83
        m_deleted.clear();
84
84
}
85
85
 
86
 
bool FSvgRenderer::loadSvg(const QString & filename) {
 
86
QByteArray FSvgRenderer::loadSvg(const QString & filename) {
87
87
        QStringList strings;
88
88
        QString string;
89
 
        return loadSvg(filename, strings, strings, string, string, false);
 
89
        return loadSvg(filename, strings, strings, strings, string, string, false);
90
90
}
91
91
 
92
 
bool FSvgRenderer::loadSvg(const QString & filename, const QStringList & connectorIDs, const QStringList & terminalIDs, const QString & setColor, const QString & colorElementID, bool findNonConnectors) {
 
92
QByteArray FSvgRenderer::loadSvg(const QString & filename, const QStringList & connectorIDs, const QStringList & terminalIDs, const QStringList & legIDs, const QString & setColor, const QString & colorElementID, bool findNonConnectors) {
93
93
        if (!QFileInfo(filename).exists() || !QFileInfo(filename).isFile()) {
94
 
                return false;
 
94
                return QByteArray();
95
95
        }
96
96
 
97
97
    QFile file(filename);
98
98
    if (!file.open(QFile::ReadOnly | QFile::Text)) {
99
 
                return false;
 
99
                return QByteArray();
100
100
        }
101
101
 
102
102
        QByteArray contents = file.readAll();
103
103
        file.close();
104
104
 
105
 
        if (contents.length() <= 0) return false;
 
105
        if (contents.length() <= 0) return QByteArray();
106
106
 
107
 
        return loadAux(contents, filename, connectorIDs, terminalIDs, setColor, colorElementID, findNonConnectors);
 
107
        return loadAux(contents, filename, connectorIDs, terminalIDs, legIDs, setColor, colorElementID, findNonConnectors);
108
108
 
109
109
        /*
110
110
 
126
126
 
127
127
}
128
128
 
129
 
bool FSvgRenderer::loadSvg(const QByteArray & contents, const QString & filename) {
 
129
QByteArray FSvgRenderer::loadSvg(const QByteArray & contents, const QString & filename) {
130
130
        QStringList strings;
131
131
        QString string;
132
 
        return loadSvg(contents, filename, strings, strings, string, string, false);
133
 
}
134
 
 
135
 
bool FSvgRenderer::loadSvg(const QByteArray & contents, const QString & filename, const QStringList & connectorIDs, const QStringList & terminalIDs, const QString & setColor, const QString & colorElementID, bool findNonConnectors) {
136
 
        return loadAux(contents, filename, connectorIDs, terminalIDs, setColor, colorElementID, findNonConnectors);
137
 
}
138
 
 
139
 
bool FSvgRenderer::loadAux(const QByteArray & contents, const QString & filename, const QStringList & connectorIDs, const QStringList & terminalIDs, const QString & setColor, const QString & colorElementID, bool findNonConnectors) {
 
132
        return loadSvg(contents, filename, strings, strings, strings, string, string, false);
 
133
}
 
134
 
 
135
QByteArray FSvgRenderer::loadSvg(const QByteArray & contents, const QString & filename, const QStringList & connectorIDs, const QStringList & terminalIDs, const QStringList & legIDs, const QString & setColor, const QString & colorElementID, bool findNonConnectors) {
 
136
        return loadAux(contents, filename, connectorIDs, terminalIDs, legIDs, setColor, colorElementID, findNonConnectors);
 
137
}
 
138
 
 
139
QByteArray FSvgRenderer::loadAux(const QByteArray & contents, const QString & filename, const QStringList & connectorIDs, const QStringList & terminalIDs, const QStringList & legIDs, const QString & setColor, const QString & colorElementID, bool findNonConnectors) {
140
140
 
141
141
        QByteArray cleanContents;
142
142
        bool cleaned = false;
183
183
                        DebugDialog::debug(QString("renderer loadAux failed %1 %2 %3 %4").arg(filename).arg(errorStr).arg(errorLine).arg(errorColumn));
184
184
                }
185
185
 
 
186
                bool resetContents = false;
 
187
 
186
188
                QDomElement root = doc.documentElement();
187
189
                if (!setColor.isEmpty()) {
188
190
                        QDomElement element = TextUtils::findElementWithAttribute(root, "id", colorElementID);
190
192
                                QStringList exceptions;
191
193
                                exceptions << "black" << "#000000";
192
194
                                SvgFileSplitter::fixColorRecurse(element, setColor, exceptions);
193
 
                                cleanContents = TextUtils::removeXMLEntities(doc.toString()).toUtf8();
 
195
                                resetContents = true;
194
196
                        }
195
197
                }
196
198
                if (connectorIDs.count() > 0) {
197
 
                        initConnectorInfo(doc, connectorIDs, terminalIDs);
 
199
                        resetContents = resetContents || initConnectorInfo(doc, connectorIDs, terminalIDs, legIDs);
198
200
                }
199
201
                if (findNonConnectors) {
200
202
                        initNonConnectorInfo(doc);
201
203
                }
 
204
 
 
205
                if (resetContents) {
 
206
                        cleanContents = TextUtils::removeXMLEntities(doc.toString()).toUtf8();
 
207
                }
202
208
        }
203
209
 
204
210
 
234
240
        bool result = QSvgRenderer::load(cleanContents);
235
241
        if (result) {
236
242
                m_filename = filename;
 
243
                return cleanContents;
237
244
        }
238
 
        return result;
 
245
 
 
246
        return QByteArray();
239
247
}
240
248
 
241
249
bool FSvgRenderer::fastLoad(const QByteArray & contents) {
271
279
                QPainter painter(pixmap);
272
280
                // preserve aspect ratio
273
281
                QSizeF def = renderer->defaultSizeF();
274
 
                qreal newW = size.width();
275
 
                qreal newH = newW * def.height() / def.width();
 
282
                double newW = size.width();
 
283
                double newH = newW * def.height() / def.width();
276
284
                if (newH > size.height()) {
277
285
                        newH = size.height();
278
286
                        newW = newH * def.width() / def.height();
323
331
                                QString ws = xml.attributes().value("width").toString();
324
332
                                QString hs = xml.attributes().value("height").toString();
325
333
                                bool ok;
326
 
                                qreal w = TextUtils::convertToInches(ws, &ok, isIllustrator);
 
334
                                double w = TextUtils::convertToInches(ws, &ok, isIllustrator);
327
335
                                if (!ok) return size;
328
336
 
329
 
                                qreal h = TextUtils::convertToInches(hs, &ok, isIllustrator);
 
337
                                double h = TextUtils::convertToInches(hs, &ok, isIllustrator);
330
338
                                if (!ok) return size;
331
339
 
332
340
                                size.setWidth(w);
372
380
        QSizeF size = parseForWidthAndHeight(xml);
373
381
        if (size.width() <= 0) return;
374
382
 
375
 
        qreal pscale = b.width() / size.width();
 
383
        double pscale = b.width() / size.width();
376
384
        DebugDialog::debug(QString("printerscale %1").arg(pscale));
377
385
 
378
386
        */
379
387
}
380
388
 
381
 
qreal FSvgRenderer::printerScale() {
 
389
double FSvgRenderer::printerScale() {
382
390
        return m_printerScale;
383
391
}
384
392
 
403
411
        }
404
412
}
405
413
 
406
 
void FSvgRenderer::initConnectorInfo(QDomDocument & domDocument, const QStringList & connectorIDs, const QStringList & terminalIDs)
 
414
bool FSvgRenderer::initConnectorInfo(QDomDocument & domDocument, const QStringList & connectorIDs, const QStringList & terminalIDs, const QStringList & legIDs)
407
415
{
 
416
        bool result = false;
408
417
        clearConnectorInfoHash(m_connectorInfoHash);
409
418
        QDomElement root = domDocument.documentElement();
410
419
        initConnectorInfoAux(root, connectorIDs);
411
420
        if (terminalIDs.count() > 0) {
412
421
                initTerminalInfoAux(root, connectorIDs, terminalIDs);
413
422
        }
 
423
        if (legIDs.count() > 0) {
 
424
                initLegInfoAux(root, connectorIDs, legIDs, result);
 
425
        }
 
426
 
 
427
        return result;
 
428
}
 
429
 
 
430
void FSvgRenderer::initLegInfoAux(QDomElement & element, const QStringList & connectorIDs, const QStringList & legIDs, bool & gotOne)
 
431
{
 
432
        QString id = element.attribute("id");
 
433
        if (!id.isEmpty()) {
 
434
                int ix = legIDs.indexOf(id);
 
435
                if (ix >= 0) {
 
436
                        element.setTagName("g");                        // don't want this element to actually be drawn
 
437
                        gotOne = true;
 
438
                        ConnectorInfo * connectorInfo = m_connectorInfoHash.value(connectorIDs.at(ix), NULL);
 
439
                        if (connectorInfo) {
 
440
                                connectorInfo->legMatrix = TextUtils::elementToMatrix(element);
 
441
                                connectorInfo->legColor = element.attribute("stroke");
 
442
                                connectorInfo->legLine = QLineF();
 
443
                                connectorInfo->legStrokeWidth = 0;
 
444
                                initLegInfoAux(element, connectorInfo);
 
445
                        }
 
446
                        // don't return here, might miss other legs
 
447
                }
 
448
        }
 
449
 
 
450
        QDomElement child = element.firstChildElement();
 
451
        while (!child.isNull()) {
 
452
                initLegInfoAux(child, connectorIDs, legIDs, gotOne);
 
453
                child = child.nextSiblingElement();
 
454
        }
 
455
}
 
456
 
 
457
bool FSvgRenderer::initLegInfoAux(QDomElement & element, ConnectorInfo * connectorInfo) 
 
458
{
 
459
        bool ok;
 
460
        double sw = element.attribute("stroke-width").toDouble(&ok);
 
461
        if (!ok) return false;
 
462
 
 
463
        double x1 = element.attribute("x1").toDouble(&ok);
 
464
        if (!ok) return false;
 
465
 
 
466
        double y1 = element.attribute("y1").toDouble(&ok);
 
467
        if (!ok) return false;
 
468
 
 
469
        double x2 = element.attribute("x2").toDouble(&ok);
 
470
        if (!ok) return false;
 
471
 
 
472
        double y2 = element.attribute("y2").toDouble(&ok);
 
473
        if (!ok) return false;
 
474
 
 
475
        connectorInfo->legStrokeWidth = sw;
 
476
        connectorInfo->legLine = QLineF(x1, y1, x2, y2);
 
477
        return true;
414
478
}
415
479
 
416
480
void FSvgRenderer::initTerminalInfoAux(QDomElement & element, const QStringList & connectorIDs, const QStringList & terminalIDs)
417
481
{
418
482
        QString id = element.attribute("id");
419
 
        int ix = terminalIDs.indexOf(id);
420
 
        if (ix >= 0) {
421
 
                ConnectorInfo * connectorInfo = m_connectorInfoHash.value(connectorIDs.at(ix), NULL);
422
 
                if (connectorInfo) {
423
 
                        connectorInfo->terminalMatrix = TextUtils::elementToMatrix(element);
 
483
        if (!id.isEmpty()) {
 
484
                int ix = terminalIDs.indexOf(id);
 
485
                if (ix >= 0) {
 
486
                        ConnectorInfo * connectorInfo = m_connectorInfoHash.value(connectorIDs.at(ix), NULL);
 
487
                        if (connectorInfo) {
 
488
                                connectorInfo->terminalMatrix = TextUtils::elementToMatrix(element);
 
489
                        }
 
490
                        // don't return here, might miss other terminal ids
424
491
                }
425
492
        }
 
493
 
426
494
        QDomElement child = element.firstChildElement();
427
495
        while (!child.isNull()) {
428
496
                initTerminalInfoAux(child, connectorIDs, terminalIDs);
433
501
void FSvgRenderer::initConnectorInfoAux(QDomElement & element, const QStringList & connectorIDs)
434
502
{
435
503
        QString id = element.attribute("id");
436
 
        if (connectorIDs.contains(id)) {
437
 
                ConnectorInfo * connectorInfo = initConnectorInfo(element);
438
 
                m_connectorInfoHash.insert(id, connectorInfo);
 
504
        if (!id.isEmpty()) {
 
505
                if (connectorIDs.contains(id)) {
 
506
                        ConnectorInfo * connectorInfo = initConnectorInfo(element);
 
507
                        m_connectorInfoHash.insert(id, connectorInfo);
 
508
                }
 
509
                // don't return here, might miss other connectors
439
510
        }
 
511
 
440
512
        QDomElement child = element.firstChildElement();
441
513
        while (!child.isNull()) {
442
514
                initConnectorInfoAux(child, connectorIDs);
474
546
        }
475
547
 
476
548
        bool ok;
477
 
        qreal cx = connectorElement.attribute("cx").toDouble(&ok);
478
 
        if (!ok) return false;
479
 
 
480
 
        qreal cy = connectorElement.attribute("cy").toDouble(&ok);
481
 
        if (!ok) return false;
482
 
 
483
 
        qreal r = connectorElement.attribute("r").toDouble(&ok);
484
 
        if (!ok) return false;
485
 
 
486
 
        qreal sw = connectorElement.attribute("stroke-width").toDouble(&ok);    
 
549
        double cx = connectorElement.attribute("cx").toDouble(&ok);
 
550
        if (!ok) return false;
 
551
 
 
552
        double cy = connectorElement.attribute("cy").toDouble(&ok);
 
553
        if (!ok) return false;
 
554
 
 
555
        double r = connectorElement.attribute("r").toDouble(&ok);
 
556
        if (!ok) return false;
 
557
 
 
558
        double sw = connectorElement.attribute("stroke-width").toDouble(&ok);   
487
559
        if (!ok) {
488
560
                //QString strokewidth("stroke-width");
489
561
                //QString s = element.attribute("style");
490
562
                //SvgFileSplitter::fixStyleAttribute(connectorElement, s, strokewidth);
491
 
                sw = connectorElement.attribute("stroke-width").toDouble(&ok);
492
 
                if (!ok) {
 
563
                //sw = connectorElement.attribute("stroke-width").toDouble(&ok);
 
564
                //if (!ok) {
493
565
                        return false;
494
 
                }
 
566
                //}
495
567
        }
496
568
 
497
569
        connectorInfo->gotCircle = true;
524
596
 
525
597
        if (svgIdLayer->m_processed) {
526
598
                // hybrids are not visible in some views
527
 
                return svgIdLayer->m_visible || svgIdLayer->m_hybrid;
 
599
                return svgIdLayer->m_svgVisible || svgIdLayer->m_hybrid;
528
600
        }
529
601
 
530
602
        svgIdLayer->m_processed = true;
533
605
 
534
606
        QRectF bounds = this->boundsOnElement(connectorID);     
535
607
        if (bounds.isNull() && !svgIdLayer->m_hybrid) {         // hybrids can have zero size
536
 
                svgIdLayer->m_visible = false;          
 
608
                svgIdLayer->m_svgVisible = false;               
537
609
                DebugDialog::debug("renderer::setupconnector: null bounds");
538
610
                return false;
539
611
        }
540
612
 
541
613
        QSizeF defaultSizeF = this->defaultSizeF();
542
 
        QSize defaultSize = this->defaultSize();
543
614
        QRectF viewBox = this->viewBoxF();
544
615
 
545
616
        ConnectorInfo * connectorInfo = getConnectorInfo(connectorID);          
574
645
                                                           r1.width() * defaultSizeF.width() / viewBox.width(), 
575
646
                                                           r1.height() * defaultSizeF.height() / viewBox.height());
576
647
 
577
 
        svgIdLayer->m_visible = !bounds.isNull();
578
 
        svgIdLayer->m_point = calcTerminalPoint(svgIdLayer->m_terminalId, svgIdLayer->m_rect, ignoreTerminalPoint, viewBox, connectorInfo->terminalMatrix, true);
 
648
        svgIdLayer->m_svgVisible = !bounds.isNull();
 
649
        //if (!svgIdLayer->m_svgVisible) {
 
650
                //DebugDialog::debug("not vis");
 
651
        //}
 
652
        svgIdLayer->m_point = calcTerminalPoint(svgIdLayer->m_terminalId, svgIdLayer->m_rect, ignoreTerminalPoint, viewBox, connectorInfo->terminalMatrix);
 
653
        calcLeg(svgIdLayer, viewBox, connectorInfo);
579
654
        
580
 
 
581
 
        /*
582
 
        svgIdLayer->m_point = calcTerminalPoint(svgIdLayer->m_terminalId, svgIdLayer->m_rect, ignoreTerminalPoint, viewBox, connectorInfo->terminalMatrix, false);
583
 
        if (calcWeirdOffset) {  
584
 
                QRectF trueRect(r1.x() * defaultSizeF.width() / viewBox.width(), 
585
 
                                                r1.y() * defaultSizeF.height() / viewBox.height(), 
586
 
                                                r1.width() * defaultSizeF.width() / viewBox.width(), 
587
 
                                                r1.height() * defaultSizeF.height() / viewBox.height());
588
 
                QMatrix m;
589
 
                QPointF truePoint = calcTerminalPoint(svgIdLayer->m_terminalId, trueRect, ignoreTerminalPoint, viewBox, m, true);
590
 
                svgIdLayer->m_weirdOffset = truePoint - svgIdLayer->m_point;
591
 
                if (truePoint != svgIdLayer->m_point) {
592
 
                        DebugDialog::debug("difference ");
593
 
                }
594
 
        }
595
 
        */
596
 
 
597
655
        return true;
598
656
}
599
657
 
600
 
QPointF FSvgRenderer::calcTerminalPoint(const QString & terminalId, const QRectF & connectorRect, bool ignoreTerminalPoint, const QRectF & viewBox, QMatrix & terminalMatrix, bool useF)
 
658
void FSvgRenderer::calcLeg(SvgIdLayer * svgIdLayer, const QRectF & viewBox, ConnectorInfo * connectorInfo)
 
659
{
 
660
        if (svgIdLayer->m_legId.isEmpty()) return;
 
661
 
 
662
        svgIdLayer->m_legColor = connectorInfo->legColor;
 
663
 
 
664
        QSizeF defaultSizeF = this->defaultSizeF();
 
665
        svgIdLayer->m_legStrokeWidth = connectorInfo->legStrokeWidth * defaultSizeF.width() / viewBox.width();
 
666
 
 
667
        QMatrix matrix = this->matrixForElement(svgIdLayer->m_legId) * connectorInfo->legMatrix;
 
668
        QPointF p1 = matrix.map(connectorInfo->legLine.p1());
 
669
        QPointF p2 = matrix.map(connectorInfo->legLine.p2());
 
670
 
 
671
        double x1 = p1.x() * defaultSizeF.width() / viewBox.width();
 
672
        double y1 = p1.y() * defaultSizeF.height() / viewBox.height();
 
673
        double x2 = p2.x() * defaultSizeF.width() / viewBox.width();
 
674
        double y2 = p2.y() * defaultSizeF.height() / viewBox.height();
 
675
        QPointF center = viewBox.center();
 
676
        double d1 = ((x1 - center.x()) * (x1 - center.x())) + ((y1 - center.y()) * (y1 - center.y()));
 
677
        double d2 = ((x2 - center.x()) * (x2 - center.x())) + ((y2 - center.y()) * (y1 - center.y()));
 
678
 
 
679
        // find the end which is closer to the center of the viewBox (which shouldn't include the leg)
 
680
        if (d1 <= d2) {
 
681
                svgIdLayer->m_legLine = QLineF(x1, y1, x2, y2);
 
682
        }
 
683
        else {
 
684
                svgIdLayer->m_legLine = QLineF(x2, y2, x1, y1);
 
685
        }
 
686
}
 
687
 
 
688
QPointF FSvgRenderer::calcTerminalPoint(const QString & terminalId, const QRectF & connectorRect, bool ignoreTerminalPoint, const QRectF & viewBox, QMatrix & terminalMatrix)
601
689
{
602
690
        QPointF terminalPoint = connectorRect.center() - connectorRect.topLeft();    // default spot is centered
603
691
        if (ignoreTerminalPoint) {
613
701
        }
614
702
 
615
703
        QSizeF defaultSizeF = this->defaultSizeF();
616
 
        QSize defaultSize = this->defaultSize();
617
704
        if (tBounds.width() >= defaultSizeF.width() && tBounds.height() >= defaultSizeF.height()) {
618
705
                return terminalPoint;
619
706
        }
629
716
        QMatrix tMatrix = this->matrixForElement(terminalId) * terminalMatrix;
630
717
        QRectF terminalRect = tMatrix.mapRect(tBounds);
631
718
        QPointF c = terminalRect.center();
632
 
        QPointF q = useF 
633
 
                                ? QPointF(c.x() * defaultSizeF.width() / viewBox.width(), c.y() * defaultSizeF.height() / viewBox.height())
634
 
                                : QPointF(c.x() * defaultSize.width() / viewBox.width(), c.y() * defaultSize.height() / viewBox.height());
 
719
        QPointF q(c.x() * defaultSizeF.width() / viewBox.width(), c.y() * defaultSizeF.height() / viewBox.height());
635
720
        terminalPoint = q - connectorRect.topLeft();
636
721
        //DebugDialog::debug(   QString("terminalagain %3 rect %1,%2 ").arg(terminalPoint.x()).
637
722
                                                                                //arg(terminalPoint.y()).
678
763
                QRectF r1 = matrix0.mapRect(bounds);
679
764
                svgIdLayer->m_rect.setRect(r1.x() * defaultSize.width() / viewBox.width(), r1.y() * defaultSize.height() / viewBox.height(), r1.width() * defaultSize.width() / viewBox.width(), r1.height() * defaultSize.height() / viewBox.height());
680
765
                svgIdLayer->m_point = svgIdLayer->m_rect.center() - svgIdLayer->m_rect.topLeft();
681
 
                svgIdLayer->m_visible = true;
 
766
                svgIdLayer->m_svgVisible = true;
682
767
 
683
768
                list.append(svgIdLayer);
684
769
        }