|
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 //} |