| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| package flashx.textLayout.compose |
| { |
| import flash.geom.Matrix; |
| import flash.geom.Point; |
| import flash.geom.Rectangle; |
| |
| import flashx.textLayout.container.ContainerController; |
| import flashx.textLayout.container.IFloatController; |
| import flashx.textLayout.container.IWrapManager; |
| import flashx.textLayout.debug.assert; |
| import flashx.textLayout.formats.BlockProgression; |
| |
| import flashx.textLayout.tlf_internal; |
| |
| use namespace tlf_internal; |
| /** The area inside a text container is sub-divided into smaller areas available for |
| * text layout. These smaller areas within the container are called Parcels. The |
| * ParcelList manages the parcel associated with a TextFlow during composition. |
| * |
| * A container will always have at least one parcel, which corresponds to the container's |
| * bounding box. If the container has more than one column, each column appears as |
| * a parcel in the parcel list. If the container has wrap applied, the area around the |
| * wrap that is available for layout is divided into rectangular-shaped parcels. |
| * Lastly, parcels may be created during composition for use by flow elements that require |
| * layout within a specific geometry that may not be the same as the columns: for instance, |
| * a straddle head, a table, or a sidehead. |
| */ |
| internal class LayoutParcelList extends ParcelList |
| { |
| /** This is a list of the wraps, or parcels that are NOT available for text layout. */ |
| private var wraps:Array; /* of Rectangle */ |
| |
| /** Inlines can extend across columns, so we have a separate parcel list |
| that is independent of columns (just has container bboxes) used for |
| creating new parcels that can extend across columns. */ |
| // private var inlineWrap:LayoutParcelList; |
| |
| /** minimum allowable width of a line */ |
| private static const MIN_WIDTH:Number = 40; |
| |
| // a single parcellist that is checked out and checked in |
| static private var _sharedLayoutParcelList:LayoutParcelList; |
| |
| /** @private */ |
| static tlf_internal function getLayoutParcelList():LayoutParcelList |
| { |
| var rslt:LayoutParcelList = _sharedLayoutParcelList ? _sharedLayoutParcelList : new LayoutParcelList(); |
| _sharedLayoutParcelList = null; |
| return rslt; |
| } |
| |
| /** @private */ |
| static tlf_internal function releaseLayoutParcelList(list:IParcelList):void |
| { |
| if (_sharedLayoutParcelList == null) |
| { |
| _sharedLayoutParcelList = list as LayoutParcelList; |
| if (_sharedLayoutParcelList) |
| _sharedLayoutParcelList.releaseAnyReferences(); |
| } |
| } |
| |
| /** Constructor */ |
| public function LayoutParcelList() |
| { |
| super(); |
| } |
| |
| /** prevent any leaks. @private */ |
| tlf_internal override function releaseAnyReferences():void |
| { |
| super.releaseAnyReferences(); |
| wraps = null; |
| } |
| |
| override protected function addOneControllerToParcelList(controllerToInitialize:ContainerController):void |
| { |
| super.addOneControllerToParcelList(controllerToInitialize); |
| if (controllerToInitialize is IFloatController) |
| { |
| if (IFloatController(controllerToInitialize).wraps) |
| this.wraps = IFloatController(controllerToInitialize).wraps.wraps; |
| for each (var wrapExclude:Rectangle in wraps) |
| addWrap(wrapExclude, controllerToInitialize, false /* wrap around the sides */); |
| } |
| } |
| |
| private function isNextAdjacent():Boolean |
| { |
| // trace("LPL: isNextAdjacent"); |
| CONFIG::debug { assert(_currentParcelIndex >= 0 && _currentParcelIndex < numParcels, "invalid _currentParcelIndex in ParcelList"); } |
| if (_currentParcelIndex + 1 >= numParcels) |
| return false; |
| var nextParcel:Parcel = getParcelAtIndex(_currentParcelIndex + 1); |
| if(_blockProgression != BlockProgression.RL) |
| { |
| if (_currentParcel.bottom != nextParcel.top || _currentParcel.left > nextParcel.right) |
| return false; |
| } |
| else |
| { |
| if(_currentParcel.left != nextParcel.right || _currentParcel.top > nextParcel.bottom) |
| return false; |
| } |
| return true; |
| } |
| |
| private function getBBox(controller:ContainerController):Rectangle |
| { |
| // trace("LPL: getBBox"); |
| var bbox:Rectangle = null; |
| for (var idx:int = 0; idx < numParcels; idx++) |
| { |
| var p:Parcel = getParcelAtIndex(idx); |
| if (p.controller == controller) |
| { |
| if (!bbox) |
| bbox = p.clone(); |
| else |
| bbox = bbox.union(p); |
| } |
| } |
| return bbox; |
| } |
| |
| private function intersects(r:Rectangle, rectArray:Array):Boolean |
| // true if r intersects any of the rectangles in rectArray |
| { |
| // trace("LPL: getBBox"); |
| if (rectArray) |
| { |
| for each (var i:Rectangle in rectArray) |
| { |
| if (i.intersects(r)) |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** @private */ |
| override public function createParcel(parcel:Rectangle, blockProgression:String, verticalJump:Boolean):Boolean |
| // If we can get the requested parcel to fit, create it in the parcels list |
| { |
| // trace("LPL: createParcel"); |
| // trace("createParcel start", parcel.toString()); |
| // traceOut(); |
| |
| var fitRect:Rectangle = new Rectangle(); |
| do { |
| getLineSlug(fitRect,parcel.height); |
| if (!fitRect || atEnd()) // Can't find contiguous vertical space for the parcel |
| return false; |
| else |
| { |
| if (blockProgression == BlockProgression.TB) |
| parcel.offset(0, fitRect.top - parcel.top); // parcel location may have been adjusted by getLineSlug |
| else |
| parcel.offset(fitRect.left - parcel.left, 0); // parcel location may have been adjusted by getLineSlug |
| |
| if (fitRect.width >= parcel.width) |
| break; // found enough vertical & horizontal space |
| |
| // Found vertical space, but not enough horizontal. |
| // It could be that parcel would fit across contiguous columns. Check for a wrap. |
| // Check that it fits within the bounding box for the container, |
| // and doesn't intersect any wraps |
| var bbox:Rectangle = getBBox(_currentParcel.controller); |
| if (bbox.containsRect(parcel) && !intersects(parcel, wraps)) |
| break; |
| |
| next(); // keep looking in other parcels |
| |
| if (_currentParcelIndex >= numParcels) |
| return false; // hit the end: space not found |
| } |
| } while (fitRect.width < parcel.width); |
| |
| // Create a new parcel, and insert it in the correct location in the parcels array |
| var targetController:ContainerController = _currentParcel.controller; |
| addWrap(parcel, targetController, verticalJump /* jumpOver */); |
| for (var l:int = 0; l < numParcels; l++) |
| { |
| var testParcel:Parcel = getParcelAtIndex(l); |
| if (testParcel.top > parcel.top && |
| !((testParcel.left > parcel.right) || (testParcel.right < parcel.left))) |
| { |
| if (testParcel.controller == targetController) |
| break; |
| } |
| } |
| var splitParcel:Parcel = getParcelAtIndex(l); |
| var splitCoverage:int = splitParcel.columnCoverage; |
| |
| // clear top of column splitParcel is not that anymore |
| splitParcel.columnCoverage = splitCoverage & ~Parcel.TOP_OF_COLUMN; |
| // we're inserting before so its bot_of_column - we aren't |
| insertParcel(l,new Parcel(parcel.x, parcel.y, parcel.width, parcel.height, targetController, splitParcel.column, splitCoverage&~Parcel.BOT_OF_COLUMN)); |
| |
| // Set the current parcel to be the one we just added |
| _currentParcelIndex = l; |
| _currentParcel = getParcelAtIndex(l); |
| |
| // trace("createParcel done"); |
| // traceOut(); |
| |
| return true; |
| } |
| |
| /** @private */ |
| override public function getLineSlug(slugRect:Rectangle,height:Number, minWidth:Number = 0):Boolean |
| { |
| return (_currentParcelIndex < numParcels) && getWidthInternal(slugRect, height, minWidth); |
| } |
| |
| /**Helper function for getLineSlug, used internally. Similar to getWidth, but |
| * although it allows a line to extend across parcels, if necessary, the line |
| * will always start in the current parce. If a line does not fit starting |
| * from the current parcel, this function (unlike getWidth) will return |
| * 0 instead of changing the parcel. |
| * @param height amount of contiguous vertical space that must be available |
| * @param minWidth amount of contiguous horizontal space that must be available |
| * @return amount of contiguous horizontal space actually available |
| */ |
| private function getWidthInternal(slugRect:Rectangle, height:Number, minWidth:Number):Boolean |
| { |
| // trace("LPL: getWidthInternal"); |
| CONFIG::debug { assert(_currentParcelIndex >= 0 && _currentParcelIndex < numParcels, "invalid position in ParcelList"); } |
| |
| // See if it fits in the current parcel |
| var tileWidth:Number = getComposeWidth(_currentParcel); |
| if (tileWidth <= minWidth) |
| return false; |
| var requiredHeight:Number = currentParcel.fitAny ? 1 : height; |
| if (currentParcel.composeToPosition || _totalDepth + requiredHeight <= getComposeHeight(_currentParcel)) |
| { |
| if (this._blockProgression != BlockProgression.RL) |
| { |
| slugRect.x = left; |
| slugRect.y = _currentParcel.top + _totalDepth; |
| slugRect.width = tileWidth; |
| slugRect.height = height; |
| } |
| else |
| { |
| slugRect.x = left; |
| slugRect.y = _currentParcel.top; |
| slugRect.width = _currentParcel.width-_totalDepth; |
| slugRect.height = tileWidth; |
| } |
| return true; |
| } |
| |
| // This tile won't fit in the parcel. Look at the next parcel(s) that are adejacent, |
| // as many as are required fit the tile. The width of the tile will be the minimum |
| // of this list. If the width of the tile is less than the minimum specified by the |
| // caller, or if there aren't enough adejacent parcels to fit the tile, |
| // return 0 to indicate the tile doesn't fit in the parcel. The client code can try |
| // again on the next parcel. |
| var offset:Number = getComposeHeight(_currentParcel) - _totalDepth; |
| var heightRemaining:Number = height - offset; |
| var leftEdge:Number = _currentParcel.left; |
| var rightEdge:Number = _currentParcel.right; |
| var topEdge:Number = _currentParcel.top; |
| if (_blockProgression == BlockProgression.RL) |
| rightEdge -= _totalDepth; |
| else |
| topEdge += _totalDepth; |
| do |
| { |
| // Next parcel isn't adejacent. We can't fit the tile. |
| if (!isNextAdjacent()) |
| return false; |
| next(); |
| tileWidth = Math.min(tileWidth, getComposeWidth(_currentParcel)); |
| if (tileWidth <= minWidth) |
| return false; // try again on next tile |
| var newDepth:Number; |
| if (_blockProgression == BlockProgression.RL) |
| { |
| topEdge = Math.max(topEdge, _currentParcel.top); |
| newDepth = -(height - heightRemaining); |
| heightRemaining -= Math.min(heightRemaining, _currentParcel.width); |
| } |
| else |
| { |
| leftEdge = Math.max(leftEdge, _currentParcel.left); |
| newDepth = -(height - heightRemaining); |
| heightRemaining -= Math.min(heightRemaining, _currentParcel.height); |
| } |
| } while (heightRemaining > 0) |
| |
| _totalDepth = newDepth; |
| _hasContent = true; |
| |
| slugRect.x = leftEdge; |
| slugRect.y = topEdge; |
| if (_blockProgression == BlockProgression.RL) |
| { |
| slugRect.x = rightEdge - height; |
| slugRect.width = height; |
| slugRect.height = tileWidth; |
| } |
| else |
| { |
| slugRect.width = tileWidth; |
| slugRect.height = height; |
| } |
| return true; |
| } |
| |
| private function getSlugParcel(parcel:Rectangle, blockProgression:String):Rectangle |
| { |
| var fitRect:Rectangle = new Rectangle(); |
| do { |
| getLineSlug(fitRect,parcel.height); |
| if (!fitRect || atEnd()) // Can't find contiguous vertical space for the parcel |
| return null; |
| else |
| { |
| if (blockProgression == BlockProgression.TB) |
| parcel.offset(0, fitRect.top - parcel.top); // parcel location may have been adjusted by getLineSlug |
| else |
| parcel.offset(fitRect.right - parcel.right, 0); // parcel location may have been adjusted by getLineSlug |
| |
| if (fitRect.width >= parcel.width) |
| break; // found enough vertical & horizontal space |
| |
| // Found vertical space, but not enough horizontal. |
| // It could be that parcel would fit across contiguous columns. Check for a wrap. |
| // Check that it fits within the bounding box for the container, |
| // and doesn't intersect any wraps |
| var bbox:Rectangle = getBBox(_currentParcel.controller); |
| if (bbox.containsRect(parcel) && !intersects(parcel, wraps)) |
| break; |
| |
| next(); // keep looking in other parcels |
| |
| if (_currentParcelIndex >= numParcels) |
| return null; // hit the end: space not found |
| } |
| } while (fitRect.width < parcel.width); |
| return parcel; |
| } |
| |
| public const NONE:String = "none"; // don't wrap -- allow overlap |
| public const LEFT:String = "left"; // allow text to the left |
| public const RIGHT:String = "right"; // allow text to the right |
| // public const BIGGEST:String = "biggest"; // wrap either left or right, whichever is a bigger space - not yet supported |
| // public const BOTH:String = "both"; // "allow text on left and right - BUT jump-overs not supported |
| |
| /** @private */ |
| override public function createParcelExperimental(parcel:Rectangle, wrapType:String) : Boolean |
| { |
| // trace("LPL: createParcel"); |
| // trace("createParcel start", parcel.toString()); |
| // traceOut(); |
| parcel = getSlugParcel(parcel, _blockProgression); |
| if (!parcel) |
| return false; // doesn't fit |
| |
| |
| // trace("before"); |
| // traceOut(); |
| // trace("parcel", parcel.toString()); |
| |
| var p:Parcel = getParcelAtIndex(0); |
| var rotationPoint:Point = new Point(p.left, p.top); |
| if (_blockProgression == BlockProgression.RL) |
| { |
| // rotate parcels to TB orientation |
| for (var i:int = 0; i < numParcels; i++) |
| { |
| p = getParcelAtIndex(i); |
| p.replaceBounds(transformRect(p, rotationPoint, true)); |
| } |
| parcel = transformRect(parcel, rotationPoint, true); |
| } |
| |
| // Create a new parcel, and insert it in the correct location in the parcels array |
| var targetController:ContainerController = _currentParcel.controller; |
| addWrapExperimental(parcel, targetController, wrapType); |
| _currentParcelIndex = numParcels; |
| _currentParcel = null; |
| for (var l:int = 0; l < numParcels; l++) |
| { |
| p = getParcelAtIndex(l); |
| if (p.equals(parcel)) |
| { |
| _currentParcelIndex = l; |
| _currentParcel = p; |
| break; |
| } |
| } |
| CONFIG::debug { assert (_currentParcelIndex != numParcels, "New parcel not current!"); } |
| |
| if (_blockProgression == BlockProgression.RL) |
| { |
| // rotate back |
| parcel = transformRect(parcel, rotationPoint, false); |
| for (i = 0; i < numParcels; i++) |
| { |
| p = getParcelAtIndex(i); |
| p.replaceBounds(transformRect(p, rotationPoint, false)); |
| } |
| } |
| |
| // trace("createParcel done"); |
| // traceOut(); |
| |
| return true; |
| } |
| |
| private function transformRect(r:Rectangle, rotationPoint:Point, up:Boolean):Rectangle |
| { |
| var dx:Number = r.x - rotationPoint.x; |
| var dy:Number = (up ? r.y : r.bottom) - rotationPoint.y; |
| if (up) |
| return new Rectangle((rotationPoint.x + dy), (rotationPoint.y - dx) - r.width, r.height, r.width); |
| return new Rectangle((rotationPoint.x - dy), (rotationPoint.y + dx), r.height, r.width); |
| } |
| |
| |
| private function addWrapExperimental(wrap:Rectangle, controller:ContainerController, wrapType:String):void |
| { |
| // trace("addWrap", wrap.toString()); |
| // traceOut(); |
| |
| // Subtracts the wrap from the space available for laying out text. |
| var insertWrap:Boolean = true; |
| var newparcels:Array = new Array(); /* of Parcel */ |
| for (var idx:int = 0; idx < numParcels; idx++) |
| { |
| var p:Parcel = getParcelAtIndex(idx); |
| if (p.controller == controller && wrap.intersects(p)) |
| { |
| // If the wrap intersects the area, return the unintersected |
| // part of the area as an array of parcels that replaces |
| // the area. If the area is entirely contained within the wrap, |
| // this will remove the area. |
| // |
| // If the wrap appears inside the area, pick the larger side |
| // to be in the area, and let the smaller side drop out as if |
| // it were part of the wrap. Note that this means we do not |
| // support jump-overs. |
| unintersectExperimental(newparcels, p, wrap, wrapType, insertWrap); |
| insertWrap = false; |
| } |
| else |
| newparcels.push(p); |
| } |
| |
| |
| // Keep track of the number of wraps per text frame. It is needed to for vertical alignment. |
| if (controller.container is IFloatController) |
| IFloatController(controller.container).numWraps++; |
| |
| parcels = newparcels; |
| CONFIG::debug { validate(); } |
| // trace("after"); |
| // traceOut(); |
| } |
| |
| private function unintersectExperimental(result:Array, parcel:Parcel, wrap:Rectangle, wrapType:String, insertWrap:Boolean):void |
| { |
| var area:Rectangle = parcel; |
| // trace("LPL: unintersect"); |
| var columnCoverage:int = parcel.columnCoverage; |
| |
| // Return the unintersected part of the area that wrap does not |
| // intersect as an array of parcels |
| var r:Rectangle = area.intersection(wrap); |
| |
| // split into zero, one, two or three chunks |
| var addTopParcel:Boolean = r.top > area.top; |
| var addMidParcel:Boolean = ((r.left - area.left > Math.max(area.right - r.right, MIN_WIDTH)) || (area.right > r.right && area.right - r.right > MIN_WIDTH)); |
| var addBotParcel:Boolean = area.bottom > r.bottom; |
| |
| var newCoverage:int; // scratch for computing coverage |
| |
| var parcelRect:Rectangle; |
| |
| // Space above the intersection |
| if (addTopParcel) |
| { |
| newCoverage = columnCoverage; |
| if (addBotParcel || addMidParcel) |
| newCoverage &= ~Parcel.BOT_OF_COLUMN; |
| columnCoverage &= ~Parcel.TOP_OF_COLUMN; |
| |
| result.push(new Parcel(area.left, area.top, area.width, r.top - area.top, parcel.controller, parcel.column, newCoverage)); |
| } |
| |
| newCoverage = columnCoverage; |
| if (addBotParcel) |
| newCoverage &= ~Parcel.BOT_OF_COLUMN; |
| columnCoverage &= ~Parcel.TOP_OF_COLUMN; |
| |
| // Push our parcel |
| if (insertWrap) |
| result.push(new Parcel(wrap.x, wrap.y, wrap.width, wrap.height, parcel.controller, parcel.column, newCoverage)); |
| |
| // Allocate space beside the parcel, depending on wrapType |
| if (wrapType == LEFT) |
| { |
| if (r.left - area.left > MIN_WIDTH) |
| result.push(new Parcel(area.left, r.top, r.left - area.left, r.height, parcel.controller, parcel.column, newCoverage)); |
| } |
| if (wrapType == RIGHT) |
| { |
| if (area.right - r.right > MIN_WIDTH) |
| result.push(new Parcel(r.right, r.top, area.right - r.right, r.height, parcel.controller, parcel.column, newCoverage)); |
| } |
| |
| // Space along the bottom |
| if (addBotParcel) |
| result.push(new Parcel(area.left, r.bottom, area.width, area.bottom - r.bottom, parcel.controller, parcel.column, columnCoverage)); |
| } |
| |
| private function addWrap(wrap:Rectangle, controller:ContainerController, verticalJump:Boolean):void |
| { |
| // trace("LPL: addWrap"); |
| // trace("addWrap", wrap.toString()); |
| // trace("before"); |
| // traceOut(); |
| |
| // Subtracts the wrap from the space available for laying out text. |
| var newparcels:Array = new Array(); /* of Parcel */ |
| for (var idx:int = 0; idx < numParcels; idx++) |
| { |
| var p:Parcel = getParcelAtIndex(idx); |
| if (p.controller == controller && wrap.intersects(p)) |
| { |
| // If the wrap intersects the area, return the unintersected |
| // part of the area as an array of parcels that replaces |
| // the area. If the area is entirely contained within the wrap, |
| // this will remove the area. |
| // |
| // If the wrap appears inside the area, pick the larger side |
| // to be in the area, and let the smaller side drop out as if |
| // it were part of the wrap. Note that this means we do not |
| // support jump-overs. |
| unintersect(newparcels, p, wrap, verticalJump); |
| // verticalJump = false; // Yuck! Turning off multiple insertions |
| } |
| else |
| newparcels.push(p); |
| } |
| |
| |
| // Keep track of the number of wraps per text frame. It is needed to for vertical alignment. |
| if (controller.container is IFloatController) |
| IFloatController(controller.container).numWraps++; |
| |
| parcels = newparcels; |
| CONFIG::debug { validate(); } |
| // trace("after"); |
| // traceOut(); |
| } |
| |
| private function unintersect(result:Array, parcel:Parcel, wrap:Rectangle, verticalJump:Boolean):void |
| { |
| // trace("LPL: unintersect"); |
| var area:Rectangle = parcel; |
| var columnCoverage:int = parcel.columnCoverage; |
| |
| // Return the unintersected part of the area that wrap does not |
| // intersect as an array of parcels |
| var r:Rectangle = area.intersection(wrap); |
| |
| // split into zero, one, two or three chunks |
| var addTopParcel:Boolean = r.top > area.top; |
| var addMidParcel:Boolean = !verticalJump && ((r.left - area.left > Math.max(area.right - r.right, MIN_WIDTH)) || (area.right > r.right && area.right - r.right > MIN_WIDTH)); |
| var addBotParcel:Boolean = area.bottom > r.bottom; |
| |
| var newCoverage:int; // scratch for computing coverage |
| |
| // Space above the intersection |
| if (addTopParcel) |
| { |
| newCoverage = columnCoverage; |
| if (addBotParcel || addMidParcel) |
| newCoverage &= ~Parcel.BOT_OF_COLUMN; |
| columnCoverage &= ~Parcel.TOP_OF_COLUMN; |
| |
| result.push(new Parcel(area.left, area.top, area.width, r.top - area.top, parcel.controller, parcel.column, newCoverage)); |
| } |
| // Space along the left side of the intersection, if the width is great than on the right |
| if (addMidParcel) |
| { |
| newCoverage = columnCoverage; |
| if (addBotParcel) |
| newCoverage &= ~Parcel.BOT_OF_COLUMN; |
| columnCoverage &= ~Parcel.TOP_OF_COLUMN; |
| |
| if (r.left - area.left > Math.max(area.right - r.right, MIN_WIDTH)) |
| result.push(new Parcel(area.left, r.top, r.left - area.left, r.height, parcel.controller, parcel.column, newCoverage)); |
| // Space along the right side if that's bigger |
| else // if (area.right > r.right && area.right - r.right > MIN_WIDTH) |
| result.push(new Parcel(r.right, r.top, area.right - r.right, r.height, parcel.controller, parcel.column, newCoverage)); |
| } |
| // Space along the bottom |
| if (addBotParcel) |
| result.push(new Parcel(area.left, r.bottom, area.width, area.bottom - r.bottom, parcel.controller, parcel.column, columnCoverage)); |
| } |
| |
| /** @private */ |
| CONFIG::debug private function validate():void |
| { |
| // Check that there are no empty parcels, and that no parcels intersect any other parcel. |
| for (var idx:int; idx < numParcels; idx++) |
| { |
| var i:Parcel = getParcelAtIndex(idx); |
| var parcelRect:Rectangle = i; |
| |
| assert(parcelRect.height != 0 && parcelRect.width != 0, "empty parcel"); |
| // assert(parcelRect.width > MIN_WIDTH, "parcel too small"); we can get a small parcel if we explicitly ask for it (e.g., for a small float) |
| for (var nidx:int; nidx < numParcels; nidx++) |
| { |
| var n:Parcel = getParcelAtIndex(nidx); |
| assert(i == n || i.controller != n.controller || !parcelRect.intersects(n), "parcels intersect"); |
| } |
| } |
| } |
| |
| CONFIG::debug { |
| private function traceOut():void |
| { |
| trace("parcels\n"); |
| for (var idx:int; idx < numParcels; idx++) |
| { |
| var p:Parcel = getParcelAtIndex(idx); |
| trace(idx.toString(), ":", p, "controller", p.controller); |
| } |
| // traceRects("wraps\n", wraps); |
| } |
| } |
| |
| CONFIG::debug { |
| private function traceRects(description:String, rects:Array):void |
| { |
| trace(description); |
| var count:int = 0; |
| for each (var i:Rectangle in rects) |
| { |
| trace(count.toString(), i); |
| count++; |
| } |
| } |
| } |
| |
| CONFIG::debug { |
| private function traceParcels(description:String, parcels:Array /* of Parcel */):void |
| { |
| trace(description); |
| var count:int = 0; |
| for each (var i:Parcel in parcels) |
| { |
| trace(count.toString(), ":", i, "controller", i.controller); |
| count++; |
| } |
| } |
| } |
| |
| } //end class |
| } //end package |