1 2 /* 3 * Copyright 2010 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11 #include "GrRectanizer.h" 12 #include "GrTBSearch.h" 13 14 #define MIN_HEIGHT_POW2 2 15 16 class GrRectanizerPow2 : public GrRectanizer { 17 public: 18 GrRectanizerPow2(int w, int h) : GrRectanizer(w, h) { 19 fNextStripY = 0; 20 fAreaSoFar = 0; 21 sk_bzero(fRows, sizeof(fRows)); 22 } 23 24 virtual ~GrRectanizerPow2() { 25 } 26 27 virtual void reset() { 28 fNextStripY = 0; 29 fAreaSoFar = 0; 30 sk_bzero(fRows, sizeof(fRows)); 31 } 32 33 virtual bool addRect(int w, int h, GrIPoint16* loc); 34 35 virtual float percentFull() const { 36 return fAreaSoFar / ((float)this->width() * this->height()); 37 } 38 39 virtual int stripToPurge(int height) const { return -1; } 40 virtual void purgeStripAtY(int yCoord) { } 41 42 /////////////////////////////////////////////////////////////////////////// 43 44 struct Row { 45 GrIPoint16 fLoc; 46 int fRowHeight; 47 48 bool canAddWidth(int width, int containerWidth) const { 49 return fLoc.fX + width <= containerWidth; 50 } 51 }; 52 53 Row fRows[16]; 54 55 static int HeightToRowIndex(int height) { 56 SkASSERT(height >= MIN_HEIGHT_POW2); 57 return 32 - SkCLZ(height - 1); 58 } 59 60 int fNextStripY; 61 int32_t fAreaSoFar; 62 63 bool canAddStrip(int height) const { 64 return fNextStripY + height <= this->height(); 65 } 66 67 void initRow(Row* row, int rowHeight) { 68 row->fLoc.set(0, fNextStripY); 69 row->fRowHeight = rowHeight; 70 fNextStripY += rowHeight; 71 } 72 }; 73 74 bool GrRectanizerPow2::addRect(int width, int height, GrIPoint16* loc) { 75 if ((unsigned)width > (unsigned)this->width() || 76 (unsigned)height > (unsigned)this->height()) { 77 return false; 78 } 79 80 int32_t area = width * height; 81 82 /* 83 We use bsearch, but there may be more than one row with the same height, 84 so we actually search for height-1, which can only be a pow2 itself if 85 height == 2. Thus we set a minimum height. 86 */ 87 height = GrNextPow2(height); 88 if (height < MIN_HEIGHT_POW2) { 89 height = MIN_HEIGHT_POW2; 90 } 91 92 Row* row = &fRows[HeightToRowIndex(height)]; 93 SkASSERT(row->fRowHeight == 0 || row->fRowHeight == height); 94 95 if (0 == row->fRowHeight) { 96 if (!this->canAddStrip(height)) { 97 return false; 98 } 99 this->initRow(row, height); 100 } else { 101 if (!row->canAddWidth(width, this->width())) { 102 if (!this->canAddStrip(height)) { 103 return false; 104 } 105 // that row is now "full", so retarget our Row record for 106 // another one 107 this->initRow(row, height); 108 } 109 } 110 111 SkASSERT(row->fRowHeight == height); 112 SkASSERT(row->canAddWidth(width, this->width())); 113 *loc = row->fLoc; 114 row->fLoc.fX += width; 115 116 SkASSERT(row->fLoc.fX <= this->width()); 117 SkASSERT(row->fLoc.fY <= this->height()); 118 SkASSERT(fNextStripY <= this->height()); 119 fAreaSoFar += area; 120 return true; 121 } 122 123 /////////////////////////////////////////////////////////////////////////////// 124 125 // factory is now in GrRectanizer_skyline.cpp 126 //GrRectanizer* GrRectanizer::Factory(int width, int height) { 127 // return SkNEW_ARGS(GrRectanizerPow2, (width, height)); 128 //} 129