• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2     Copyright 2010 Google Inc.
3 
4     Licensed under the Apache License, Version 2.0 (the "License");
5     you may not use this file except in compliance with the License.
6     You may obtain a copy of the License at
7 
8          http://www.apache.org/licenses/LICENSE-2.0
9 
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15  */
16 
17 
18 #include "GrRectanizer.h"
19 #include "GrTBSearch.h"
20 
21 #define MIN_HEIGHT_POW2     2
22 
23 class GrRectanizerFIFO : public GrRectanizer {
24 public:
GrRectanizerFIFO(int w,int h)25     GrRectanizerFIFO(int w, int h) : GrRectanizer(w, h) {
26         fNextStripY = 0;
27         fAreaSoFar = 0;
28         Gr_bzero(fRows, sizeof(fRows));
29     }
30 
~GrRectanizerFIFO()31     virtual ~GrRectanizerFIFO() {
32     }
33 
34     virtual bool addRect(int w, int h, GrIPoint16* loc);
35 
percentFull() const36     virtual float percentFull() const {
37         return fAreaSoFar / ((float)this->width() * this->height());
38     }
39 
stripToPurge(int height) const40     virtual int stripToPurge(int height) const { return -1; }
purgeStripAtY(int yCoord)41     virtual void purgeStripAtY(int yCoord) { }
42 
43     ///////////////////////////////////////////////////////////////////////////
44 
45     struct Row {
46         GrIPoint16  fLoc;
47         int         fRowHeight;
48 
canAddWidthGrRectanizerFIFO::Row49         bool canAddWidth(int width, int containerWidth) const {
50             return fLoc.fX + width <= containerWidth;
51         }
52     };
53 
54     Row fRows[16];
55 
HeightToRowIndex(int height)56     static int HeightToRowIndex(int height) {
57         GrAssert(height >= MIN_HEIGHT_POW2);
58         return 32 - Gr_clz(height - 1);
59     }
60 
61     int fNextStripY;
62     int32_t fAreaSoFar;
63 
canAddStrip(int height) const64     bool canAddStrip(int height) const {
65         return fNextStripY + height <= this->height();
66     }
67 
initRow(Row * row,int rowHeight)68     void initRow(Row* row, int rowHeight) {
69         row->fLoc.set(0, fNextStripY);
70         row->fRowHeight = rowHeight;
71         fNextStripY += rowHeight;
72     }
73 };
74 
addRect(int width,int height,GrIPoint16 * loc)75 bool GrRectanizerFIFO::addRect(int width, int height, GrIPoint16* loc) {
76     if ((unsigned)width > (unsigned)this->width() ||
77         (unsigned)height > (unsigned)this->height()) {
78         return false;
79     }
80 
81     int32_t area = width * height;
82 
83     /*
84      We use bsearch, but there may be more than one row with the same height,
85      so we actually search for height-1, which can only be a pow2 itself if
86      height == 2. Thus we set a minimum height.
87      */
88     height = GrNextPow2(height);
89     if (height < MIN_HEIGHT_POW2) {
90         height = MIN_HEIGHT_POW2;
91     }
92 
93     Row* row = &fRows[HeightToRowIndex(height)];
94     GrAssert(row->fRowHeight == 0 || row->fRowHeight == height);
95 
96     if (0 == row->fRowHeight) {
97         if (!this->canAddStrip(height)) {
98             return false;
99         }
100         this->initRow(row, height);
101     } else {
102         if (!row->canAddWidth(width, this->width())) {
103             if (!this->canAddStrip(height)) {
104                 return false;
105             }
106             // that row is now "full", so retarget our Row record for
107             // another one
108             this->initRow(row, height);
109         }
110     }
111 
112     GrAssert(row->fRowHeight == height);
113     GrAssert(row->canAddWidth(width, this->width()));
114     *loc = row->fLoc;
115     row->fLoc.fX += width;
116 
117     GrAssert(row->fLoc.fX <= this->width());
118     GrAssert(row->fLoc.fY <= this->height());
119     GrAssert(fNextStripY <= this->height());
120     fAreaSoFar += area;
121     return true;
122 }
123 
124 ///////////////////////////////////////////////////////////////////////////////
125 
Factory(int width,int height)126 GrRectanizer* GrRectanizer::Factory(int width, int height) {
127     return new GrRectanizerFIFO(width, height);
128 }
129 
130 
131