00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
00227
00228
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