src/gui/text/qfontmetrics.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
   163     metrics that are compatible with a certain paint device.
   163     metrics that are compatible with a certain paint device.
   164 */
   164 */
   165 QFontMetrics::QFontMetrics(const QFont &font)
   165 QFontMetrics::QFontMetrics(const QFont &font)
   166     : d(font.d.data())
   166     : d(font.d.data())
   167 {
   167 {
   168     d->ref.ref();
       
   169 }
   168 }
   170 
   169 
   171 /*!
   170 /*!
   172     Constructs a font metrics object for \a font and \a paintdevice.
   171     Constructs a font metrics object for \a font and \a paintdevice.
   173 
   172 
   194         d = new QFontPrivate(*font.d);
   193         d = new QFontPrivate(*font.d);
   195         d->dpi = dpi;
   194         d->dpi = dpi;
   196         d->screen = screen;
   195         d->screen = screen;
   197     } else {
   196     } else {
   198         d = font.d.data();
   197         d = font.d.data();
   199         d->ref.ref();
       
   200     }
   198     }
   201 
   199 
   202 }
   200 }
   203 
   201 
   204 /*!
   202 /*!
   205     Constructs a copy of \a fm.
   203     Constructs a copy of \a fm.
   206 */
   204 */
   207 QFontMetrics::QFontMetrics(const QFontMetrics &fm)
   205 QFontMetrics::QFontMetrics(const QFontMetrics &fm)
   208     : d(fm.d)
   206     : d(fm.d.data())
   209 { d->ref.ref(); }
   207 {
       
   208 }
   210 
   209 
   211 /*!
   210 /*!
   212     Destroys the font metrics object and frees all allocated
   211     Destroys the font metrics object and frees all allocated
   213     resources.
   212     resources.
   214 */
   213 */
   215 QFontMetrics::~QFontMetrics()
   214 QFontMetrics::~QFontMetrics()
   216 {
   215 {
   217     if (!d->ref.deref())
       
   218         delete d;
       
   219 }
   216 }
   220 
   217 
   221 /*!
   218 /*!
   222     Assigns the font metrics \a fm.
   219     Assigns the font metrics \a fm.
   223 */
   220 */
   224 QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm)
   221 QFontMetrics &QFontMetrics::operator=(const QFontMetrics &fm)
   225 {
   222 {
   226     qAtomicAssign(d, fm.d);
   223     d = fm.d.data();
   227     return *this;
   224     return *this;
   228 }
   225 }
   229 
   226 
   230 /*!
   227 /*!
   231     \overload
   228     \overload
   534         len = text.length();
   531         len = text.length();
   535     }
   532     }
   536     if (len == 0)
   533     if (len == 0)
   537         return 0;
   534         return 0;
   538 
   535 
   539     QTextEngine layout(text, d);
   536     QTextEngine layout(text, d.data());
   540     layout.ignoreBidi = true;
   537     layout.ignoreBidi = true;
   541     return qRound(layout.width(0, len));
   538     return qRound(layout.width(0, len));
   542 }
   539 }
   543 
   540 
   544 /*!
   541 /*!
   610     if (script != QUnicodeTables::Common) {
   607     if (script != QUnicodeTables::Common) {
   611         // complex script shaping. Have to do some hard work
   608         // complex script shaping. Have to do some hard work
   612         int from = qMax(0, pos - 8);
   609         int from = qMax(0, pos - 8);
   613         int to = qMin(text.length(), pos + 8);
   610         int to = qMin(text.length(), pos + 8);
   614         QString cstr = QString::fromRawData(text.unicode() + from, to - from);
   611         QString cstr = QString::fromRawData(text.unicode() + from, to - from);
   615         QTextEngine layout(cstr, d);
   612         QTextEngine layout(cstr, d.data());
   616         layout.ignoreBidi = true;
   613         layout.ignoreBidi = true;
   617         layout.itemize();
   614         layout.itemize();
   618         width = qRound(layout.width(pos-from, 1));
   615         width = qRound(layout.width(pos-from, 1));
   619     } else if (QChar::category(ch.unicode()) == QChar::Mark_NonSpacing) {
   616     } else if (QChar::category(ch.unicode()) == QChar::Mark_NonSpacing) {
   620         width = 0;
   617         width = 0;
   659 QRect QFontMetrics::boundingRect(const QString &text) const
   656 QRect QFontMetrics::boundingRect(const QString &text) const
   660 {
   657 {
   661     if (text.length() == 0)
   658     if (text.length() == 0)
   662         return QRect();
   659         return QRect();
   663 
   660 
   664     QTextEngine layout(text, d);
   661     QTextEngine layout(text, d.data());
   665     layout.ignoreBidi = true;
   662     layout.ignoreBidi = true;
   666     layout.itemize();
   663     layout.itemize();
   667     glyph_metrics_t gm = layout.boundingBox(0, text.length());
   664     glyph_metrics_t gm = layout.boundingBox(0, text.length());
   668     return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
   665     return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
   669 }
   666 }
   768         while (tabArray[tabArrayLen])
   765         while (tabArray[tabArrayLen])
   769             tabArrayLen++;
   766             tabArrayLen++;
   770 
   767 
   771     QRectF rb;
   768     QRectF rb;
   772     QRectF rr(rect);
   769     QRectF rr(rect);
   773     qt_format_text(QFont(d), rr, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
   770     qt_format_text(QFont(d.data()), rr, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
   774                    tabArrayLen, 0);
   771                    tabArrayLen, 0);
   775 
   772 
   776     return rb.toAlignedRect();
   773     return rb.toAlignedRect();
   777 }
   774 }
   778 
   775 
   829 QRect QFontMetrics::tightBoundingRect(const QString &text) const
   826 QRect QFontMetrics::tightBoundingRect(const QString &text) const
   830 {
   827 {
   831     if (text.length() == 0)
   828     if (text.length() == 0)
   832         return QRect();
   829         return QRect();
   833 
   830 
   834     QTextEngine layout(text, d);
   831     QTextEngine layout(text, d.data());
   835     layout.ignoreBidi = true;
   832     layout.ignoreBidi = true;
   836     layout.itemize();
   833     layout.itemize();
   837     glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
   834     glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
   838     return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
   835     return QRect(qRound(gm.x), qRound(gm.y), qRound(gm.width), qRound(gm.height));
   839 }
   836 }
   874             posA = posB + 1;
   871             posA = posB + 1;
   875             posB = _text.indexOf(QLatin1Char('\x9c'), posA);
   872             posB = _text.indexOf(QLatin1Char('\x9c'), posA);
   876         }
   873         }
   877         _text = _text.mid(posA);
   874         _text = _text.mid(posA);
   878     }
   875     }
   879     QStackTextEngine engine(_text, QFont(d));
   876     QStackTextEngine engine(_text, QFont(d.data()));
   880     return engine.elidedText(mode, width, flags);
   877     return engine.elidedText(mode, width, flags);
   881 }
   878 }
   882 
   879 
   883 /*!
   880 /*!
   884     Returns the distance from the base line to where an underscore
   881     Returns the distance from the base line to where an underscore
   987 
   984 
   988     Constructs a font metrics object with floating point precision
   985     Constructs a font metrics object with floating point precision
   989     from the given \a fontMetrics object.
   986     from the given \a fontMetrics object.
   990 */
   987 */
   991 QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics)
   988 QFontMetricsF::QFontMetricsF(const QFontMetrics &fontMetrics)
   992     : d(fontMetrics.d)
   989     : d(fontMetrics.d.data())
   993 {
   990 {
   994     d->ref.ref();
       
   995 }
   991 }
   996 
   992 
   997 /*!
   993 /*!
   998     \since 4.2
   994     \since 4.2
   999 
   995 
  1000     Assigns \a other to this object.
   996     Assigns \a other to this object.
  1001 */
   997 */
  1002 QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
   998 QFontMetricsF &QFontMetricsF::operator=(const QFontMetrics &other)
  1003 {
   999 {
  1004     qAtomicAssign(d, other.d);
  1000     d = other.d.data();
  1005     return *this;
  1001     return *this;
  1006 }
  1002 }
  1007 
  1003 
  1008 /*!
  1004 /*!
  1009     Constructs a font metrics object for \a font.
  1005     Constructs a font metrics object for \a font.
  1019     metrics that are compatible with a certain paint device.
  1015     metrics that are compatible with a certain paint device.
  1020 */
  1016 */
  1021 QFontMetricsF::QFontMetricsF(const QFont &font)
  1017 QFontMetricsF::QFontMetricsF(const QFont &font)
  1022     : d(font.d.data())
  1018     : d(font.d.data())
  1023 {
  1019 {
  1024     d->ref.ref();
       
  1025 }
  1020 }
  1026 
  1021 
  1027 /*!
  1022 /*!
  1028     Constructs a font metrics object for \a font and \a paintdevice.
  1023     Constructs a font metrics object for \a font and \a paintdevice.
  1029 
  1024 
  1050         d = new QFontPrivate(*font.d);
  1045         d = new QFontPrivate(*font.d);
  1051         d->dpi = dpi;
  1046         d->dpi = dpi;
  1052         d->screen = screen;
  1047         d->screen = screen;
  1053     } else {
  1048     } else {
  1054         d = font.d.data();
  1049         d = font.d.data();
  1055         d->ref.ref();
       
  1056     }
  1050     }
  1057 
  1051 
  1058 }
  1052 }
  1059 
  1053 
  1060 /*!
  1054 /*!
  1061     Constructs a copy of \a fm.
  1055     Constructs a copy of \a fm.
  1062 */
  1056 */
  1063 QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm)
  1057 QFontMetricsF::QFontMetricsF(const QFontMetricsF &fm)
  1064     : d(fm.d)
  1058     : d(fm.d.data())
  1065 { d->ref.ref(); }
  1059 {
       
  1060 }
  1066 
  1061 
  1067 /*!
  1062 /*!
  1068     Destroys the font metrics object and frees all allocated
  1063     Destroys the font metrics object and frees all allocated
  1069     resources.
  1064     resources.
  1070 */
  1065 */
  1071 QFontMetricsF::~QFontMetricsF()
  1066 QFontMetricsF::~QFontMetricsF()
  1072 {
  1067 {
  1073     if (!d->ref.deref())
       
  1074         delete d;
       
  1075 }
  1068 }
  1076 
  1069 
  1077 /*!
  1070 /*!
  1078     Assigns the font metrics \a fm to this font metrics object.
  1071     Assigns the font metrics \a fm to this font metrics object.
  1079 */
  1072 */
  1080 QFontMetricsF &QFontMetricsF::operator=(const QFontMetricsF &fm)
  1073 QFontMetricsF &QFontMetricsF::operator=(const QFontMetricsF &fm)
  1081 {
  1074 {
  1082     qAtomicAssign(d, fm.d);
  1075     d = fm.d.data();
  1083     return *this;
  1076     return *this;
  1084 }
  1077 }
  1085 
  1078 
  1086 /*!
  1079 /*!
  1087   \overload
  1080   \overload
  1372 
  1365 
  1373     \sa boundingRect()
  1366     \sa boundingRect()
  1374 */
  1367 */
  1375 qreal QFontMetricsF::width(const QString &text) const
  1368 qreal QFontMetricsF::width(const QString &text) const
  1376 {
  1369 {
  1377     QTextEngine layout(text, d);
  1370     int pos = text.indexOf(QLatin1Char('\x9c'));
       
  1371     int len = (pos != -1) ? pos : text.length();
       
  1372 
       
  1373     QTextEngine layout(text, d.data());
  1378     layout.ignoreBidi = true;
  1374     layout.ignoreBidi = true;
  1379     layout.itemize();
  1375     layout.itemize();
  1380     return layout.width(0, text.length()).toReal();
  1376     return layout.width(0, len).toReal();
  1381 }
  1377 }
  1382 
  1378 
  1383 /*!
  1379 /*!
  1384     \overload
  1380     \overload
  1385 
  1381 
  1449 {
  1445 {
  1450     int len = text.length();
  1446     int len = text.length();
  1451     if (len == 0)
  1447     if (len == 0)
  1452         return QRectF();
  1448         return QRectF();
  1453 
  1449 
  1454     QTextEngine layout(text, d);
  1450     QTextEngine layout(text, d.data());
  1455     layout.ignoreBidi = true;
  1451     layout.ignoreBidi = true;
  1456     layout.itemize();
  1452     layout.itemize();
  1457     glyph_metrics_t gm = layout.boundingBox(0, len);
  1453     glyph_metrics_t gm = layout.boundingBox(0, len);
  1458     return QRectF(gm.x.toReal(), gm.y.toReal(),
  1454     return QRectF(gm.x.toReal(), gm.y.toReal(),
  1459                   gm.width.toReal(), gm.height.toReal());
  1455                   gm.width.toReal(), gm.height.toReal());
  1557     if (tabArray)
  1553     if (tabArray)
  1558         while (tabArray[tabArrayLen])
  1554         while (tabArray[tabArrayLen])
  1559             tabArrayLen++;
  1555             tabArrayLen++;
  1560 
  1556 
  1561     QRectF rb;
  1557     QRectF rb;
  1562     qt_format_text(QFont(d), rect, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
  1558     qt_format_text(QFont(d.data()), rect, flags | Qt::TextDontPrint, text, &rb, tabStops, tabArray,
  1563                    tabArrayLen, 0);
  1559                    tabArrayLen, 0);
  1564     return rb;
  1560     return rb;
  1565 }
  1561 }
  1566 
  1562 
  1567 /*!
  1563 /*!
  1592 
  1588 
  1593     \sa boundingRect()
  1589     \sa boundingRect()
  1594 */
  1590 */
  1595 QSizeF QFontMetricsF::size(int flags, const QString &text, int tabStops, int *tabArray) const
  1591 QSizeF QFontMetricsF::size(int flags, const QString &text, int tabStops, int *tabArray) const
  1596 {
  1592 {
  1597     return boundingRect(QRectF(), flags, text, tabStops, tabArray).size();
  1593     return boundingRect(QRectF(), flags | Qt::TextLongestVariant, text, tabStops, tabArray).size();
  1598 }
  1594 }
  1599 
  1595 
  1600 /*!
  1596 /*!
  1601   \since 4.3
  1597   \since 4.3
  1602 
  1598 
  1622 QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
  1618 QRectF QFontMetricsF::tightBoundingRect(const QString &text) const
  1623 {
  1619 {
  1624     if (text.length() == 0)
  1620     if (text.length() == 0)
  1625         return QRect();
  1621         return QRect();
  1626 
  1622 
  1627     QTextEngine layout(text, d);
  1623     QTextEngine layout(text, d.data());
  1628     layout.ignoreBidi = true;
  1624     layout.ignoreBidi = true;
  1629     layout.itemize();
  1625     layout.itemize();
  1630     glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
  1626     glyph_metrics_t gm = layout.tightBoundingBox(0, text.length());
  1631     return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
  1627     return QRectF(gm.x.toReal(), gm.y.toReal(), gm.width.toReal(), gm.height.toReal());
  1632 }
  1628 }
  1647     The \a flags argument is optional and currently only supports
  1643     The \a flags argument is optional and currently only supports
  1648     Qt::TextShowMnemonic as value.
  1644     Qt::TextShowMnemonic as value.
  1649 */
  1645 */
  1650 QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags) const
  1646 QString QFontMetricsF::elidedText(const QString &text, Qt::TextElideMode mode, qreal width, int flags) const
  1651 {
  1647 {
  1652     QStackTextEngine engine(text, QFont(d));
  1648     QString _text = text;
       
  1649     if (!(flags & Qt::TextLongestVariant)) {
       
  1650         int posA = 0;
       
  1651         int posB = _text.indexOf(QLatin1Char('\x9c'));
       
  1652         while (posB >= 0) {
       
  1653             QString portion = _text.mid(posA, posB - posA);
       
  1654             if (size(flags, portion).width() <= width)
       
  1655                 return portion;
       
  1656             posA = posB + 1;
       
  1657             posB = _text.indexOf(QLatin1Char('\x9c'), posA);
       
  1658         }
       
  1659         _text = _text.mid(posA);
       
  1660     }
       
  1661     QStackTextEngine engine(_text, QFont(d.data()));
  1653     return engine.elidedText(mode, QFixed::fromReal(width), flags);
  1662     return engine.elidedText(mode, QFixed::fromReal(width), flags);
  1654 }
  1663 }
  1655 
  1664 
  1656 /*!
  1665 /*!
  1657     Returns the distance from the base line to where an underscore
  1666     Returns the distance from the base line to where an underscore