00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <qapplication.h>
00011 #include <qpainter.h>
00012 #if QT_VERSION < 0x040000
00013 #include <qpaintdevicemetrics.h>
00014 #include <qsimplerichtext.h>
00015 #include <qwmatrix.h>
00016 #include <qpointarray.h>
00017 #define QwtPointArray QPointArray
00018 #define QwtMatrix QWMatrix
00019 #else
00020 #include <qlabel.h>
00021 #include <qtextdocument.h>
00022 #include <qabstracttextdocumentlayout.h>
00023 #include <qmatrix.h>
00024 #include <qpolygon.h>
00025 #define QwtPointArray QPolygon
00026 #define QwtMatrix QMatrix
00027 #endif
00028 #include <qpaintdevice.h>
00029 #include <qdesktopwidget.h>
00030 #include "qwt_math.h"
00031 #include "qwt_layout_metrics.h"
00032
00033 static QSize deviceDpi(const QPaintDevice *device)
00034 {
00035 QSize dpi;
00036 #if QT_VERSION < 0x040000
00037 const QPaintDeviceMetrics metrics(device);
00038 dpi.setWidth(metrics.logicalDpiX());
00039 dpi.setHeight(metrics.logicalDpiY());
00040 #else
00041 dpi.setWidth(device->logicalDpiX());
00042 dpi.setHeight(device->logicalDpiY());
00043 #endif
00044
00045 return dpi;
00046 }
00047
00048 #if QT_VERSION < 0x040000
00049
00050 inline static const QWMatrix &matrix(const QPainter *painter)
00051 {
00052 return painter->worldMatrix();
00053 }
00054 inline static QWMatrix invMatrix(const QPainter *painter)
00055 {
00056 return painter->worldMatrix().invert();
00057 }
00058
00059 #else // QT_VERSION >= 0x040000
00060
00061 inline static const QMatrix &matrix(const QPainter *painter)
00062 {
00063 return painter->matrix();
00064 }
00065 inline static QMatrix invMatrix(const QPainter *painter)
00066 {
00067 return painter->matrix().inverted();
00068 }
00069
00070 #endif
00071
00072 static QRect alignedRect(int w, int h, int flags)
00073 {
00074 int x = 0;
00075 int y = 0;
00076 if (flags & Qt::AlignHCenter)
00077 x -= w/2;
00078 else if (flags & Qt::AlignRight)
00079 x -= w;
00080
00081 if (flags & Qt::AlignVCenter)
00082 y -= h/2;
00083 else if (flags & Qt::AlignBottom)
00084 y -= h;
00085
00086 return QRect(x, y, w, h);
00087 }
00088
00089 QwtMetricsMap::QwtMetricsMap()
00090 {
00091 d_screenToLayoutX = d_screenToLayoutY =
00092 d_deviceToLayoutX = d_deviceToLayoutY = 1.0;
00093 }
00094
00095 void QwtMetricsMap::setMetrics(const QPaintDevice *layoutDevice,
00096 const QPaintDevice *paintDevice)
00097 {
00098 const QSize screenDpi = deviceDpi(QApplication::desktop());
00099 const QSize layoutDpi = deviceDpi(layoutDevice);
00100 const QSize paintDpi = deviceDpi(paintDevice);
00101
00102 d_screenToLayoutX = double(layoutDpi.width()) /
00103 double(screenDpi.width());
00104 d_screenToLayoutY = double(layoutDpi.height()) /
00105 double(screenDpi.height());
00106
00107 d_deviceToLayoutX = double(layoutDpi.width()) /
00108 double(paintDpi.width());
00109 d_deviceToLayoutY = double(layoutDpi.height()) /
00110 double(paintDpi.height());
00111 }
00112
00113 #ifndef QT_NO_TRANSFORMATIONS
00114 QPoint QwtMetricsMap::layoutToDevice(const QPoint &point,
00115 const QPainter *painter) const
00116 #else
00117 QPoint QwtMetricsMap::layoutToDevice(const QPoint &point,
00118 const QPainter *) const
00119 #endif
00120 {
00121 if ( isIdentity() )
00122 return point;
00123
00124 QPoint mappedPoint(point);
00125
00126 #ifndef QT_NO_TRANSFORMATIONS
00127 if ( painter )
00128 mappedPoint = matrix(painter).map(mappedPoint);
00129 #endif
00130
00131 mappedPoint.setX(layoutToDeviceX(mappedPoint.x()));
00132 mappedPoint.setY(layoutToDeviceY(mappedPoint.y()));
00133
00134 #ifndef QT_NO_TRANSFORMATIONS
00135 if ( painter )
00136 mappedPoint = invMatrix(painter).map(mappedPoint);
00137 #endif
00138
00139 return mappedPoint;
00140 }
00141
00142 #ifndef QT_NO_TRANSFORMATIONS
00143 QPoint QwtMetricsMap::deviceToLayout(const QPoint &point,
00144 const QPainter *painter) const
00145 #else
00146 QPoint QwtMetricsMap::deviceToLayout(const QPoint &point,
00147 const QPainter *) const
00148 #endif
00149 {
00150 if ( isIdentity() )
00151 return point;
00152
00153 QPoint mappedPoint(point);
00154
00155 #ifndef QT_NO_TRANSFORMATIONS
00156 if ( painter )
00157 mappedPoint = matrix(painter).map(mappedPoint);
00158 #endif
00159
00160 mappedPoint.setX(deviceToLayoutX(mappedPoint.x()));
00161 mappedPoint.setY(deviceToLayoutY(mappedPoint.y()));
00162
00163 #ifndef QT_NO_TRANSFORMATIONS
00164 if ( painter )
00165 mappedPoint = invMatrix(painter).map(mappedPoint);
00166 #endif
00167
00168 return mappedPoint;
00169 }
00170
00171 QPoint QwtMetricsMap::screenToLayout(const QPoint &point) const
00172 {
00173 if ( d_screenToLayoutX == 1.0 && d_screenToLayoutY == 1.0 )
00174 return point;
00175
00176 return QPoint(screenToLayoutX(point.x()), screenToLayoutY(point.y()));
00177 }
00178
00179 #ifndef QT_NO_TRANSFORMATIONS
00180 QRect QwtMetricsMap::layoutToDevice(const QRect &rect,
00181 const QPainter *painter) const
00182 #else
00183 QRect QwtMetricsMap::layoutToDevice(const QRect &rect,
00184 const QPainter *) const
00185 #endif
00186 {
00187 if ( isIdentity() )
00188 return rect;
00189
00190 QRect mappedRect(rect);
00191 #ifndef QT_NO_TRANSFORMATIONS
00192 if ( painter )
00193 mappedRect = translate(matrix(painter), mappedRect);
00194 #endif
00195
00196 mappedRect = QRect(
00197 layoutToDeviceX(mappedRect.x()),
00198 layoutToDeviceY(mappedRect.y()),
00199 layoutToDeviceX(mappedRect.width()),
00200 layoutToDeviceY(mappedRect.height())
00201 );
00202
00203 #ifndef QT_NO_TRANSFORMATIONS
00204 if ( painter )
00205 mappedRect = translate(invMatrix(painter), mappedRect);
00206 #endif
00207
00208 return mappedRect;
00209 }
00210
00211 #ifndef QT_NO_TRANSFORMATIONS
00212 QRect QwtMetricsMap::deviceToLayout(const QRect &rect,
00213 const QPainter *painter) const
00214 #else
00215 QRect QwtMetricsMap::deviceToLayout(const QRect &rect,
00216 const QPainter *) const
00217 #endif
00218 {
00219 if ( isIdentity() )
00220 return rect;
00221
00222 QRect mappedRect(rect);
00223 #ifndef QT_NO_TRANSFORMATIONS
00224 if ( painter )
00225 mappedRect = translate(matrix(painter), mappedRect);
00226 #endif
00227
00228 mappedRect = QRect(
00229 deviceToLayoutX(mappedRect.x()),
00230 deviceToLayoutY(mappedRect.y()),
00231 deviceToLayoutX(mappedRect.width()),
00232 deviceToLayoutY(mappedRect.height())
00233 );
00234
00235 #ifndef QT_NO_TRANSFORMATIONS
00236 if ( painter )
00237 mappedRect = translate(invMatrix(painter), mappedRect);
00238 #endif
00239
00240 return mappedRect;
00241 }
00242
00243 QRect QwtMetricsMap::screenToLayout(const QRect &rect) const
00244 {
00245 if ( d_deviceToLayoutX == 1.0 && d_deviceToLayoutY == 1.0 )
00246 return rect;
00247
00248 return QRect(screenToLayoutX(rect.x()), screenToLayoutY(rect.y()),
00249 screenToLayoutX(rect.width()), screenToLayoutY(rect.height()));
00250 }
00251
00252 #ifndef QT_NO_TRANSFORMATIONS
00253 QwtPointArray QwtMetricsMap::layoutToDevice(const QwtPointArray &pa,
00254 const QPainter *painter) const
00255 #else
00256 QwtPointArray QwtMetricsMap::layoutToDevice(const QwtPointArray &pa,
00257 const QPainter *) const
00258 #endif
00259 {
00260 if ( isIdentity() )
00261 return pa;
00262
00263 QwtPointArray mappedPa(pa);
00264
00265 #ifndef QT_NO_TRANSFORMATIONS
00266 if ( painter )
00267 mappedPa = translate(matrix(painter), mappedPa);
00268 #endif
00269
00270 QwtMatrix m;
00271 m.scale(1.0 / d_deviceToLayoutX, 1.0 / d_deviceToLayoutY);
00272 mappedPa = translate(m, mappedPa);
00273
00274 #ifndef QT_NO_TRANSFORMATIONS
00275 if ( painter )
00276 mappedPa = translate(invMatrix(painter), mappedPa);
00277 #endif
00278
00279 return mappedPa;
00280 }
00281
00282 #ifndef QT_NO_TRANSFORMATIONS
00283 QwtPointArray QwtMetricsMap::deviceToLayout(const QwtPointArray &pa,
00284 const QPainter *painter) const
00285 #else
00286 QwtPointArray QwtMetricsMap::deviceToLayout(const QwtPointArray &pa,
00287 const QPainter *) const
00288 #endif
00289 {
00290 if ( isIdentity() )
00291 return pa;
00292
00293 QwtPointArray mappedPa(pa);
00294
00295 #ifndef QT_NO_TRANSFORMATIONS
00296 if ( painter )
00297 mappedPa = translate(matrix(painter), mappedPa);
00298 #endif
00299
00300 QwtMatrix m;
00301 m.scale(d_deviceToLayoutX, d_deviceToLayoutY);
00302 mappedPa = translate(m, mappedPa);
00303
00304 #ifndef QT_NO_TRANSFORMATIONS
00305 if ( painter )
00306 mappedPa = translate(invMatrix(painter), mappedPa);
00307 #endif
00308
00309 return mappedPa;
00310 }
00311
00316 QRect QwtMetricsMap::translate(
00317 const QwtMatrix &m, const QRect &rect)
00318 {
00319 return m.mapRect(rect);
00320 }
00321
00326 QwtPointArray QwtMetricsMap::translate(
00327 const QwtMatrix &m, const QwtPointArray &pa)
00328 {
00329 return m.map(pa);
00330 }
00331
00332 QwtLayoutMetrics::QwtLayoutMetrics()
00333 {
00334 }
00335
00336 QwtLayoutMetrics::QwtLayoutMetrics(const QwtMetricsMap &map):
00337 d_map(map)
00338 {
00339 }
00340
00341 void QwtLayoutMetrics::setMap(const QwtMetricsMap &map)
00342 {
00343 d_map = map;
00344 }
00345
00346 int QwtLayoutMetrics::heightForWidth(const QString &text,
00347 int width, int flags, const QFontMetrics &fm) const
00348 {
00349 const QRect rect = fm.boundingRect(
00350 0, 0, d_map.layoutToScreenX(width), QWIDGETSIZE_MAX, flags, text);
00351 return d_map.screenToLayoutY(rect.height());
00352 }
00353
00354 int QwtLayoutMetrics::heightForWidth(const QString &text,
00355 int width, int flags, QPainter *painter) const
00356 {
00357 const QRect rect = painter->boundingRect(
00358 0, 0, d_map.layoutToDeviceX(width), QWIDGETSIZE_MAX, flags, text);
00359
00360 return d_map.deviceToLayoutY(rect.height());
00361 }
00362
00363 QRect QwtLayoutMetrics::boundingRect(const QString &text,
00364 int flags, QPainter *painter) const
00365 {
00366 const QRect rect = painter->boundingRect(
00367 0, 0, 0, 0, flags, text);
00368
00369 return d_map.deviceToLayout(rect);
00370 }
00371
00372 QRect QwtLayoutMetrics::boundingRect(const QString &text,
00373 int flags, const QFontMetrics &fm) const
00374 {
00375 QRect rect = fm.boundingRect(
00376 0, 0, QWIDGETSIZE_MAX, QWIDGETSIZE_MAX, flags, text);
00377
00378 return d_map.screenToLayout(rect);
00379 }
00380
00381 #ifndef QT_NO_RICHTEXT
00382
00383 #if QT_VERSION < 0x040000
00384 int QwtLayoutMetrics::heightForWidth(QSimpleRichText &text, int width) const
00385 {
00386 text.setWidth(d_map.layoutToScreenX(width));
00387 return d_map.screenToLayoutY(text.height());
00388 }
00389
00390 QRect QwtLayoutMetrics::boundingRect(
00391 const QSimpleRichText &text, int flags, QPainter *painter) const
00392 {
00393 const int tw = text.width();
00394
00395 int w, h;
00396 if ( painter )
00397 {
00398 ((QSimpleRichText &)text).setWidth(painter, QWIDGETSIZE_MAX);
00399 w = d_map.deviceToLayoutX(text.widthUsed());
00400 h = d_map.deviceToLayoutY(text.height());
00401 }
00402 else
00403 {
00404 ((QSimpleRichText &)text).setWidth(QWIDGETSIZE_MAX);
00405 w = d_map.screenToLayoutX(text.widthUsed());
00406 h = d_map.screenToLayoutY(text.height());
00407 }
00408
00409 ((QSimpleRichText &)text).setWidth(tw);
00410
00411 return alignedRect(w, h, flags);
00412 }
00413 #else
00414 int QwtLayoutMetrics::heightForWidth(QTextDocument &text, int width) const
00415 {
00416 width = d_map.layoutToScreenX(width);
00417 text.setPageSize(QSize(width, QWIDGETSIZE_MAX));
00418
00419 const int h = qRound(text.documentLayout()->documentSize().height());
00420 return d_map.screenToLayoutY(h);
00421 }
00422
00423 QRect QwtLayoutMetrics::boundingRect(const QString &text,
00424 QTextDocument &doc, int flags) const
00425 {
00426 static int off = 0;
00427 static QLabel *label = NULL;
00428 if ( label == NULL )
00429 {
00430 label = new QLabel;
00431 label->hide();
00432
00433 const char *s = "XXXXX";
00434 label->setText(s);
00435 int w1 = label->sizeHint().width();
00436 const QFontMetrics fm(label->font());
00437 int w2 = fm.width(s);
00438 off = w1 - w2;
00439 }
00440 label->setFont(doc.defaultFont());
00441 label->setText(text);
00442
00443 int w = qwtMax(label->sizeHint().width() - off, 0);
00444 w = d_map.screenToLayoutX(w);
00445
00446 int h = heightForWidth(doc, w);
00447
00448 return alignedRect(w, h, flags);
00449 }
00450 #endif
00451
00452 #endif // !QT_NO_RICHTEXT