Ticket #3651: 0002-UnicodeBlockView-SelectBlockForCharacter-and-Charact.patch

File 0002-UnicodeBlockView-SelectBlockForCharacter-and-Charact.patch, 5.9 KB (added by dsizzle, 7 years ago)

Performance patch; linear lookups converted to binary searches

  • src/apps/charactermap/CharacterView.cpp

    From 11f5f66de2db2f8d54b95b586e75f810bca88238 Mon Sep 17 00:00:00 2001
    From: Dale Cieslak <dcieslak@yahoo.com>
    Date: Fri, 2 Jun 2017 22:59:07 +0000
    Subject: [PATCH 2/2] UnicodeBlockView::SelectBlockForCharacter and
     CharacterView::_FrameFor use the same linear search to find which block a
     character is in, so I refactored both to use a shared BlockForCharacter
     function in UnicodeBlocks.cpp that is a binary search.
     CharacterView::_BlockAt also had a TODO comment to use a binary search, so I
     rewrote it as a binary search.  It's not the same search as the
     aforementioned BlockForCharacter function. These two changes ought to improve
     the overall performance of CharacterMap.  #3651 is the issue for CharacterMap
     improvements.
    
    ---
     src/apps/charactermap/CharacterView.cpp    | 53 ++++++++++++++++--------------
     src/apps/charactermap/UnicodeBlockView.cpp | 21 ++++--------
     src/apps/charactermap/UnicodeBlocks.cpp    | 27 +++++++++++++++
     src/apps/charactermap/UnicodeBlocks.h      |  2 ++
     4 files changed, 64 insertions(+), 39 deletions(-)
    
    diff --git a/src/apps/charactermap/CharacterView.cpp b/src/apps/charactermap/CharacterView.cpp
    index 075c536..e4f41db 100644
    a b void  
    110110CharacterView::ScrollToBlock(int32 blockIndex)
    111111{
    112112    // don't scroll if the selected block is already in view.
    113     // this prevents distracting jumps when crossing a block 
     113    // this prevents distracting jumps when crossing a block
    114114    // boundary in the character view.
    115     if (IsBlockVisible(blockIndex))   
     115    if (IsBlockVisible(blockIndex))
    116116        return;
    117        
     117
    118118    if (blockIndex < 0)
    119119        blockIndex = 0;
    120120    else if (blockIndex >= (int32)kNumUnicodeBlocks)
    bool  
    146146CharacterView::IsBlockVisible(int32 block) const
    147147{
    148148    int32 topBlock = _BlockAt(BPoint(Bounds().left, Bounds().top));
    149     int32 bottomBlock = _BlockAt(BPoint(Bounds().right, Bounds().bottom)); 
     149    int32 bottomBlock = _BlockAt(BPoint(Bounds().right, Bounds().bottom));
    150150
    151     if (block >= topBlock && block <= bottomBlock) 
     151    if (block >= topBlock && block <= bottomBlock)
    152152        return true;
    153        
     153
    154154    return false;
    155155}
    156156
    CharacterView::DoLayout()  
    478478int32
    479479CharacterView::_BlockAt(BPoint point) const
    480480{
    481     // TODO: use binary search
    482     for (uint32 i = 0; i < kNumUnicodeBlocks; i++) {
    483         if (!IsShowingBlock(i))
    484             continue;
     481    uint32 min = 0;
     482    uint32 max = kNumUnicodeBlocks;
     483    uint32 guess = (max + min) / 2;
     484
     485    while ((max >= min) && (guess < kNumUnicodeBlocks - 1 )) {
     486        if (fTitleTops[guess] <= point.y && fTitleTops[guess + 1] >= point.y) {
     487            if (!IsShowingBlock(guess))
     488                return -1;
     489            else
     490                return guess;
     491        }
    485492
    486         if (fTitleTops[i] <= point.y
    487             && (i == kNumUnicodeBlocks - 1 || fTitleTops[i + 1] > point.y))
    488             return i;
     493        if (fTitleTops[guess + 1] < point.y) {
     494            min = guess + 1;
     495        } else {
     496            max = guess - 1;
     497        }
     498
     499        guess = (max + min) / 2;
    489500    }
    490501
    491502    return -1;
    BRect  
    650661CharacterView::_FrameFor(uint32 character) const
    651662{
    652663    // find block containing the character
     664    int32 blockNumber = BlockForCharacter(character);
    653665
    654     // TODO: could use binary search here
    655 
    656     for (uint32 i = 0; i < kNumUnicodeBlocks; i++) {
    657         if (kUnicodeBlocks[i].end < character)
    658             continue;
    659         if (kUnicodeBlocks[i].start > character) {
    660             // Character is not mapped
    661             return BRect();
    662         }
    663 
    664         int32 diff = character - kUnicodeBlocks[i].start;
    665         int32 y = fTitleTops[i] + fTitleHeight
     666    if (blockNumber > 0) {
     667        int32 diff = character - kUnicodeBlocks[blockNumber].start;
     668        int32 y = fTitleTops[blockNumber] + fTitleHeight
    666669            + (diff / fCharactersPerLine) * fCharacterHeight;
    667670        int32 x = fGap / 2 + diff % fCharactersPerLine;
    668671
  • src/apps/charactermap/UnicodeBlockView.cpp

    diff --git a/src/apps/charactermap/UnicodeBlockView.cpp b/src/apps/charactermap/UnicodeBlockView.cpp
    index b40e40b..ee60811 100644
    a b void  
    123123UnicodeBlockView::SelectBlockForCharacter(uint32 character)
    124124{
    125125    // find block containing the character
     126    int32 blockNumber = BlockForCharacter(character);
    126127
    127     // TODO: could use binary search here
    128     for (uint32 i = 0; i < kNumUnicodeBlocks; i++) {
    129         if (kUnicodeBlocks[i].end < character)
    130             continue;
    131         if (kUnicodeBlocks[i].start > character) {
    132             // Character is not mapped
    133             break;
    134         }
     128    if (blockNumber > 0) {
     129        BlockListItem* block = fBlocks.ItemAt(blockNumber);
     130
     131        int32 blockIndex = IndexOf(block);
    135132
    136         BlockListItem* block = fBlocks.ItemAt(i);
    137        
    138         int32 blockNum = IndexOf(block);
    139        
    140         if (blockNum >= 0) {
    141             Select(blockNum);
     133        if (blockIndex >= 0) {
     134            Select(blockIndex);
    142135            ScrollToSelection();
    143136        }
    144137    }
  • src/apps/charactermap/UnicodeBlocks.cpp

    diff --git a/src/apps/charactermap/UnicodeBlocks.cpp b/src/apps/charactermap/UnicodeBlocks.cpp
    index e165ac9..597ea4e 100644
    a b const struct unicode_block_entry kUnicodeBlocks[] = {  
    233233
    234234const uint32 kNumUnicodeBlocks
    235235    = sizeof(kUnicodeBlocks) / sizeof(kUnicodeBlocks[0]);
     236
     237
     238int32
     239BlockForCharacter(const uint32 character)
     240{
     241    uint32 min = 0;
     242    uint32 max = kNumUnicodeBlocks;
     243    uint32 guess = (max + min) / 2;
     244
     245    while ((max >= min) && (guess < kNumUnicodeBlocks)) {
     246        uint32 start = kUnicodeBlocks[guess].start;
     247        uint32 end = kUnicodeBlocks[guess].end;
     248
     249        if (start <= character && end >= character)
     250            return guess;
     251
     252        if (end < character) {
     253            min = guess + 1;
     254        } else {
     255            max = guess - 1;
     256        }
     257
     258        guess = (max + min) / 2;
     259    }
     260
     261    return -1;
     262}
  • src/apps/charactermap/UnicodeBlocks.h

    diff --git a/src/apps/charactermap/UnicodeBlocks.h b/src/apps/charactermap/UnicodeBlocks.h
    index 4c6b99c..7e90382 100644
    a b extern const unicode_block kNoBlock;  
    2323extern const struct unicode_block_entry kUnicodeBlocks[];
    2424extern const uint32 kNumUnicodeBlocks;
    2525
     26int32 BlockForCharacter(const uint32 character);
     27
    2628#endif  // UNICODE_BLOCKS_H