1 #ifndef DALI_DEMO_GRID_FLAGS_H
2 #define DALI_DEMO_GRID_FLAGS_H
4 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
19 #include <dali/dali.h>
23 /** Controls the output of application logging. */
24 //#define DEBUG_PRINT_GRID_DIAGNOSTICS
31 * @brief A 2D grid of booleans, settable and gettable via integer (x,y) coordinates.
37 * Create grid of specified dimensions.
39 GridFlags(unsigned width, unsigned height)
40 : mCells(width * height),
45 #ifdef DEBUG_PRINT_GRID_DIAGNOSTICS
46 fprintf(stderr, "Grid created with dimensions: (%u, %u).\n", mWidth, mHeight);
50 void Set(const unsigned x, const unsigned y)
52 const unsigned index = CellIndex(x, y);
53 mCells[index] += 1u; ///< += To allow a debug check of the number of times a cell is set.
54 mHighestUsedRow = std::max(mHighestUsedRow, y);
57 bool Get(unsigned x, unsigned y) const
59 return mCells[CellIndex(x, y)] != 0;
62 unsigned GetHighestUsedRow() const
64 return mHighestUsedRow;
68 * @brief Try to find space in a grid of cells for the region requested.
69 * @return true if any region (not necessarily an exact match) was found, else false.
70 * @param[in] region The rectangular region requested
71 * @param[out] outCellX The X coordinate of the region allocated, if any.
72 * @param[out] outCellY The Y coordinate of the region allocated, if any.
73 * @param[out] outRegion The rectangle actually found: the lowest-Y exact match region
74 * or the largest area rectangular region no greater than the requested
75 * region in x or y. Undefined if false is returned.
77 bool AllocateRegion(const Vector2& region, unsigned& outCellX, unsigned& outCellY, Vector2& outRegion)
79 const unsigned regionWidth = (region.x + 0.5f);
80 const unsigned regionHeight = (region.y + 0.5f);
81 #ifdef DEBUG_PRINT_GRID_DIAGNOSTICS
82 fprintf(stderr, "Allocation requested for region (%u, %u). Result: ", regionWidth, regionHeight);
84 unsigned bestRegionWidth = 0;
85 unsigned bestRegionHeight = 0;
86 unsigned bestCellX = 0;
87 unsigned bestCellY = 0;
89 // Look for a non-set cell:
90 for(unsigned y = 0; y < mHeight; ++y)
92 for(unsigned x = 0; x < mWidth; ++x)
96 // Look for clear grid cells under the desired region:
98 const unsigned clampedRegionHeight = std::min(regionHeight, mHeight - y);
99 const unsigned clampedRegionWidth = std::min(regionWidth, mWidth - x);
100 const unsigned regionLimitY = y + clampedRegionHeight;
101 const unsigned regionLimitX = x + clampedRegionWidth;
103 for(unsigned regionY = y; regionY < regionLimitY; ++regionY)
105 for(unsigned regionX = x; regionX < regionLimitX; ++regionX)
107 if(Get(regionX, regionY))
109 // The region of clear cells is not big enough but remember it
110 // anyway in case there is no region that fits:
111 const unsigned clearRegionWidth = regionX - x;
112 const unsigned clearRegionHeight = (regionY + 1) - y;
113 if(clearRegionWidth * clearRegionHeight > bestRegionWidth * bestRegionHeight)
117 bestRegionWidth = clearRegionWidth;
118 bestRegionHeight = clearRegionHeight;
120 goto whole_region_not_found;
125 // Every cell in the region is clear so check if it is the best one yet:
126 if(clampedRegionWidth * clampedRegionHeight > bestRegionWidth * bestRegionHeight)
130 bestRegionWidth = clampedRegionWidth;
131 bestRegionHeight = clampedRegionHeight;
134 // If a big-enough region was found, end the search early and greedily allocate it:
135 if(clampedRegionHeight == regionHeight && clampedRegionWidth == regionWidth)
140 whole_region_not_found:
146 // Allocate and return the best cell region found:
148 if(bestRegionWidth == 0 || bestRegionHeight == 0)
150 #ifdef DEBUG_PRINT_GRID_DIAGNOSTICS
151 fputs("false.\n", stderr);
156 // Allocate the found region:
157 #ifdef DEBUG_PRINT_GRID_DIAGNOSTICS
158 fprintf(stderr, " - bestCellX = %u, bestCellY = %u, bestRegionWidth = %u, bestRegionHeight = %u - ", bestCellX, bestCellY, bestRegionWidth, bestRegionHeight);
160 for(unsigned y = bestCellY; y < bestCellY + bestRegionHeight; ++y)
162 for(unsigned x = bestCellX; x < bestCellX + bestRegionWidth; ++x)
168 outCellX = bestCellX;
169 outCellY = bestCellY;
170 outRegion = Vector2(bestRegionWidth, bestRegionHeight);
171 #ifdef DEBUG_PRINT_GRID_DIAGNOSTICS
172 fputs("true.\n", stderr);
177 /** @return True if every cell was set one or zero times, else false. */
178 bool DebugCheckGridValid()
180 for(unsigned cell = 0; cell < mWidth * mHeight; ++cell)
191 unsigned CellIndex(unsigned x, unsigned y) const
193 const unsigned offset = mWidth * y + x;
194 assert(offset < mCells.size() && "Out of range access to grid.");
198 std::vector<unsigned char> mCells;
199 const unsigned mWidth;
200 const unsigned mHeight;
201 unsigned mHighestUsedRow;
208 #endif // DALI_DEMO_GRID_FLAGS_H