001: /*
002: *
003: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
004: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License version
008: * 2 only, as published by the Free Software Foundation.
009: *
010: * This program is distributed in the hope that it will be useful, but
011: * WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * General Public License version 2 for more details (a copy is
014: * included at /legal/license.txt).
015: *
016: * You should have received a copy of the GNU General Public License
017: * version 2 along with this work; if not, write to the Free Software
018: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
019: * 02110-1301 USA
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
022: * Clara, CA 95054 or visit www.sun.com if you need additional
023: * information or have any questions.
024: */
025:
026: package com.sun.pisces;
027:
028: public class Texture extends Paint {
029:
030: int imageType;
031: int[] intData;
032: int imageWidth;
033: int imageHeight;
034: int stride;
035:
036: boolean repeat;
037:
038: long m00, m01, m02;
039: long m10, m11, m12;
040:
041: int wmask, hmask;
042:
043: boolean interpolate = true;
044:
045: private void computeTransform() {
046: this .m00 = (long) inverse.m00;
047: this .m01 = (long) inverse.m01;
048: this .m10 = (long) inverse.m10;
049: this .m11 = (long) inverse.m11;
050: this .m02 = (long) inverse.m02 + (m00 >> 1) + (m01 >> 1);
051: this .m12 = (long) inverse.m12 + (m10 >> 1) + (m11 >> 1);
052:
053: if (interpolate) {
054: this .m02 -= 32768;
055: this .m12 -= 32768;
056: }
057: }
058:
059: public Texture(int imageType, Object data, int width, int height,
060: int offset, int stride, Transform6 textureTransform,
061: boolean repeat) {
062: super (textureTransform);
063:
064: this .imageType = imageType;
065:
066: int[] srcData = (int[]) data;
067: this .intData = new int[(width + 2) * (height + 2)];
068:
069: // prepare additional pixels for interpolation
070: int copyToFirstCol;
071: int copyToLastCol;
072: int copyToFirstRow;
073: int copyToLastRow;
074:
075: if (repeat) {
076: copyToFirstCol = width - 1;
077: copyToLastCol = 0;
078: copyToFirstRow = height - 1;
079: copyToLastRow = 0;
080: } else {
081: copyToFirstCol = 0;
082: copyToLastCol = width - 1;
083: copyToFirstRow = 0;
084: copyToLastRow = height - 1;
085: }
086:
087: int sidx = offset;
088: int didx = width + 2;
089: for (int y = 0; y < height; y++) {
090: System.arraycopy(srcData, sidx, intData, didx + 1, width);
091: intData[didx] = intData[didx + copyToFirstCol + 1];
092: intData[didx + width + 1] = intData[didx + copyToLastCol
093: + 1];
094: sidx += stride;
095: didx += width + 2;
096: }
097:
098: System.arraycopy(intData, (copyToFirstRow + 1) * (width + 2),
099: intData, 0, width + 2);
100: System.arraycopy(intData, (copyToLastRow + 1) * (width + 2),
101: intData, (height + 1) * (width + 2), width + 2);
102:
103: this .imageWidth = width;
104: this .imageHeight = height;
105: this .stride = width + 2;
106: this .repeat = repeat;
107: computeTransform();
108:
109: int iw = imageWidth;
110: int wshift = 0;
111: while (iw > 0) {
112: iw >>= 1;
113: ++wshift;
114: }
115: this .wmask = 0xffffffff << (wshift - 1);
116:
117: int ih = imageHeight;
118: int hshift = 0;
119: while (ih > 0) {
120: ih >>= 1;
121: ++hshift;
122: }
123: this .hmask = 0xffffffff << (hshift - 1);
124: }
125:
126: public void setTransform(Transform6 transform) {
127: super .setTransform(transform);
128: computeTransform();
129: }
130:
131: public void setQuality(int quality) {
132: // Interpolate if quality >= 1/2
133: this .interpolate = (quality > 65536 / 2);
134: computeTransform();
135: }
136:
137: private int mod(int x, int y) {
138: x = x % y;
139: if (x < 0) {
140: x += y;
141: }
142: return x;
143: }
144:
145: private long mod(long x, long y) {
146: x = x % y;
147: if (x < 0) {
148: x += y;
149: }
150: return x;
151: }
152:
153: private int interp(int x0, int x1, int frac) {
154: return ((x0 << 16) + (x1 - x0) * frac + 0x8000) >> 16;
155: }
156:
157: public void paint(int x, int y, int width, int height,
158: int[] minTouched, int[] maxTouched, int[] dst,
159: int dstOffset, int dstScanlineStride) {
160: int sx = x;
161:
162: for (int j = 0; j < height; j++, y++) {
163: int minX = minTouched[j];
164: int maxX = maxTouched[j];
165: int w = (maxX >= minX) ? (maxX - minX + 1) : 0;
166: if (w + minX > width) {
167: w = width - minX;
168: }
169:
170: int didx = dstOffset + minX;
171: x = sx + minX;
172:
173: long ltx = x * m00 + y * m01 + m02;
174: long lty = x * m10 + y * m11 + m12;
175:
176: for (int i = 0; i < w; i++, didx++) {
177: int tx = (int) (ltx >> 16);
178: int ty = (int) (lty >> 16);
179:
180: int hfrac = (int) (ltx & 0xffff);
181: int vfrac = (int) (lty & 0xffff);
182:
183: // It appears to be cheaper to perform a bounds check
184: // for every pixel and only perform 'mod' when needed
185: // that to 'mod' every pixel
186:
187: // If tx is in bounds, tx & wmask must be 0. The
188: // converse is not necessarily true; i.e., the test is
189: // conservative
190:
191: boolean inBounds = true;
192:
193: if ((tx & wmask) != 0) {
194: if (tx < -1 || tx >= imageWidth) {
195: if (repeat) {
196: ltx = mod(ltx, imageWidth << 16);
197: tx = (int) (ltx >> 16);
198: } else {
199: inBounds = false;
200: }
201: }
202: }
203: if ((ty & hmask) != 0) {
204: if (ty < -1 || ty >= imageHeight) {
205: if (repeat) {
206: lty = mod(lty, imageHeight << 16);
207: ty = (int) (lty >> 16);
208: } else {
209: inBounds = false;
210: }
211: }
212: }
213:
214: if (inBounds) {
215: int sidx = (ty + 1) * stride + tx + 1;
216: int p00 = intData[sidx];
217: if (interpolate) {
218: int p01 = intData[sidx + 1];
219: sidx += stride;
220: int p10 = intData[sidx];
221: int p11 = intData[sidx + 1];
222:
223: int a00 = (p00 >> 24) & 0xff;
224: int r00 = (p00 >> 16) & 0xff;
225: int g00 = (p00 >> 8) & 0xff;
226: int b00 = p00 & 0xff;
227:
228: int a01 = (p01 >> 24) & 0xff;
229: int r01 = (p01 >> 16) & 0xff;
230: int g01 = (p01 >> 8) & 0xff;
231: int b01 = p01 & 0xff;
232:
233: int a0 = interp(a00, a01, hfrac);
234: int r0 = interp(r00, r01, hfrac);
235: int g0 = interp(g00, g01, hfrac);
236: int b0 = interp(b00, b01, hfrac);
237:
238: int a10 = (p10 >> 24) & 0xff;
239: int r10 = (p10 >> 16) & 0xff;
240: int g10 = (p10 >> 8) & 0xff;
241: int b10 = p10 & 0xff;
242:
243: int a11 = (p11 >> 24) & 0xff;
244: int r11 = (p11 >> 16) & 0xff;
245: int g11 = (p11 >> 8) & 0xff;
246: int b11 = p11 & 0xff;
247:
248: int a1 = interp(a10, a11, hfrac);
249: int r1 = interp(r10, r11, hfrac);
250: int g1 = interp(g10, g11, hfrac);
251: int b1 = interp(b10, b11, hfrac);
252:
253: int a = interp(a0, a1, vfrac);
254: int r = interp(r0, r1, vfrac);
255: int g = interp(g0, g1, vfrac);
256: int b = interp(b0, b1, vfrac);
257:
258: dst[didx] = (a << 24) | (r << 16) | (g << 8)
259: | b;
260: } else {
261: dst[didx] = p00;
262: }
263: } else {
264: dst[didx] = 0;
265: }
266:
267: ltx += m00;
268: lty += m10;
269: }
270:
271: dstOffset += dstScanlineStride;
272: }
273: }
274: }
|