src/gui/text/qtextformat.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
--- a/src/gui/text/qtextformat.cpp	Tue Jan 26 12:42:25 2010 +0200
+++ b/src/gui/text/qtextformat.cpp	Tue Feb 02 00:43:10 2010 +0200
@@ -265,21 +265,55 @@
     friend QDataStream &operator>>(QDataStream &, QTextFormat &);
 };
 
-static uint variantHash(const QVariant &variant)
+// this is only safe if sizeof(int) == sizeof(float)
+static inline uint hash(float d)
+{
+    return reinterpret_cast<uint&>(d);
+}
+
+static inline uint hash(const QColor &color)
+{
+    return (color.isValid()) ? color.rgba() : 0x234109;
+}
+
+static inline uint hash(const QPen &pen)
+{
+    return hash(pen.color()) + hash(pen.widthF());
+}
+
+static inline uint hash(const QBrush &brush)
 {
-    switch (variant.userType()) {
+    return hash(brush.color()) + (brush.style() << 3);
+}
+
+static inline uint variantHash(const QVariant &variant)
+{
+    // simple and fast hash functions to differentiate between type and value
+    switch (variant.userType()) { // sorted by occurrence frequency
+    case QVariant::String: return qHash(variant.toString());
+    case QVariant::Double: return hash(variant.toDouble());
+    case QVariant::Int: return 0x811890 + variant.toInt();
+    case QVariant::Brush:
+        return 0x01010101 + hash(qvariant_cast<QBrush>(variant));
+    case QVariant::Bool: return 0x371818 + variant.toBool();
+    case QVariant::Pen: return 0x02020202 + hash(qvariant_cast<QPen>(variant));
+    case QVariant::List:
+        return 0x8377 + qvariant_cast<QVariantList>(variant).count();
+    case QVariant::Color: return hash(qvariant_cast<QColor>(variant));
+      case QVariant::TextLength:
+        return 0x377 + hash(qvariant_cast<QTextLength>(variant).rawValue());
+    case QMetaType::Float: return hash(variant.toFloat());
     case QVariant::Invalid: return 0;
-    case QVariant::Bool: return variant.toBool();
-    case QVariant::Int: return variant.toInt();
-    case QMetaType::Float: return static_cast<int>(variant.toFloat());
-    case QVariant::Double: return static_cast<int>(variant.toDouble());
-    case QVariant::String: return qHash(variant.toString());
-    case QVariant::Color: return qHash(qvariant_cast<QColor>(variant).rgb());
     default: break;
     }
     return qHash(variant.typeName());
 }
 
+static inline int getHash(const QTextFormatPrivate *d, int format)
+{
+    return (d ? d->hash() : 0) + format;
+}
+
 uint QTextFormatPrivate::recalcHash() const
 {
     hashValue = 0;
@@ -3033,13 +3067,15 @@
 
 int QTextFormatCollection::indexForFormat(const QTextFormat &format)
 {
-    uint hash = format.d ? format.d->hash() : 0;
-    if (hashes.contains(hash)) {
-        for (int i = 0; i < formats.size(); ++i) {
-            if (formats.at(i) == format)
-                return i;
+    uint hash = getHash(format.d, format.format_type);
+    QMultiHash<uint, int>::const_iterator i = hashes.find(hash);
+    while (i != hashes.end() && i.key() == hash) {
+        if (formats.value(i.value()) == format) {
+            return i.value();
         }
+        ++i;
     }
+
     int idx = formats.size();
     formats.append(format);
 
@@ -3049,7 +3085,7 @@
             f.d = new QTextFormatPrivate;
         f.d->resolveFont(defaultFnt);
 
-        hashes.insert(hash);
+        hashes.insert(hash, idx);
 
     } QT_CATCH(...) {
         formats.pop_back();
@@ -3060,11 +3096,13 @@
 
 bool QTextFormatCollection::hasFormatCached(const QTextFormat &format) const
 {
-    uint hash = format.d ? format.d->hash() : 0;
-    if (hashes.contains(hash)) {
-        for (int i = 0; i < formats.size(); ++i)
-            if (formats.at(i) == format)
-                return true;
+    uint hash = getHash(format.d, format.format_type);
+    QMultiHash<uint, int>::const_iterator i = hashes.find(hash);
+    while (i != hashes.end() && i.key() == hash) {
+        if (formats.value(i.value()) == format) {
+            return true;
+        }
+        ++i;
     }
     return false;
 }