| 553 | } |
| 554 | |
| 555 | void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, |
| 556 | const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc) { |
| 557 | |
| 558 | allClear = false; |
| 559 | int probe = -1; |
| 560 | if ((!pces.empty()) && (len < 30)) { |
| 561 | // Only store short strings in the cache so it doesn't churn with |
| 562 | // long comments with only a single comment. |
| 563 | |
| 564 | // Two way associative: try two probe positions. |
| 565 | int hashValue = PositionCacheEntry::Hash(styleNumber, s, len); |
| 566 | probe = static_cast<int>(hashValue % pces.size()); |
| 567 | if (pces[probe].Retrieve(styleNumber, s, len, positions)) { |
| 568 | return; |
| 569 | } |
| 570 | int probe2 = static_cast<int>((hashValue * 37) % pces.size()); |
| 571 | if (pces[probe2].Retrieve(styleNumber, s, len, positions)) { |
| 572 | return; |
| 573 | } |
| 574 | // Not found. Choose the oldest of the two slots to replace |
| 575 | if (pces[probe].NewerThan(pces[probe2])) { |
| 576 | probe = probe2; |
| 577 | } |
| 578 | } |
| 579 | if (len > BreakFinder::lengthStartSubdivision) { |
| 580 | // Break up into segments |
| 581 | unsigned int startSegment = 0; |
| 582 | XYPOSITION xStartSegment = 0; |
| 583 | while (startSegment < len) { |
| 584 | unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision); |
| 585 | surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment); |
| 586 | for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) { |
| 587 | positions[startSegment + inSeg] += xStartSegment; |
| 588 | } |
| 589 | xStartSegment = positions[startSegment + lenSegment - 1]; |
| 590 | startSegment += lenSegment; |
| 591 | } |
| 592 | } else { |
| 593 | surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions); |
| 594 | } |
| 595 | if (probe >= 0) { |
| 596 | clock++; |
| 597 | if (clock > 60000) { |
| 598 | // Since there are only 16 bits for the clock, wrap it round and |
| 599 | // reset all cache entries so none get stuck with a high clock. |
| 600 | for (size_t i=0; i<pces.size(); i++) { |
| 601 | pces[i].ResetClock(); |
| 602 | } |
| 603 | clock = 2; |
| 604 | } |
| 605 | pces[probe].Set(styleNumber, s, len, positions, clock); |
| 606 | } |
| 607 | } |
no test coverage detected