src/svg/qsvggraphics.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the QtSVG module of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "qsvggraphics_p.h"
00025 #include "qsvgfont_p.h"
00026 
00027 #include "qpainter.h"
00028 #include "qtextdocument.h"
00029 #include "qabstracttextdocumentlayout.h"
00030 #include "qtextcursor.h"
00031 #include "qdebug.h"
00032 
00033 #include <math.h>
00034 #include <limits.h>
00035 
00036 void QSvgAnimation::draw(QPainter *)
00037 {
00038     qWarning("<animation> no implemented");
00039 }
00040 
00041 
00042 QSvgCircle::QSvgCircle(QSvgNode *parent, const QRectF &rect)
00043     : QSvgNode(parent), m_bounds(rect)
00044 {
00045 }
00046 
00047 
00048 QRectF QSvgCircle::bounds() const
00049 {
00050     return m_bounds;
00051 }
00052 
00053 void QSvgCircle::draw(QPainter *p)
00054 {
00055     applyStyle(p);
00056     p->drawEllipse(m_bounds);
00057     revertStyle(p);
00058 }
00059 
00060 QSvgArc::QSvgArc(QSvgNode *parent, const QPainterPath &path)
00061     : QSvgNode(parent), cubic(path)
00062 {
00063     m_cachedBounds = path.boundingRect();
00064 }
00065 
00066 void QSvgArc::draw(QPainter *p)
00067 {
00068     applyStyle(p);
00069     p->drawPath(cubic);
00070     revertStyle(p);
00071 }
00072 
00073 QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect)
00074     : QSvgNode(parent), m_bounds(rect)
00075 {
00076 }
00077 
00078 QRectF QSvgEllipse::bounds() const
00079 {
00080     return m_bounds;
00081 }
00082 
00083 void QSvgEllipse::draw(QPainter *p)
00084 {
00085     applyStyle(p);
00086     p->drawEllipse(m_bounds);
00087     revertStyle(p);
00088 }
00089 
00090 QSvgImage::QSvgImage(QSvgNode *parent, const QImage &image,
00091                      const QRect &bounds)
00092     : QSvgNode(parent), m_image(image),
00093       m_bounds(bounds)
00094 {
00095     if (m_bounds.width() == 0)
00096         m_bounds.setWidth(m_image.width());
00097     if (m_bounds.height() == 0)
00098         m_bounds.setHeight(m_image.height());
00099 }
00100 
00101 void QSvgImage::draw(QPainter *p)
00102 {
00103     applyStyle(p);
00104     p->drawImage(m_bounds, m_image);
00105     revertStyle(p);
00106 }
00107 
00108 
00109 QSvgLine::QSvgLine(QSvgNode *parent, const QLineF &line)
00110     : QSvgNode(parent), m_bounds(line)
00111 {
00112 }
00113 
00114 
00115 void QSvgLine::draw(QPainter *p)
00116 {
00117     applyStyle(p);
00118     p->drawLine(m_bounds);
00119     revertStyle(p);
00120 }
00121 
00122 QSvgPath::QSvgPath(QSvgNode *parent, const QPainterPath &qpath)
00123     : QSvgNode(parent), m_path(qpath)
00124 {
00125     //m_cachedBounds = m_path.controlPointRect();
00126     m_cachedBounds = m_path.boundingRect();
00127 }
00128 
00129 void QSvgPath::draw(QPainter *p)
00130 {
00131     applyStyle(p);
00132     p->drawPath(m_path);
00133     revertStyle(p);
00134 }
00135 
00136 QRectF QSvgPath::bounds() const
00137 {
00138     return m_cachedBounds;
00139 }
00140 
00141 QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly)
00142     : QSvgNode(parent), m_poly(poly)
00143 {
00144 
00145 }
00146 
00147 QRectF QSvgPolygon::bounds() const
00148 {
00149     return m_poly.boundingRect();
00150 }
00151 
00152 void QSvgPolygon::draw(QPainter *p)
00153 {
00154     applyStyle(p);
00155     p->drawPolygon(m_poly);
00156     revertStyle(p);
00157 }
00158 
00159 
00160 QSvgPolyline::QSvgPolyline(QSvgNode *parent, const QPolygonF &poly)
00161     : QSvgNode(parent), m_poly(poly)
00162 {
00163 
00164 }
00165 
00166 void QSvgPolyline::draw(QPainter *p)
00167 {
00168     applyStyle(p);
00169     if (p->brush().style() != Qt::NoBrush) {
00170         QPen save = p->pen();
00171         p->setPen(QPen(Qt::NoPen));
00172         p->drawPolygon(m_poly);
00173         p->setPen(save);
00174     }
00175     p->drawPolyline(m_poly);
00176     revertStyle(p);
00177 }
00178 
00179 QSvgRect::QSvgRect(QSvgNode *node, const QRectF &rect, int rx, int ry)
00180     : QSvgNode(node),
00181       m_rect(rect), m_rx(rx), m_ry(ry)
00182 {
00183 }
00184 
00185 QRectF QSvgRect::bounds() const
00186 {
00187     return m_rect;
00188 }
00189 
00190 void QSvgRect::draw(QPainter *p)
00191 {
00192     applyStyle(p);
00193     
00194     if (m_rx || m_ry)
00195         p->drawRoundRect(m_rect, m_rx, m_ry);
00196     else
00197         p->drawRect(m_rect);
00198     revertStyle(p);
00199 }
00200 
00201 QSvgText::QSvgText(QSvgNode *parent, const QPointF &coord)
00202     : QSvgNode(parent), m_coord(coord),
00203       m_textAlignment(Qt::AlignLeft)
00204 {
00205 }
00206 
00207 QSvgText::~QSvgText()
00208 {
00209 }
00210 
00211 //QRectF QSvgText::bounds() const {}
00212 
00213 void QSvgText::draw(QPainter *p)
00214 {
00215     applyStyle(p);
00216 
00217     QSvgFontStyle *fontStyle = static_cast<QSvgFontStyle*>(
00218         styleProperty(QSvgStyleProperty::FONT));
00219     if (fontStyle && fontStyle->svgFont()) {
00220         fontStyle->svgFont()->draw(p, m_coord, m_text, fontStyle->pointSize());
00221         revertStyle(p);
00222         return;
00223     }
00224 
00225     QTextLayout tl(m_text);
00226     //QTextOption op = tl.textOption();
00227     //op.setAlignment(m_textAlignment);
00228     //tl.setTextOption(op);
00229     tl.setAdditionalFormats(m_formatRanges);
00230     tl.beginLayout();
00231     qreal y = 0;
00232     bool initial = true;
00233     qreal px = m_coord.x();
00234     qreal py = m_coord.y();
00235 
00236     forever {
00237         QTextLine line = tl.createLine();
00238         if (!line.isValid())
00239             break;
00240     }
00241     for (int i = 0; i < tl.lineCount(); ++i) {
00242         QTextLine line = tl.lineAt(i);
00243 
00244         line.setPosition(QPointF(0, y-line.ascent()));
00245         y += line.height();
00246 
00247         if (initial) {
00248             qreal w = line.naturalTextWidth();
00249             px = m_coord.x();
00250             py = m_coord.y();
00251             if (m_textAlignment == Qt::AlignHCenter) {
00252                 px = m_coord.x() - w / 2;
00253             }
00254             else if (m_textAlignment == Qt::AlignRight) {
00255                 px = m_coord.x() - w;
00256             }
00257             initial = false;
00258         }
00259     }
00260     tl.endLayout();
00261     tl.draw(p, QPointF(px, py));
00262 
00263     revertStyle(p);
00264 }
00265 
00266 void QSvgText::insertText(const QString &text)
00267 {
00268     if (!m_formats.isEmpty()) {
00269         QTextLayout::FormatRange range;
00270         range.start = m_text.length();
00271         range.length = text.length();
00272         range.format = m_formats.top();
00273         m_formatRanges.append(range);
00274     }
00275 
00276     m_text += text;
00277 }
00278 
00279 void QSvgText::insertFormat(const QTextCharFormat &format)
00280 {
00281     QTextCharFormat mergedFormat = format;
00282     if (!m_formats.isEmpty()) {
00283         mergedFormat = m_formats.top();
00284         mergedFormat.merge(format);
00285     }
00286 
00287     m_formats.push(mergedFormat);
00288 }
00289 
00290 void QSvgText::popFormat()
00291 {
00292     if (m_formats.count() > 1)
00293         m_formats.pop();
00294 }
00295 
00296 const QTextCharFormat &QSvgText::topFormat() const
00297 {
00298     return m_formats.top();
00299 }
00300 
00301 void QSvgText::setTextAlignment(const Qt::Alignment &alignment)
00302 {
00303     m_textAlignment = alignment;
00304 }
00305 
00306 void QSvgTextArea::draw(QPainter *p)
00307 {
00308     applyStyle(p);
00309 
00310     revertStyle(p);
00311 }
00312 
00313 QSvgUse::QSvgUse(const QPointF &start, QSvgNode *parent, QSvgNode *node)
00314     : QSvgNode(parent), m_link(node), m_start(start)
00315 {
00316 
00317 }
00318 
00319 void QSvgUse::draw(QPainter *p)
00320 {
00321     applyStyle(p);
00322 
00323     if (!m_start.isNull()) {
00324         p->translate(m_start);
00325     }   
00326     m_link->draw(p);
00327     if (!m_start.isNull()) {
00328         p->translate(-m_start);
00329     }
00330     
00331     revertStyle(p);
00332 }
00333 
00334 void QSvgVideo::draw(QPainter *p)
00335 {
00336     applyStyle(p);
00337 
00338     revertStyle(p);
00339 }
00340 
00341 QSvgNode::Type QSvgAnimation::type() const
00342 {
00343     return ANIMATION;
00344 }
00345 
00346 QSvgNode::Type QSvgArc::type() const
00347 {
00348     return ARC;
00349 }
00350 
00351 QSvgNode::Type QSvgCircle::type() const
00352 {
00353     return CIRCLE;
00354 }
00355 
00356 QSvgNode::Type QSvgEllipse::type() const
00357 {
00358     return ELLIPSE;
00359 }
00360 
00361 QSvgNode::Type QSvgImage::type() const
00362 {
00363     return IMAGE;
00364 }
00365 
00366 QSvgNode::Type QSvgLine::type() const
00367 {
00368     return LINE;
00369 }
00370 
00371 QSvgNode::Type QSvgPath::type() const
00372 {
00373     return PATH;
00374 }
00375 
00376 QSvgNode::Type QSvgPolygon::type() const
00377 {
00378     return POLYGON;
00379 }
00380 
00381 QSvgNode::Type QSvgPolyline::type() const
00382 {
00383     return POLYLINE;
00384 }
00385 
00386 QSvgNode::Type QSvgRect::type() const
00387 {
00388     return RECT;
00389 }
00390 
00391 QSvgNode::Type QSvgText::type() const
00392 {
00393     return TEXT;
00394 }
00395 
00396 QSvgNode::Type QSvgTextArea::type() const
00397 {
00398     return TEXTAREA;
00399 }
00400 
00401 QSvgNode::Type QSvgUse::type() const
00402 {
00403     return USE;
00404 }
00405 
00406 QSvgNode::Type QSvgVideo::type() const
00407 {
00408     return VIDEO;
00409 }
00410 
00411 QRectF QSvgUse::bounds() const
00412 {
00413     if (m_link && m_bounds.isEmpty())  {
00414         m_bounds = m_link->bounds();
00415         m_bounds = QRectF(m_bounds.x()+m_start.x(),
00416                           m_bounds.y()+m_start.y(),
00417                           m_bounds.width(),
00418                           m_bounds.height());
00419         
00420         return m_bounds;
00421     }
00422     return m_bounds;
00423 }
00424 
00425 QRectF QSvgUse::transformedBounds(const QMatrix &mat) const
00426 {
00427     QRectF bounds;
00428     QMatrix m = mat;
00429     
00430     if (m_link)  {       
00431         QSvgTransformStyle *trans = m_style.transform;
00432         if (trans) {
00433             m = trans->qmatrix() * m;
00434         }
00435         m.translate(m_start.x(), m_start.y());
00436 
00437         bounds = m_link->transformedBounds(m);
00438         
00439         return bounds;
00440     }
00441     return bounds;
00442 }
00443 
00444 QRectF QSvgPolyline::bounds() const
00445 {
00446     return m_poly.boundingRect();
00447 }
00448 
00449 QRectF QSvgArc::bounds() const
00450 {
00451     return m_cachedBounds;
00452 }
00453 
00454 QRectF QSvgImage::bounds() const
00455 {
00456     return m_bounds;
00457 }
00458 
00459 QRectF QSvgLine::bounds() const
00460 {
00461     qreal minX = qMin(m_bounds.x1(), m_bounds.x2());
00462     qreal minY = qMin(m_bounds.y1(), m_bounds.y2());
00463     qreal maxX = qMax(m_bounds.x1(), m_bounds.x2());
00464     qreal maxY = qMax(m_bounds.y1(), m_bounds.y2());
00465     
00466     return QRectF(minX, minY, maxX-minX, maxY-minY);
00467 }
00468 

Generated on Thu Mar 15 12:00:08 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1