1 21 24 package org.lobobrowser.html.renderer; 25 26 import java.awt.*; 27 28 import org.lobobrowser.util.Diagnostics; 29 30 32 35 class MarkupUtilities { 36 38 43 46 private MarkupUtilities() { 47 super(); 48 } 49 50 public static BoundableRenderable findRenderable(Renderable[] renderables, Point point, boolean vertical) { 51 return findRenderable(renderables, point, 0, renderables.length, vertical); 52 } 53 54 public static BoundableRenderable findRenderable(Renderable[] renderables, int x, int y, boolean vertical) { 55 return findRenderable(renderables, x, y, 0, renderables.length, vertical); 56 } 57 58 private static BoundableRenderable findRenderable(Renderable[] renderables, Point point, int firstIndex, int length, boolean vertical) { 59 return findRenderable(renderables, point.x, point.y, firstIndex, length, vertical); 60 } 61 62 private static BoundableRenderable findRenderable(Renderable[] renderables, int x, int y, int firstIndex, int length, boolean vertical) { 63 if(length == 0) { 64 return null; 65 } 66 if(length == 1) { 67 Renderable r = renderables[firstIndex]; 68 if(!(r instanceof BoundableRenderable)) { 69 return null; 70 } 71 BoundableRenderable br = (BoundableRenderable) r; 72 Rectangle rbounds = br.getBounds(); 73 return rbounds.contains(x, y) ? br : null; 74 } 75 else { 76 int middleIndex = firstIndex + length / 2; 77 Renderable r = renderables[middleIndex]; 78 Rectangle rbounds; 79 if(r instanceof BoundableRenderable) { 80 rbounds = ((BoundableRenderable) r).getBounds(); 81 } 82 else { 83 BoundableRenderable rleft = findRenderable(renderables, x, y, firstIndex, middleIndex - firstIndex, vertical); 84 if(rleft != null) { 85 return rleft; 86 } 87 return findRenderable(renderables, x, y, middleIndex + 1, length - (middleIndex - firstIndex + 1), vertical); 88 } 89 if(rbounds.contains(x, y)) { 90 return (BoundableRenderable) r; 91 } 92 if(vertical) { 93 if(y < rbounds.y) { 94 return findRenderable(renderables, x, y, firstIndex, middleIndex - firstIndex, vertical); 95 } 96 else { 97 return findRenderable(renderables, x, y, middleIndex + 1, length - (middleIndex - firstIndex + 1), vertical); 98 } 99 } 100 else { 101 if(x < rbounds.x) { 102 return findRenderable(renderables, x, y, firstIndex, middleIndex - firstIndex, vertical); 103 } 104 else { 105 return findRenderable(renderables, x, y, middleIndex + 1, length - (middleIndex - firstIndex + 1), vertical); 106 } 107 } 108 } 109 } 110 111 public static Range findRenderables(Renderable[] renderables, Rectangle clipArea, boolean vertical) { 112 return findRenderables(renderables, clipArea, 0, renderables.length, vertical); 113 } 114 115 private static Range findRenderables(Renderable[] renderables, Rectangle clipArea, int firstIndex, int length, boolean vertical) { 116 if(length == 0) { 117 return new Range(0, 0); 118 } 119 int offset1 = findFirstIndex(renderables, clipArea, firstIndex, length, vertical); 120 int offset2 = findLastIndex(renderables, clipArea, firstIndex, length, vertical); 121 if(offset1 == -1 && offset2 == -1) { 122 return new Range(0, 0); 127 } 128 if(offset1 == -1) { 129 offset1 = firstIndex; 130 } 131 if(offset2 == -1) { 132 offset2 = firstIndex + length - 1; 133 } 134 return new Range(offset1, offset2 - offset1 + 1); 135 } 136 137 private static int findFirstIndex(Renderable[] renderables, Rectangle clipArea, int index, int length, boolean vertical) { 138 Diagnostics.Assert(length > 0, "length=" + length); 139 if(length == 1) { 140 Renderable r = renderables[index]; 141 Rectangle rbounds; 142 if(r instanceof BoundableRenderable) { 143 rbounds = ((BoundableRenderable) r).getBounds(); 144 } 145 else { 146 return -1; 147 } 148 if(intersects(rbounds, clipArea, vertical)) { 149 return index; 150 } 151 else { 152 return -1; 153 } 154 } 155 else { 156 int middleIndex = index + length / 2; 157 Renderable r = renderables[middleIndex]; 158 Rectangle rbounds; 159 if(r instanceof BoundableRenderable) { 160 rbounds = ((BoundableRenderable) r).getBounds(); 161 } 162 else { 163 int leftIndex = findFirstIndex(renderables, clipArea, index, middleIndex - index, vertical); 164 if(leftIndex != -1) { 165 return leftIndex; 166 } 167 return findFirstIndex(renderables, clipArea, middleIndex + 1, length - (middleIndex - index + 1), vertical); 168 } 169 if(vertical) { 170 if(rbounds.y + rbounds.height < clipArea.y) { 171 int newLen = length - (middleIndex - index + 1); 172 return newLen == 0 ? -1 : findFirstIndex(renderables, clipArea, middleIndex + 1, newLen, vertical); 173 } 174 else { 175 int newLen = middleIndex - index; 176 int resultIdx = newLen == 0 ? -1 : findFirstIndex(renderables, clipArea, index, newLen, vertical); 177 if(resultIdx == -1) { 178 if(intersects(clipArea, rbounds, vertical)) { 179 return middleIndex; 180 } 181 } 182 return resultIdx; 183 } 184 } 185 else { 186 if(rbounds.x + rbounds.width < clipArea.x) { 187 return findFirstIndex(renderables, clipArea, middleIndex + 1, length - (middleIndex - index), vertical); 188 } 189 else { 190 int resultIdx = findFirstIndex(renderables, clipArea, index, middleIndex - index, vertical); 191 if(resultIdx == -1) { 192 if(intersects(clipArea, rbounds, vertical)) { 193 return middleIndex; 194 } 195 } 196 return resultIdx; 197 } 198 } 199 } 200 } 201 202 private static int findLastIndex(Renderable[] renderables, Rectangle clipArea, int index, int length, boolean vertical) { 203 Diagnostics.Assert(length > 0, "length<=0"); 204 if(length == 1) { 205 Renderable r = renderables[index]; 206 Rectangle rbounds; 207 if(r instanceof BoundableRenderable) { 208 rbounds = ((BoundableRenderable) r).getBounds(); 209 } 210 else { 211 return -1; 212 } 213 if(intersects(clipArea, rbounds, vertical)) { 214 return index; 215 } 216 else { 217 return -1; 218 } 219 } 220 else { 221 int middleIndex = index + length / 2; 222 Renderable r = renderables[middleIndex]; 223 Rectangle rbounds; 224 if(r instanceof BoundableRenderable) { 225 rbounds = ((BoundableRenderable) r).getBounds(); 226 } 227 else { 228 int rightIndex = findLastIndex(renderables, clipArea, middleIndex + 1, length - (middleIndex - index + 1), vertical); 229 if(rightIndex != -1) { 230 return rightIndex; 231 } 232 return findLastIndex(renderables, clipArea, index, middleIndex - index, vertical); 233 } 234 if(vertical) { 235 if(rbounds.y > clipArea.y + clipArea.height) { 236 return findLastIndex(renderables, clipArea, index, middleIndex - index, vertical); 237 } 238 else { 239 int newLen = length - (middleIndex - index + 1); 240 int resultIdx = newLen == 0 ? -1 : findLastIndex(renderables, clipArea, middleIndex + 1, newLen, vertical); 241 if(resultIdx == -1) { 242 if(intersects(clipArea, rbounds, vertical)) { 243 return middleIndex; 244 } 245 } 246 return resultIdx; 247 } 248 } 249 else { 250 if(rbounds.x > clipArea.x + clipArea.width) { 251 return findLastIndex(renderables, clipArea, index, middleIndex - index, vertical); 252 } 253 else { 254 int resultIdx = findLastIndex(renderables, clipArea, middleIndex + 1, length - (middleIndex - index + 1), vertical); 255 if(resultIdx == -1) { 256 if(intersects(clipArea, rbounds, vertical)) { 257 return middleIndex; 258 } 259 } 260 return resultIdx; 261 } 262 } 263 } 264 } 265 266 private static boolean intersects(Rectangle rect1, Rectangle rect2, boolean vertical) { 267 if(vertical) { 268 return !( 269 (rect1.y > rect2.y + rect2.height) || 270 (rect2.y > rect1.y + rect1.height) 271 ); 272 } 273 else { 274 return !( 275 (rect1.x > rect2.x + rect2.width) || 276 (rect2.x > rect1.x + rect1.width) 277 ); 278 } 279 } 280 } 281 | Popular Tags |