1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkTileGrid.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,133 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2012 Google Inc. 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 +#include "SkTileGrid.h" 1.13 + 1.14 +SkTileGrid::SkTileGrid(int xTileCount, int yTileCount, const SkTileGridPicture::TileGridInfo& info, 1.15 + SkTileGridNextDatumFunctionPtr nextDatumFunction) 1.16 +{ 1.17 + fXTileCount = xTileCount; 1.18 + fYTileCount = yTileCount; 1.19 + fInfo = info; 1.20 + // Margin is offset by 1 as a provision for AA and 1.21 + // to cancel-out the outset applied by getClipDeviceBounds. 1.22 + fInfo.fMargin.fHeight++; 1.23 + fInfo.fMargin.fWidth++; 1.24 + fTileCount = fXTileCount * fYTileCount; 1.25 + fInsertionCount = 0; 1.26 + fGridBounds = SkIRect::MakeXYWH(0, 0, fInfo.fTileInterval.width() * fXTileCount, 1.27 + fInfo.fTileInterval.height() * fYTileCount); 1.28 + fNextDatumFunction = nextDatumFunction; 1.29 + fTileData = SkNEW_ARRAY(SkTDArray<void *>, fTileCount); 1.30 +} 1.31 + 1.32 +SkTileGrid::~SkTileGrid() { 1.33 + SkDELETE_ARRAY(fTileData); 1.34 +} 1.35 + 1.36 +int SkTileGrid::tileCount(int x, int y) { 1.37 + return this->tile(x, y).count(); 1.38 +} 1.39 + 1.40 +SkTDArray<void *>& SkTileGrid::tile(int x, int y) { 1.41 + return fTileData[y * fXTileCount + x]; 1.42 +} 1.43 + 1.44 +void SkTileGrid::insert(void* data, const SkIRect& bounds, bool) { 1.45 + SkASSERT(!bounds.isEmpty()); 1.46 + SkIRect dilatedBounds = bounds; 1.47 + dilatedBounds.outset(fInfo.fMargin.width(), fInfo.fMargin.height()); 1.48 + dilatedBounds.offset(fInfo.fOffset); 1.49 + if (!SkIRect::Intersects(dilatedBounds, fGridBounds)) { 1.50 + return; 1.51 + } 1.52 + 1.53 + // Note: SkIRects are non-inclusive of the right() column and bottom() row, 1.54 + // hence the "-1"s in the computations of maxTileX and maxTileY. 1.55 + int minTileX = SkMax32(SkMin32(dilatedBounds.left() / fInfo.fTileInterval.width(), 1.56 + fXTileCount - 1), 0); 1.57 + int maxTileX = SkMax32(SkMin32((dilatedBounds.right() - 1) / fInfo.fTileInterval.width(), 1.58 + fXTileCount - 1), 0); 1.59 + int minTileY = SkMax32(SkMin32(dilatedBounds.top() / fInfo.fTileInterval.height(), 1.60 + fYTileCount -1), 0); 1.61 + int maxTileY = SkMax32(SkMin32((dilatedBounds.bottom() -1) / fInfo.fTileInterval.height(), 1.62 + fYTileCount -1), 0); 1.63 + 1.64 + for (int x = minTileX; x <= maxTileX; x++) { 1.65 + for (int y = minTileY; y <= maxTileY; y++) { 1.66 + this->tile(x, y).push(data); 1.67 + } 1.68 + } 1.69 + fInsertionCount++; 1.70 +} 1.71 + 1.72 +void SkTileGrid::search(const SkIRect& query, SkTDArray<void*>* results) { 1.73 + SkIRect adjustedQuery = query; 1.74 + // The inset is to counteract the outset that was applied in 'insert' 1.75 + // The outset/inset is to optimize for lookups of size 1.76 + // 'tileInterval + 2 * margin' that are aligned with the tile grid. 1.77 + adjustedQuery.inset(fInfo.fMargin.width(), fInfo.fMargin.height()); 1.78 + adjustedQuery.offset(fInfo.fOffset); 1.79 + adjustedQuery.sort(); // in case the inset inverted the rectangle 1.80 + // Convert the query rectangle from device coordinates to tile coordinates 1.81 + // by rounding outwards to the nearest tile boundary so that the resulting tile 1.82 + // region includes the query rectangle. (using truncating division to "floor") 1.83 + int tileStartX = adjustedQuery.left() / fInfo.fTileInterval.width(); 1.84 + int tileEndX = (adjustedQuery.right() + fInfo.fTileInterval.width() - 1) / 1.85 + fInfo.fTileInterval.width(); 1.86 + int tileStartY = adjustedQuery.top() / fInfo.fTileInterval.height(); 1.87 + int tileEndY = (adjustedQuery.bottom() + fInfo.fTileInterval.height() - 1) / 1.88 + fInfo.fTileInterval.height(); 1.89 + 1.90 + tileStartX = SkPin32(tileStartX, 0, fXTileCount - 1); 1.91 + tileEndX = SkPin32(tileEndX, tileStartX+1, fXTileCount); 1.92 + tileStartY = SkPin32(tileStartY, 0, fYTileCount - 1); 1.93 + tileEndY = SkPin32(tileEndY, tileStartY+1, fYTileCount); 1.94 + 1.95 + int queryTileCount = (tileEndX - tileStartX) * (tileEndY - tileStartY); 1.96 + SkASSERT(queryTileCount); 1.97 + if (queryTileCount == 1) { 1.98 + *results = this->tile(tileStartX, tileStartY); 1.99 + } else { 1.100 + results->reset(); 1.101 + SkAutoSTArray<kStackAllocationTileCount, int> curPositions(queryTileCount); 1.102 + SkAutoSTArray<kStackAllocationTileCount, SkTDArray<void *>*> storage(queryTileCount); 1.103 + SkTDArray<void *>** tileRange = storage.get(); 1.104 + int tile = 0; 1.105 + for (int x = tileStartX; x < tileEndX; ++x) { 1.106 + for (int y = tileStartY; y < tileEndY; ++y) { 1.107 + tileRange[tile] = &this->tile(x, y); 1.108 + curPositions[tile] = tileRange[tile]->count() ? 0 : kTileFinished; 1.109 + ++tile; 1.110 + } 1.111 + } 1.112 + void *nextElement; 1.113 + while(NULL != (nextElement = fNextDatumFunction(tileRange, curPositions))) { 1.114 + results->push(nextElement); 1.115 + } 1.116 + } 1.117 +} 1.118 + 1.119 +void SkTileGrid::clear() { 1.120 + for (int i = 0; i < fTileCount; i++) { 1.121 + fTileData[i].reset(); 1.122 + } 1.123 +} 1.124 + 1.125 +int SkTileGrid::getCount() const { 1.126 + return fInsertionCount; 1.127 +} 1.128 + 1.129 +void SkTileGrid::rewindInserts() { 1.130 + SkASSERT(fClient); 1.131 + for (int i = 0; i < fTileCount; ++i) { 1.132 + while (!fTileData[i].isEmpty() && fClient->shouldRewind(fTileData[i].top())) { 1.133 + fTileData[i].pop(); 1.134 + } 1.135 + } 1.136 +}