LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkRTree.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 117 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2012 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #include "SkRTree.h"
       9             : 
      10           0 : SkRTree::SkRTree(SkScalar aspectRatio)
      11           0 :     : fCount(0), fAspectRatio(isfinite(aspectRatio) ? aspectRatio : 1) {}
      12             : 
      13           0 : SkRect SkRTree::getRootBound() const {
      14           0 :     if (fCount) {
      15           0 :         return fRoot.fBounds;
      16             :     } else {
      17           0 :         return SkRect::MakeEmpty();
      18             :     }
      19             : }
      20             : 
      21           0 : void SkRTree::insert(const SkRect boundsArray[], int N) {
      22           0 :     SkASSERT(0 == fCount);
      23             : 
      24           0 :     SkTDArray<Branch> branches;
      25           0 :     branches.setReserve(N);
      26             : 
      27           0 :     for (int i = 0; i < N; i++) {
      28           0 :         const SkRect& bounds = boundsArray[i];
      29           0 :         if (bounds.isEmpty()) {
      30           0 :             continue;
      31             :         }
      32             : 
      33           0 :         Branch* b = branches.push();
      34           0 :         b->fBounds = bounds;
      35           0 :         b->fOpIndex = i;
      36             :     }
      37             : 
      38           0 :     fCount = branches.count();
      39           0 :     if (fCount) {
      40           0 :         if (1 == fCount) {
      41           0 :             fNodes.setReserve(1);
      42           0 :             Node* n = this->allocateNodeAtLevel(0);
      43           0 :             n->fNumChildren = 1;
      44           0 :             n->fChildren[0] = branches[0];
      45           0 :             fRoot.fSubtree = n;
      46           0 :             fRoot.fBounds  = branches[0].fBounds;
      47             :         } else {
      48           0 :             fNodes.setReserve(CountNodes(fCount, fAspectRatio));
      49           0 :             fRoot = this->bulkLoad(&branches);
      50             :         }
      51             :     }
      52           0 : }
      53             : 
      54           0 : SkRTree::Node* SkRTree::allocateNodeAtLevel(uint16_t level) {
      55           0 :     SkDEBUGCODE(Node* p = fNodes.begin());
      56           0 :     Node* out = fNodes.push();
      57           0 :     SkASSERT(fNodes.begin() == p);  // If this fails, we didn't setReserve() enough.
      58           0 :     out->fNumChildren = 0;
      59           0 :     out->fLevel = level;
      60           0 :     return out;
      61             : }
      62             : 
      63             : // This function parallels bulkLoad, but just counts how many nodes bulkLoad would allocate.
      64           0 : int SkRTree::CountNodes(int branches, SkScalar aspectRatio) {
      65           0 :     if (branches == 1) {
      66           0 :         return 1;
      67             :     }
      68           0 :     int numBranches = branches / kMaxChildren;
      69           0 :     int remainder   = branches % kMaxChildren;
      70           0 :     if (remainder > 0) {
      71           0 :         numBranches++;
      72           0 :         if (remainder >= kMinChildren) {
      73           0 :             remainder = 0;
      74             :         } else {
      75           0 :             remainder = kMinChildren - remainder;
      76             :         }
      77             :     }
      78           0 :     int numStrips = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(numBranches) / aspectRatio));
      79           0 :     int numTiles  = SkScalarCeilToInt(SkIntToScalar(numBranches) / SkIntToScalar(numStrips));
      80           0 :     int currentBranch = 0;
      81           0 :     int nodes = 0;
      82           0 :     for (int i = 0; i < numStrips; ++i) {
      83           0 :         for (int j = 0; j < numTiles && currentBranch < branches; ++j) {
      84           0 :             int incrementBy = kMaxChildren;
      85           0 :             if (remainder != 0) {
      86           0 :                 if (remainder <= kMaxChildren - kMinChildren) {
      87           0 :                     incrementBy -= remainder;
      88           0 :                     remainder = 0;
      89             :                 } else {
      90           0 :                     incrementBy = kMinChildren;
      91           0 :                     remainder -= kMaxChildren - kMinChildren;
      92             :                 }
      93             :             }
      94           0 :             nodes++;
      95           0 :             currentBranch++;
      96           0 :             for (int k = 1; k < incrementBy && currentBranch < branches; ++k) {
      97           0 :                 currentBranch++;
      98             :             }
      99             :         }
     100             :     }
     101           0 :     return nodes + CountNodes(nodes, aspectRatio);
     102             : }
     103             : 
     104           0 : SkRTree::Branch SkRTree::bulkLoad(SkTDArray<Branch>* branches, int level) {
     105           0 :     if (branches->count() == 1) { // Only one branch.  It will be the root.
     106           0 :         return (*branches)[0];
     107             :     }
     108             : 
     109             :     // We might sort our branches here, but we expect Blink gives us a reasonable x,y order.
     110             :     // Skipping a call to sort (in Y) here resulted in a 17% win for recording with negligible
     111             :     // difference in playback speed.
     112           0 :     int numBranches = branches->count() / kMaxChildren;
     113           0 :     int remainder   = branches->count() % kMaxChildren;
     114           0 :     int newBranches = 0;
     115             : 
     116           0 :     if (remainder > 0) {
     117           0 :         ++numBranches;
     118             :         // If the remainder isn't enough to fill a node, we'll add fewer nodes to other branches.
     119           0 :         if (remainder >= kMinChildren) {
     120           0 :             remainder = 0;
     121             :         } else {
     122           0 :             remainder = kMinChildren - remainder;
     123             :         }
     124             :     }
     125             : 
     126           0 :     int numStrips = SkScalarCeilToInt(SkScalarSqrt(SkIntToScalar(numBranches) / fAspectRatio));
     127           0 :     int numTiles  = SkScalarCeilToInt(SkIntToScalar(numBranches) / SkIntToScalar(numStrips));
     128           0 :     int currentBranch = 0;
     129             : 
     130           0 :     for (int i = 0; i < numStrips; ++i) {
     131             :         // Might be worth sorting by X here too.
     132           0 :         for (int j = 0; j < numTiles && currentBranch < branches->count(); ++j) {
     133           0 :             int incrementBy = kMaxChildren;
     134           0 :             if (remainder != 0) {
     135             :                 // if need be, omit some nodes to make up for remainder
     136           0 :                 if (remainder <= kMaxChildren - kMinChildren) {
     137           0 :                     incrementBy -= remainder;
     138           0 :                     remainder = 0;
     139             :                 } else {
     140           0 :                     incrementBy = kMinChildren;
     141           0 :                     remainder -= kMaxChildren - kMinChildren;
     142             :                 }
     143             :             }
     144           0 :             Node* n = allocateNodeAtLevel(level);
     145           0 :             n->fNumChildren = 1;
     146           0 :             n->fChildren[0] = (*branches)[currentBranch];
     147             :             Branch b;
     148           0 :             b.fBounds = (*branches)[currentBranch].fBounds;
     149           0 :             b.fSubtree = n;
     150           0 :             ++currentBranch;
     151           0 :             for (int k = 1; k < incrementBy && currentBranch < branches->count(); ++k) {
     152           0 :                 b.fBounds.join((*branches)[currentBranch].fBounds);
     153           0 :                 n->fChildren[k] = (*branches)[currentBranch];
     154           0 :                 ++n->fNumChildren;
     155           0 :                 ++currentBranch;
     156             :             }
     157           0 :             (*branches)[newBranches] = b;
     158           0 :             ++newBranches;
     159             :         }
     160             :     }
     161           0 :     branches->setCount(newBranches);
     162           0 :     return this->bulkLoad(branches, level + 1);
     163             : }
     164             : 
     165           0 : void SkRTree::search(const SkRect& query, SkTDArray<int>* results) const {
     166           0 :     if (fCount > 0 && SkRect::Intersects(fRoot.fBounds, query)) {
     167           0 :         this->search(fRoot.fSubtree, query, results);
     168             :     }
     169           0 : }
     170             : 
     171           0 : void SkRTree::search(Node* node, const SkRect& query, SkTDArray<int>* results) const {
     172           0 :     for (int i = 0; i < node->fNumChildren; ++i) {
     173           0 :         if (SkRect::Intersects(node->fChildren[i].fBounds, query)) {
     174           0 :             if (0 == node->fLevel) {
     175           0 :                 results->push(node->fChildren[i].fOpIndex);
     176             :             } else {
     177           0 :                 this->search(node->fChildren[i].fSubtree, query, results);
     178             :             }
     179             :         }
     180             :     }
     181           0 : }
     182             : 
     183           0 : size_t SkRTree::bytesUsed() const {
     184           0 :     size_t byteCount = sizeof(SkRTree);
     185             : 
     186           0 :     byteCount += fNodes.reserved() * sizeof(Node);
     187             : 
     188           0 :     return byteCount;
     189             : }

Generated by: LCOV version 1.13