1 /* 2 * Copyright (c) 1999, 2020, 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 * Constructs an instance based on the given Region 52 */ RegionSpanIterator(Region r)53 public RegionSpanIterator(Region r) { 54 int[] bounds = new int[4]; 55 56 r.getBounds(bounds); 57 lox = bounds[0]; 58 loy = bounds[1]; 59 hix = bounds[2]; 60 hiy = bounds[3]; 61 isrect = r.isRectangular(); 62 63 ri = r.getIterator(); 64 } 65 66 /** 67 * Gets the bbox of the available region spans. 68 */ getPathBox(int[] pathbox)69 public void getPathBox(int[] pathbox) { 70 pathbox[0] = lox; 71 pathbox[1] = loy; 72 pathbox[2] = hix; 73 pathbox[3] = hiy; 74 } 75 76 /** 77 * Intersect the box used for clipping the output spans with the 78 * given box. 79 */ intersectClipBox(int clox, int cloy, int chix, int chiy)80 public void intersectClipBox(int clox, int cloy, int chix, int chiy) { 81 if (clox > lox) { 82 lox = clox; 83 } 84 if (cloy > loy) { 85 loy = cloy; 86 } 87 if (chix < hix) { 88 hix = chix; 89 } 90 if (chiy < hiy) { 91 hiy = chiy; 92 } 93 done = lox >= hix || loy >= hiy; 94 } 95 96 /** 97 * Fetches the next span that needs to be operated on. 98 * If the return value is false then there are no more spans. 99 */ nextSpan(int[] spanbox)100 public boolean nextSpan(int[] spanbox) { 101 102 // Quick test for end conditions 103 if (done) { 104 return false; 105 } 106 107 // If the Region is rectangular, we store our bounds (possibly 108 // clipped via intersectClipBox()) in spanbox and return true 109 // so that the caller will process the single span. We set done 110 // to true to ensure that this will be the last span processed. 111 if (isrect) { 112 getPathBox(spanbox); 113 done = true; 114 return true; 115 } 116 117 // Local cache of current span's bounds 118 int curlox, curhix; 119 int curloy = this.curloy; 120 int curhiy = this.curhiy; 121 122 while (true) { 123 if (!ri.nextXBand(spanbox)) { 124 if (!ri.nextYRange(spanbox)) { 125 done = true; 126 return false; 127 } 128 // Update the current y band and clip it 129 curloy = spanbox[1]; 130 curhiy = spanbox[3]; 131 if (curloy < loy) { 132 curloy = loy; 133 } 134 if (curhiy > hiy) { 135 curhiy = hiy; 136 } 137 // Check for moving below the clip rect 138 if (curloy >= hiy) { 139 done = true; 140 return false; 141 } 142 continue; 143 } 144 // Clip the x box 145 curlox = spanbox[0]; 146 curhix = spanbox[2]; 147 if (curlox < lox) { 148 curlox = lox; 149 } 150 if (curhix > hix) { 151 curhix = hix; 152 } 153 // If it's non- box, we're done 154 if (curlox < curhix && curloy < curhiy) { 155 break; 156 } 157 } 158 159 // Update the result and the store y range 160 spanbox[0] = curlox; 161 spanbox[1] = this.curloy = curloy; 162 spanbox[2] = curhix; 163 spanbox[3] = this.curhiy = curhiy; 164 return true; 165 } 166 167 /** 168 * This method tells the iterator that it may skip all spans 169 * whose Y range is completely above the indicated Y coordinate. 170 */ skipDownTo(int y)171 public void skipDownTo(int y) { 172 loy = y; 173 } 174 175 /** 176 * This method returns a native pointer to a function block that 177 * can be used by a native method to perform the same iteration 178 * cycle that the above methods provide while avoiding upcalls to 179 * the Java object. 180 * The definition of the structure whose pointer is returned by 181 * this method is defined in: 182 * <pre> 183 * src/share/native/sun/java2d/pipe/SpanIterator.h 184 * </pre> 185 */ getNativeIterator()186 public long getNativeIterator() { 187 return 0; 188 } 189 } 190