##// END OF EJS Templates
Optimize string truncation algorithm...
Miikka Heikkinen -
r2541:563b21497627
parent child
Show More
@@ -36,12 +36,19
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 QGraphicsTextItem *dummyTextItem = 0;
39 static QGraphicsTextItem *dummyTextItem = 0;
40 static const char *truncateMatchString = "&#?[0-9a-zA-Z]*;$";
41 static QRegExp *truncateMatcher = 0;
42
40 43 class StaticDummyTextDeleter
41 44 {
42 45 public:
43 46 StaticDummyTextDeleter() {}
44 ~StaticDummyTextDeleter() { delete dummyTextItem; }
47 ~StaticDummyTextDeleter()
48 {
49 delete dummyTextItem;
50 delete truncateMatcher;
51 }
45 52 };
46 53 StaticDummyTextDeleter staticDummyTextDeleter;
47 54
@@ -416,23 +423,60 QString ChartPresenter::truncatedText(const QFont &font, const QString &text, qr
416 423 qreal checkDimension = ((constraintOrientation == Qt::Horizontal)
417 424 ? boundingRect.width() : boundingRect.height());
418 425 if (checkDimension > maxSize) {
419 truncatedString.append("...");
420 while (checkDimension > maxSize && truncatedString.length() > 3) {
421 // Crude truncation logic - simply remove any html tag completely
422 int removeIndex(-1);
423 int removeCount(1);
424 if (truncatedString.at(truncatedString.length() - 4) == QLatin1Char('>')) {
425 removeIndex = truncatedString.lastIndexOf(QLatin1Char('<'));
426 if (removeIndex != -1)
427 removeCount = truncatedString.length() - 3 - removeIndex;
428 }
429 if (removeIndex == -1)
430 removeIndex = truncatedString.length() - 4;
431
432 truncatedString.remove(removeIndex, removeCount);
433 boundingRect = textBoundingRect(font, truncatedString, angle);
426 // It can be assumed that almost any amount of string manipulation is faster
427 // than calculating one bounding rectangle, so first prepare a list of truncated strings
428 // to try.
429 if (!truncateMatcher)
430 truncateMatcher = new QRegExp(truncateMatchString);
431 QVector<QString> testStrings(text.length());
432 int count(0);
433 static QLatin1Char closeTag('>');
434 static QLatin1Char openTag('<');
435 static QLatin1Char semiColon(';');
436 static QLatin1String ellipsis("...");
437 while (truncatedString.length() > 1) {
438 int chopIndex(-1);
439 int chopCount(1);
440 QChar lastChar(truncatedString.at(truncatedString.length() - 1));
441
442 if (lastChar == closeTag)
443 chopIndex = truncatedString.lastIndexOf(openTag);
444 else if (lastChar == semiColon)
445 chopIndex = truncateMatcher->indexIn(truncatedString, 0);
446
447 if (chopIndex != -1)
448 chopCount = truncatedString.length() - chopIndex;
449 truncatedString.chop(chopCount);
450 testStrings[count] = truncatedString + ellipsis;
451 count++;
452 }
453
454 // Binary search for best fit
455 int minIndex(0);
456 int maxIndex(count - 1);
457 int bestIndex(count);
458 QRectF checkRect;
459 while (maxIndex >= minIndex) {
460 int mid = (maxIndex + minIndex) / 2;
461 checkRect = textBoundingRect(font, testStrings.at(mid), angle);
434 462 checkDimension = ((constraintOrientation == Qt::Horizontal)
435 ? boundingRect.width() : boundingRect.height());
463 ? checkRect.width() : checkRect.height());
464 if (checkDimension > maxSize) {
465 // Checked index too large, all under this are also too large
466 minIndex = mid + 1;
467 } else {
468 // Checked index fits, all over this also fit
469 maxIndex = mid - 1;
470 bestIndex = mid;
471 boundingRect = checkRect;
472 }
473 }
474 // Default to "..." if nothing fits
475 if (bestIndex == count) {
476 boundingRect = textBoundingRect(font, ellipsis, angle);
477 truncatedString = ellipsis;
478 } else {
479 truncatedString = testStrings.at(bestIndex);
436 480 }
437 481 }
438 482
General Comments 0
You need to be logged in to leave comments. Login now