1 /* 2 * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.java2d.pipe; 27 28 /** 29 * This class implements the ShapeIterator interface for a Region. 30 * This is useful as the source iterator of a device clip region 31 * (in its native guise), and also as the result of clipping a 32 * Region to a rectangle. 33 */ 34 public class RegionSpanIterator implements SpanIterator { 35 // The RegionIterator that we use to do the work 36 RegionIterator ri; 37 38 // Clipping bounds 39 int lox, loy, hix, hiy; 40 41 // Current Y band limits 42 int curloy, curhiy; 43 44 // Are we done? 45 boolean done = false; 46 47 // Is the associated Region rectangular? 48 boolean isrect; 49 50 /* 51 REMIND: For native implementation 52 long pData; // Private storage of rect info 53 54 static { 55 initIDs(); 56 } 57 58 public static native void initIDs(); 59 */ 60 61 /** 62 * Constructs an instance based on the given Region 63 */ 64 public RegionSpanIterator(Region r) { 65 int[] bounds = new int[4]; 66 67 r.getBounds(bounds); 68 lox = bounds[0]; 69 loy = bounds[1]; 70 hix = bounds[2]; 71 hiy = bounds[3]; 72 isrect = r.isRectangular(); 73 74 ri = r.getIterator(); 75 } 76 77 /** 78 * Gets the bbox of the available region spans. 79 */ 80 public void getPathBox(int[] pathbox) { 81 pathbox[0] = lox; 82 pathbox[1] = loy; 83 pathbox[2] = hix; 84 pathbox[3] = hiy; 85 } 86 87 /** 88 * Intersect the box used for clipping the output spans with the 89 * given box. 90 */ 91 public void intersectClipBox(int clox, int cloy, int chix, int chiy) { 92 if (clox > lox) { 93 lox = clox; 94 } 95 if (cloy > loy) { 96 loy = cloy; 97 } 98 if (chix < hix) { 99 hix = chix; 100 } 101 if (chiy < hiy) { 102 hiy = chiy; 103 } 104 done = lox >= hix || loy >= hiy; 105 } 106 107 /** 108 * Fetches the next span that needs to be operated on. 109 * If the return value is false then there are no more spans. 110 */ 111 public boolean nextSpan(int[] spanbox) { 112 113 // Quick test for end conditions 114 if (done) { 115 return false; 116 } 117 118 // If the Region is rectangular, we store our bounds (possibly 119 // clipped via intersectClipBox()) in spanbox and return true 120 // so that the caller will process the single span. We set done 121 // to true to ensure that this will be the last span processed. 122 if (isrect) { 123 getPathBox(spanbox); 124 done = true; 125 return true; 126 } 127 128 // Local cache of current span's bounds 129 int curlox, curhix; 130 int curloy = this.curloy; 131 int curhiy = this.curhiy; 132 133 while (true) { 134 if (!ri.nextXBand(spanbox)) { 135 if (!ri.nextYRange(spanbox)) { 136 done = true; 137 return false; 138 } 139 // Update the current y band and clip it 140 curloy = spanbox[1]; 141 curhiy = spanbox[3]; 142 if (curloy < loy) { 143 curloy = loy; 144 } 145 if (curhiy > hiy) { 146 curhiy = hiy; 147 } 148 // Check for moving below the clip rect 149 if (curloy >= hiy) { 150 done = true; 151 return false; 152 } 153 continue; 154 } 155 // Clip the x box 156 curlox = spanbox[0]; 157 curhix = spanbox[2]; 158 if (curlox < lox) { 159 curlox = lox; 160 } 161 if (curhix > hix) { 162 curhix = hix; 163 } 164 // If it's non- box, we're done 165 if (curlox < curhix && curloy < curhiy) { 166 break; 167 } 168 } 169 170 // Update the result and the store y range 171 spanbox[0] = curlox; 172 spanbox[1] = this.curloy = curloy; 173 spanbox[2] = curhix; 174 spanbox[3] = this.curhiy = curhiy; 175 return true; 176 } 177 178 /** 179 * This method tells the iterator that it may skip all spans 180 * whose Y range is completely above the indicated Y coordinate. 181 */ 182 public void skipDownTo(int y) { 183 loy = y; 184 } 185 186 /** 187 * This method returns a native pointer to a function block that 188 * can be used by a native method to perform the same iteration 189 * cycle that the above methods provide while avoiding upcalls to 190 * the Java object. 191 * The definition of the structure whose pointer is returned by 192 * this method is defined in: 193 * <pre> 194 * src/share/native/sun/java2d/pipe/SpanIterator.h 195 * </pre> 196 */ 197 public long getNativeIterator() { 198 return 0; 199 } 200 201 /* 202 * Cleans out all internal data structures. 203 * REMIND: Native implementation 204 public native void dispose(); 205 206 protected void finalize() { 207 dispose(); 208 } 209 */ 210 }