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 <math.h>
00025 #include <QtGui>
00026
00027 #include "displayshape.h"
00028
00029 DisplayShape::DisplayShape(const QPointF &position, const QSizeF &maxSize)
00030 : pos(position), maxSize(maxSize), interactive(false)
00031 {
00032 }
00033
00034 bool DisplayShape::animate()
00035 {
00036 if (!targetPos.isNull()) {
00037 QLineF displacement(pos, targetPos);
00038 QPointF newPosition = displacement.pointAt(0.15);
00039 if (displacement.length() <= 1.0) {
00040 pos = targetPos;
00041 targetPos = QPointF();
00042 } else {
00043 pos = newPosition;
00044 }
00045 return true;
00046 }
00047
00048 return false;
00049 }
00050
00051 bool DisplayShape::contains(const QString &key) const
00052 {
00053 return meta.contains(key);
00054 }
00055
00056 bool DisplayShape::isInteractive() const
00057 {
00058 return interactive;
00059 }
00060
00061 QVariant DisplayShape::metaData(const QString &key) const
00062 {
00063 return meta.value(key);
00064 }
00065
00066 void DisplayShape::paint(QPainter *painter) const
00067 {
00068 painter->save();
00069 painter->drawImage(pos, image);
00070 painter->restore();
00071 }
00072
00073 QPointF DisplayShape::position() const
00074 {
00075 return pos;
00076 }
00077
00078 QRectF DisplayShape::rect() const
00079 {
00080 return QRectF(pos, image.size());
00081 }
00082
00083 void DisplayShape::removeMetaData(const QString &key)
00084 {
00085 meta.remove(key);
00086 }
00087
00088 void DisplayShape::setInteractive(bool enable)
00089 {
00090 interactive = enable;
00091 }
00092
00093 void DisplayShape::setMetaData(const QString &key, const QVariant &value)
00094 {
00095 meta[key] = value;
00096 }
00097
00098 void DisplayShape::setPosition(const QPointF &position)
00099 {
00100 pos = position;
00101 }
00102
00103 void DisplayShape::setSize(const QSizeF &size)
00104 {
00105 maxSize = size;
00106 }
00107
00108 void DisplayShape::setTarget(const QPointF &position)
00109 {
00110 targetPos = position;
00111 }
00112
00113 QSizeF DisplayShape::size() const
00114 {
00115 return maxSize;
00116 }
00117
00118 QPointF DisplayShape::target() const
00119 {
00120 return targetPos;
00121 }
00122
00123 PanelShape::PanelShape(const QPainterPath &path, const QBrush &normal,
00124 const QBrush &highlighted, const QPen &pen,
00125 const QPointF &position, const QSizeF &maxSize)
00126 : DisplayShape(position, maxSize), highlightedBrush(highlighted),
00127 normalBrush(normal), path(path), pen(pen)
00128 {
00129 brush = normalBrush;
00130 }
00131
00132 bool PanelShape::animate()
00133 {
00134 bool updated = false;
00135
00136 if (!meta.contains("destroy")) {
00137 if (meta.contains("fade")) {
00138 QColor penColor = pen.color();
00139 QColor brushColor = brush.color();
00140 int penAlpha = penColor.alpha();
00141 int brushAlpha = brushColor.alpha();
00142 int fadeMinimum = meta.value("fade minimum").toInt();
00143
00144 if (penAlpha != fadeMinimum || brushAlpha != fadeMinimum
00145 || meta.value("fade").toInt() > 0) {
00146
00147 penAlpha = qBound(fadeMinimum,
00148 penAlpha + meta.value("fade").toInt(), 255);
00149 brushAlpha = qBound(fadeMinimum,
00150 brushAlpha + meta.value("fade").toInt(), 255);
00151
00152 penColor.setAlpha(penAlpha);
00153 brushColor.setAlpha(brushAlpha);
00154 pen.setColor(penColor);
00155 brush.setColor(brushColor);
00156
00157 if (penAlpha == 0 && brushAlpha == 0) {
00158 meta["destroy"] = true;
00159 meta.remove("fade");
00160 } else if (penAlpha == 255 && brushAlpha == 255)
00161 meta.remove("fade");
00162
00163 updated = true;
00164 }
00165 } else if (meta.contains("highlight")) {
00166 qreal scale = meta.value("highlight scale").toDouble();
00167 QColor color = brush.color();
00168
00169 if (meta.value("highlight").toBool())
00170 scale = qBound(0.0, scale + 0.5, 1.0);
00171 else
00172 scale = qBound(0.0, scale - 0.2, 1.0);
00173
00174 if (scale == 0.0) {
00175 brush = normalBrush;
00176 meta.remove("highlight");
00177 meta.remove("highlight scale");
00178 updated = true;
00179 } else if (scale != meta["highlight scale"]) {
00180 meta["highlight scale"] = scale;
00181
00182 if (scale == 1.0)
00183 brush = highlightedBrush;
00184 else {
00185 QColor normal = normalBrush.color();
00186 QColor highlighted = highlightedBrush.color();
00187
00188 color.setRedF((1.0-scale) * normal.redF()
00189 + scale*highlighted.redF());
00190 color.setGreenF((1.0-scale) * normal.greenF()
00191 + scale*highlighted.greenF());
00192 color.setBlueF((1.0-scale) * normal.blueF()
00193 + scale*highlighted.blueF());
00194 brush.setColor(color);
00195 }
00196 updated = true;
00197 }
00198 }
00199 }
00200
00201 return DisplayShape::animate() || updated;
00202 }
00203
00204 void PanelShape::paint(QPainter *painter) const
00205 {
00206 painter->save();
00207 painter->setRenderHint(QPainter::Antialiasing);
00208 painter->setBrush(brush);
00209 painter->setPen(pen);
00210 painter->translate(pos);
00211 painter->drawPath(path);
00212 painter->restore();
00213 }
00214
00215 QRectF PanelShape::rect() const
00216 {
00217 return QRectF(pos + path.boundingRect().topLeft(),
00218 path.boundingRect().size());
00219 }
00220
00221 TitleShape::TitleShape(const QString &text, const QFont &f,
00222 const QPen &pen, const QPointF &position,
00223 const QSizeF &maxSize, Qt::Alignment alignment)
00224 : DisplayShape(position, maxSize), font(f), text(text), pen(pen),
00225 alignment(alignment)
00226 {
00227 QFontMetricsF fm(font);
00228 textRect = fm.boundingRect(QRectF(QPointF(0, 0), maxSize), alignment, text);
00229
00230 qreal textWidth = qMax(fm.width(text), textRect.width());
00231 qreal textHeight = qMax(fm.height(), textRect.height());
00232
00233 qreal scale = qMin(maxSize.width()/textWidth,
00234 maxSize.height()/textHeight);
00235
00236 font.setPointSizeF(font.pointSizeF() * scale);
00237 fm = QFontMetricsF(font);
00238 textRect = fm.boundingRect(QRectF(QPointF(0, 0), maxSize), alignment, text);
00239 baselineStart = QPointF(textRect.left(), textRect.bottom() - fm.descent());
00240 }
00241
00242 bool TitleShape::animate()
00243 {
00244 bool updated = false;
00245
00246 if (!meta.contains("destroy")) {
00247 if (meta.contains("fade")) {
00248 QColor penColor = pen.color();
00249 int penAlpha = penColor.alpha();
00250
00251 penAlpha = qBound(meta.value("fade minimum").toInt(),
00252 penAlpha + meta.value("fade").toInt(), 255);
00253
00254 penColor.setAlpha(penAlpha);
00255 pen.setColor(penColor);
00256
00257 if (penAlpha == 0) {
00258 meta["destroy"] = true;
00259 meta.remove("fade");
00260 } else if (penAlpha == 255)
00261 meta.remove("fade");
00262
00263 updated = true;
00264 }
00265 }
00266
00267 return DisplayShape::animate() || updated;
00268 }
00269
00270 void TitleShape::paint(QPainter *painter) const
00271 {
00272 QRectF rect(textRect);
00273 rect.translate(pos);
00274 painter->save();
00275 painter->setRenderHint(QPainter::TextAntialiasing);
00276 painter->setPen(pen);
00277 painter->setFont(font);
00278 painter->drawText(pos + baselineStart, text);
00279 painter->restore();
00280 }
00281
00282 QRectF TitleShape::rect() const
00283 {
00284 QRectF rect(textRect);
00285 return rect.translated(pos);
00286 }
00287
00288 ImageShape::ImageShape(const QImage &original, const QPointF &position,
00289 const QSizeF &maxSize, int alpha,
00290 Qt::Alignment alignment)
00291 : DisplayShape(position, maxSize), alpha(alpha), alignment(alignment)
00292 {
00293 source = original.convertToFormat(QImage::Format_ARGB32_Premultiplied);
00294 qreal scale = qMin(qMin(maxSize.width()/source.width(),
00295 maxSize.height()/source.height()), qreal(1.0));
00296
00297 source = source.scaled(int(ceil(source.width() * scale)),
00298 int(ceil(source.height() * scale)),
00299 Qt::KeepAspectRatio,
00300 Qt::SmoothTransformation);
00301
00302 image = QImage(source.size(), QImage::Format_ARGB32_Premultiplied);
00303
00304 offset = QPointF(0.0, 0.0);
00305
00306 if (alignment & Qt::AlignHCenter)
00307 offset.setX((maxSize.width() - image.width())/2);
00308 else if (alignment & Qt::AlignRight)
00309 offset.setX(maxSize.width() - image.width());
00310
00311 if (alignment & Qt::AlignVCenter)
00312 offset.setY((maxSize.height() - image.height())/2);
00313 else if (alignment & Qt::AlignBottom)
00314 offset.setY(maxSize.height() - image.height());
00315
00316 redraw();
00317 }
00318
00319 void ImageShape::redraw()
00320 {
00321 image.fill(qRgba(alpha, alpha, alpha, alpha));
00322
00323 QPainter painter;
00324 painter.begin(&image);
00325 painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
00326 painter.drawImage(0, 0, source);
00327 painter.end();
00328 }
00329
00330 void ImageShape::paint(QPainter *painter) const
00331 {
00332 painter->drawImage(pos + offset, image);
00333 }
00334
00335 QRectF ImageShape::rect() const
00336 {
00337 return QRectF(pos, maxSize);
00338 }
00339
00340 bool ImageShape::animate()
00341 {
00342 bool updated = false;
00343
00344 if (!meta.contains("destroy")) {
00345 if (meta.contains("fade")) {
00346 alpha = qBound(meta.value("fade minimum").toInt(),
00347 alpha + meta.value("fade").toInt(), 255);
00348 redraw();
00349
00350 if (alpha == 0) {
00351 meta["destroy"] = true;
00352 meta.remove("fade");
00353 } else if (alpha == 255)
00354 meta.remove("fade");
00355
00356 updated = true;
00357 }
00358 }
00359
00360 return DisplayShape::animate() || updated;
00361 }
00362
00363 DocumentShape::DocumentShape(const QString &text, const QFont &font,
00364 const QPointF &position, const QSizeF &maxSize,
00365 int alpha)
00366 : DisplayShape(position, maxSize), alpha(alpha)
00367 {
00368 textDocument.setHtml(text);
00369 textDocument.setDefaultFont(font);
00370 textDocument.setPageSize(maxSize);
00371 QSizeF documentSize = textDocument.documentLayout()->documentSize();
00372 setSize(QSizeF(maxSize.width(),
00373 qMin(maxSize.height(), documentSize.height())));
00374
00375 source = QImage(int(ceil(documentSize.width())),
00376 int(ceil(documentSize.height())),
00377 QImage::Format_ARGB32_Premultiplied);
00378 source.fill(qRgba(255, 255, 255, 255));
00379
00380 QAbstractTextDocumentLayout::PaintContext context;
00381 textDocument.documentLayout()->setPaintDevice(&source);
00382
00383 QPainter painter;
00384 painter.begin(&source);
00385 painter.setRenderHint(QPainter::TextAntialiasing);
00386 painter.setRenderHint(QPainter::Antialiasing);
00387 textDocument.documentLayout()->draw(&painter, context);
00388 painter.end();
00389
00390 source = source.scaled(int(ceil(maxSize.width())),
00391 int(ceil(maxSize.height())),
00392 Qt::KeepAspectRatio,
00393 Qt::SmoothTransformation);
00394
00395 image = QImage(source.size(), source.format());
00396 redraw();
00397 }
00398
00399 DocumentShape::~DocumentShape()
00400 {
00401 }
00402
00403 bool DocumentShape::animate()
00404 {
00405 bool updated = false;
00406
00407 if (!meta.contains("destroy")) {
00408 if (meta.contains("fade")) {
00409 alpha = qBound(meta.value("fade minimum").toInt(),
00410 alpha + meta.value("fade").toInt(), 255);
00411 redraw();
00412
00413 if (alpha == 0) {
00414 meta["destroy"] = true;
00415 meta.remove("fade");
00416 } else if (alpha == 255)
00417 meta.remove("fade");
00418
00419 updated = true;
00420 }
00421 }
00422
00423 return DisplayShape::animate() || updated;
00424 }
00425
00426 void DocumentShape::redraw()
00427 {
00428 image.fill(qRgba(alpha, alpha, alpha, alpha));
00429
00430 QPainter painter;
00431 painter.begin(&image);
00432 painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
00433 painter.drawImage(0, 0, source);
00434 painter.end();
00435 }
00436
00437 void DocumentShape::paint(QPainter *painter) const
00438 {
00439 painter->drawImage(pos, image);
00440 }
00441
00442 QRectF DocumentShape::rect() const
00443 {
00444 return QRectF(pos, maxSize);
00445 }