/* GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Contact info: lobochief@users.sourceforge.net */ /* * Created on Apr 16, 2005 */ package org.lobobrowser.html.renderer; import java.awt.Point; import java.awt.Rectangle; import java.util.ArrayList; import java.util.List; //import java.util.logging.*; /** * @author J. H. S. */ class MarkupUtilities { // private static final Logger logger = // Logger.getLogger(MarkupUtilities.class); // public static final int MODE_ABOVE_OR_AT = 0; // public static final int MODE_BELOW_OR_AT = 1; // public static final int MODE_LEFT_OR_AT = 0; // public static final int MODE_RIGHT_OR_AT = 1; /** * */ private MarkupUtilities() { super(); } public static BoundableRenderable findRenderable(final Renderable[] renderables, final Point point, final boolean vertical) { return findRenderable(renderables, point, 0, renderables.length, vertical); } public static BoundableRenderable findRenderable(final Renderable[] renderables, final int x, final int y, final boolean vertical) { return findRenderable(renderables, x, y, 0, renderables.length, vertical); } private static BoundableRenderable findRenderable(final Renderable[] renderables, final Point point, final int firstIndex, final int length, final boolean vertical) { return findRenderable(renderables, point.x, point.y, firstIndex, length, vertical); } private static BoundableRenderable findRenderable(final Renderable[] renderables, final int x, final int y, final int firstIndex, final int length, final boolean vertical) { for (int i = firstIndex + length - 1; i >= firstIndex; i--) { if (renderables[i] instanceof BoundableRenderable) { final BoundableRenderable br2 = (BoundableRenderable) renderables[i]; if ((!br2.isDelegated()) && br2.contains(x, y)) { return br2; } } } return null; } // Linear scan version public static List<BoundableRenderable> findRenderables(final Renderable[] renderables, final int x, final int y, final boolean vertical) { List<BoundableRenderable> found = null; for (int i = 0; i < renderables.length; i++) { if (renderables[i] instanceof BoundableRenderable) { final BoundableRenderable br = (BoundableRenderable) renderables[i]; if ((!br.isDelegated()) && br.contains(x, y)) { if (found == null) { found = new ArrayList<>(); } found.add(br); } } } return found; } /* private static BoundableRenderable findRenderable(final Renderable[] renderables, final int x, final int y, final int firstIndex, final int length, final boolean vertical) { if (length == 0) { return null; } if (length == 1) { final Renderable r = renderables[firstIndex]; if (!(r instanceof BoundableRenderable)) { return null; } final BoundableRenderable br = (BoundableRenderable) r; // return br.contains(x, y) ? br : null; if (br.contains(x, y)) { return br; } else { for (int i = firstIndex; i>= 0; i--) { if (renderables[i] instanceof BoundableRenderable) { final BoundableRenderable br2 = (BoundableRenderable) renderables[i]; if (br2.contains(x, y)) { return br2; } } } return null; } } else { final int middleIndex = firstIndex + (length / 2); final Renderable r = renderables[middleIndex]; Rectangle rbounds; if (r instanceof BoundableRenderable) { rbounds = ((BoundableRenderable) r).getVisualBounds(); } else { final BoundableRenderable rleft = findRenderable(renderables, x, y, firstIndex, middleIndex + 1 - firstIndex, vertical); if (rleft != null) { return rleft; } return findRenderable(renderables, x, y, middleIndex + 1, length - ((middleIndex - firstIndex) + 1), vertical); } if (rbounds.contains(x, y)) { return (BoundableRenderable) r; } if (vertical) { if (y < rbounds.y) { return findRenderable(renderables, x, y, firstIndex, middleIndex - firstIndex, vertical); } else { return findRenderable(renderables, x, y, middleIndex + 1, length - ((middleIndex - firstIndex) + 1), vertical); } } else { if (x < rbounds.x) { return findRenderable(renderables, x, y, firstIndex, middleIndex - firstIndex, vertical); } else { return findRenderable(renderables, x, y, middleIndex + 1, length - ((middleIndex - firstIndex) + 1), vertical); } } } }*/ public static Range findRenderables(final Renderable[] renderables, final Rectangle clipArea, final boolean vertical) { return findRenderables(renderables, clipArea, 0, renderables.length, vertical); } private static Range findRenderables(final Renderable[] renderables, final Rectangle clipArea, final int firstIndex, final int length, final boolean vertical) { if (length == 0) { return new Range(0, 0); } int offset1 = findFirstIndex(renderables, clipArea, firstIndex, length, vertical); int offset2 = findLastIndex(renderables, clipArea, firstIndex, length, vertical); if ((offset1 == -1) && (offset2 == -1)) { // if(logger.isLoggable(Level.INFO))logger.info("findRenderables(): Range not found for clipArea=" // + clipArea + ",length=" + length); // for(int i = firstIndex; i < length; i++) { // logger.info("findRenderables(): renderable.bounds=" + // renderables[i].getBounds()); // } return new Range(0, 0); } if (offset1 == -1) { offset1 = firstIndex; } if (offset2 == -1) { offset2 = (firstIndex + length) - 1; } return new Range(offset1, (offset2 - offset1) + 1); } /* private static int findFirstIndex(final Renderable[] renderables, final Rectangle clipArea, final int index, final int length, final boolean vertical) { Diagnostics.Assert(length > 0, "length=" + length); if (length == 1) { final Renderable r = renderables[index]; Rectangle rbounds; if (r instanceof BoundableRenderable) { rbounds = ((BoundableRenderable) r).getVisualBounds(); } else { return -1; } if (intersects(rbounds, clipArea, vertical)) { return index; } else { return -1; } } else { final int middleIndex = index + (length / 2); final Renderable r = renderables[middleIndex]; Rectangle rbounds; if (r instanceof BoundableRenderable) { rbounds = ((BoundableRenderable) r).getVisualBounds(); } else { final int leftIndex = findFirstIndex(renderables, clipArea, index, middleIndex - index, vertical); if (leftIndex != -1) { return leftIndex; } return findFirstIndex(renderables, clipArea, middleIndex + 1, length - ((middleIndex - index) + 1), vertical); } if (vertical) { if ((rbounds.y + rbounds.height) < clipArea.y) { final int newLen = length - ((middleIndex - index) + 1); return newLen == 0 ? -1 : findFirstIndex(renderables, clipArea, middleIndex + 1, newLen, vertical); } else { final int newLen = middleIndex - index; final int resultIdx = newLen == 0 ? -1 : findFirstIndex(renderables, clipArea, index, newLen, vertical); if (resultIdx == -1) { if (intersects(clipArea, rbounds, vertical)) { return middleIndex; } } return resultIdx; } } else { if ((rbounds.x + rbounds.width) < clipArea.x) { return findFirstIndex(renderables, clipArea, middleIndex + 1, length - (middleIndex - index), vertical); } else { final int resultIdx = findFirstIndex(renderables, clipArea, index, middleIndex - index, vertical); if (resultIdx == -1) { if (intersects(clipArea, rbounds, vertical)) { return middleIndex; } } return resultIdx; } } } } */ private static int findFirstIndex(final Renderable[] renderables, final Rectangle clipArea, final int index, final int length, final boolean vertical) { for (int i = index; i < length; i++) { final Renderable ri = renderables[i]; if (ri instanceof BoundableRenderable) { final BoundableRenderable br = (BoundableRenderable) ri; if (intersects(clipArea, br.getVisualBounds(), vertical)) { return i; } } } return -1; } private static int findLastIndex(final Renderable[] renderables, final Rectangle clipArea, final int index, final int length, final boolean vertical) { for (int i = index + length - 1; i >= index; i--) { final Renderable ri = renderables[i]; if (ri instanceof BoundableRenderable) { final BoundableRenderable br = (BoundableRenderable) ri; if (intersects(clipArea, br.getVisualBounds(), vertical)) { return i; } } } return -1; } /* private static int findLastIndex(final Renderable[] renderables, final Rectangle clipArea, final int index, final int length, final boolean vertical) { Diagnostics.Assert(length > 0, "length<=0"); if (length == 1) { final Renderable r = renderables[index]; Rectangle rbounds; if (r instanceof BoundableRenderable) { rbounds = ((BoundableRenderable) r).getVisualBounds(); } else { return -1; } if (intersects(clipArea, rbounds, vertical)) { return index; } else { return -1; } } else { final int middleIndex = index + (length / 2); final Renderable r = renderables[middleIndex]; Rectangle rbounds; if (r instanceof BoundableRenderable) { rbounds = ((BoundableRenderable) r).getVisualBounds(); } else { final int rightIndex = findLastIndex(renderables, clipArea, middleIndex + 1, length - ((middleIndex - index) + 1), vertical); if (rightIndex != -1) { return rightIndex; } return findLastIndex(renderables, clipArea, index, middleIndex - index, vertical); } if (vertical) { if (rbounds.y > (clipArea.y + clipArea.height)) { return findLastIndex(renderables, clipArea, index, middleIndex - index, vertical); } else { final int newLen = length - ((middleIndex - index) + 1); final int resultIdx = newLen == 0 ? -1 : findLastIndex(renderables, clipArea, middleIndex + 1, newLen, vertical); if (resultIdx == -1) { if (intersects(clipArea, rbounds, vertical)) { return middleIndex; } } return resultIdx; } } else { if (rbounds.x > (clipArea.x + clipArea.width)) { return findLastIndex(renderables, clipArea, index, middleIndex - index, vertical); } else { final int resultIdx = findLastIndex(renderables, clipArea, middleIndex + 1, length - ((middleIndex - index) + 1), vertical); if (resultIdx == -1) { if (intersects(clipArea, rbounds, vertical)) { return middleIndex; } } return resultIdx; } } } } */ private static boolean intersects(final Rectangle rect1, final Rectangle rect2, final boolean vertical) { if (vertical) { return !((rect1.y > (rect2.y + rect2.height)) || (rect2.y > (rect1.y + rect1.height))); } else { return !((rect1.x > (rect2.x + rect2.width)) || (rect2.x > (rect1.x + rect1.width))); } } }