Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members | Related Pages

qwt_layout_metrics.cpp

00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  * 
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
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); // reset width
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

Generated on Wed Aug 31 23:02:29 2005 for Qwt User's Guide by  doxygen 1.4.1