40package com.jogamp.opengl.util.packrect;
52 private Object backingStore;
54 private static final float EXPANSION_FACTOR = 0.5f;
55 private static final float SHRINK_FACTOR = 0.3f;
57 private final int initialWidth;
58 private final int initialHeight;
60 private int maxWidth = -1;
61 private int maxHeight = -1;
63 static class RectHComparator
implements Comparator<Rect> {
65 public int compare(
final Rect r1,
final Rect r2) {
66 return r2.h() - r1.h();
70 public boolean equals(
final Object obj) {
74 private static final Comparator<Rect> rectHComparator =
new RectHComparator();
77 final int initialWidth,
78 final int initialHeight) {
79 this.manager = manager;
80 levels =
new LevelSet(initialWidth, initialHeight);
81 this.initialWidth = initialWidth;
82 this.initialHeight = initialHeight;
86 if (backingStore ==
null) {
98 public void setMaxSize(
final int maxWidth,
final int maxHeight) {
99 this.maxWidth = maxWidth;
100 this.maxHeight = maxHeight;
110 public void add(
final Rect rect)
throws RuntimeException {
112 if (backingStore ==
null)
115 int attemptNumber = 0;
116 boolean tryAgain =
false;
120 if (levels.
add(rect))
128 tryAgain = manager.
preExpand(rect, attemptNumber++);
135 throw new RuntimeException(
"BackingStoreManager does not support compaction or expansion, and didn't clear space for new rectangle");
146 public void remove(
final Rect rect) {
152 levels.
visit(visitor);
171 private void compactImpl(
final Rect cause) {
178 boolean done =
false;
179 int newWidth = levels.w();
180 int newHeight = levels.h();
182 int attemptNumber = 0;
183 boolean needAdditionFailureNotification =
false;
187 if (cause.w() > newWidth) {
188 newWidth = cause.w();
190 newHeight = (int) (newHeight * (1.0f + EXPANSION_FACTOR));
195 needAdditionFailureNotification =
false;
196 if (maxWidth > 0 && newWidth > maxWidth) {
198 needAdditionFailureNotification =
true;
200 if (maxHeight > 0 && newHeight > maxHeight) {
201 newHeight = maxHeight;
202 needAdditionFailureNotification =
true;
205 nextLevelSet =
new LevelSet(newWidth, newHeight);
208 final List<Rect> newRects =
new ArrayList<Rect>();
209 for (
final Iterator<Level> i1 = levels.
iterator(); i1.hasNext(); ) {
210 final Level level = i1.next();
211 for (
final Iterator<Rect> i2 = level.iterator(); i2.hasNext(); ) {
212 final Rect cur = i2.next();
213 final Rect newRect =
new Rect(0, 0, cur.w(), cur.h(),
null);
214 cur.setNextLocation(newRect);
216 newRect.setNextLocation(cur);
217 newRects.add(newRect);
222 Collections.sort(newRects, rectHComparator);
225 for (
final Iterator<Rect> iter = newRects.iterator(); iter.hasNext(); ) {
226 if (!nextLevelSet.
add(iter.next())) {
232 if (done && cause !=
null) {
234 if (nextLevelSet.
add(cause)) {
243 if (!done && needAdditionFailureNotification && cause !=
null) {
252 nextLevelSet.
getUsedHeight() < nextLevelSet.h() * SHRINK_FACTOR) {
253 int shrunkHeight = Math.max(initialHeight,
254 (
int) (nextLevelSet.
getUsedHeight() * (1.0f + EXPANSION_FACTOR)));
255 if (maxHeight > 0 && shrunkHeight > maxHeight) {
256 shrunkHeight = maxHeight;
264 nextLevelSet.
remove(cause);
274 for (
final Iterator<Level> i1 = levels.
iterator(); i1.hasNext(); ) {
275 final Level level = i1.next();
276 for (
final Iterator<Rect> i2 = level.iterator(); i2.hasNext(); ) {
277 final Rect cur = i2.next();
278 manager.
move(backingStore, cur,
279 newBackingStore, cur.getNextLocation());
284 manager.
endMovement(backingStore, newBackingStore);
288 backingStore = newBackingStore;
289 levels = nextLevelSet;
301 if (backingStore !=
null)
Manages a list of Levels; this is the core data structure contained within the RectanglePacker and en...
boolean add(final Rect rect)
Returns true if the given rectangle was successfully added to the LevelSet given its current dimensio...
void setHeight(final int height)
Sets the height of this LevelSet.
boolean remove(final Rect rect)
Removes the given Rect from this LevelSet.
void visit(final RectVisitor visitor)
Visits all Rects contained in this LevelSet.
float verticalFragmentationRatio()
Returns the vertical fragmentation ratio of this LevelSet.
void updateRectangleReferences()
Updates the references to the Rect objects in this LevelSet with the "next locations" of those Rects.
boolean compactAndAdd(final Rect rect, final Object backingStore, final BackingStoreManager manager)
Allocates the given Rectangle, performing compaction of a Level if necessary.
Iterator< Level > iterator()
int getUsedHeight()
Gets the used height of the levels in this LevelSet.
void clear()
Clears out all Levels stored in this LevelSet.
Represents a rectangular region on the backing store.
Packs rectangles supplied by the user (typically representing image regions) into a larger backing st...
void clear()
Clears all Rects contained in this RectanglePacker.
void dispose()
Disposes the backing store allocated by the BackingStoreManager.
void compact()
Forces a compaction cycle, which typically results in allocating a new backing store and copying all ...
void add(final Rect rect)
Decides upon an (x, y) position for the given rectangle (leaving its width and height unchanged) and ...
void setMaxSize(final int maxWidth, final int maxHeight)
Sets up a maximum width and height for the backing store.
RectanglePacker(final BackingStoreManager manager, final int initialWidth, final int initialHeight)
float verticalFragmentationRatio()
Returns the vertical fragmentation ratio of this RectanglePacker.
void visit(final RectVisitor visitor)
Visits all Rects contained in this RectanglePacker.
This interface must be implemented by the end user and is called in response to events like addition ...
boolean additionFailed(Rect cause, int attemptNumber)
Notification that addition of the given Rect failed because a maximum size was set in the RectanglePa...
boolean preExpand(Rect cause, int attemptNumber)
Notification that expansion of the backing store is about to be done due to addition of the given rec...
void beginMovement(Object oldBackingStore, Object newBackingStore)
Notification that movement is starting.
void endMovement(Object oldBackingStore, Object newBackingStore)
Notification that movement is ending.
Object allocateBackingStore(int w, int h)
void deleteBackingStore(Object backingStore)
boolean canCompact()
Indication whether this BackingStoreManager supports compaction; in other words, the allocation of a ...
void move(Object oldBackingStore, Rect oldLocation, Object newBackingStore, Rect newLocation)
Tells the manager to move the contents of the given rect from the old location on the old backing sto...
Iteration construct without exposing the internals of the RectanglePacker and without implementing a ...