1 /*
2 * Copyright (c) 1997, 2013, 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
318 int rowincx, int rowincxerr,
319 int rowincy, int rowincyerr);
320
321 /*
322 * Blends the four ARGB values in the rgbs array using the factors
323 * described by xmul and ymul in the following ratio:
324 *
325 * rgbs[0] * (1-xmul) * (1-ymul) +
326 * rgbs[1] * ( xmul) * (1-ymul) +
327 * rgbs[2] * (1-xmul) * ( ymul) +
328 * rgbs[3] * ( xmul) * ( ymul)
329 *
330 * xmul and ymul are integer values in the half-open range [0, 2^31)
331 * where 0 == 0.0 and 2^31 == 1.0.
332 *
333 * Note that since the range is half-open, the values are always
334 * logically less than 1.0. This makes sense because while choosing
335 * pixels to blend, when the error values reach 1.0 we move to the
336 * next pixel and reset them to 0.0.
337 */
338 public static int blend(int rgbs[], int xmul, int ymul) {
339 // xmul/ymul are 31 bits wide, (0 => 2^31-1)
340 // shift them to 12 bits wide, (0 => 2^12-1)
341 xmul = (xmul >>> 19);
342 ymul = (ymul >>> 19);
343 int accumA, accumR, accumG, accumB;
344 accumA = accumR = accumG = accumB = 0;
345 for (int i = 0; i < 4; i++) {
346 int rgb = rgbs[i];
347 // The complement of the [xy]mul values (1-[xy]mul) can result
348 // in new values in the range (1 => 2^12). Thus for any given
349 // loop iteration, the values could be anywhere in (0 => 2^12).
350 xmul = (1<<12) - xmul;
351 if ((i & 1) == 0) {
352 ymul = (1<<12) - ymul;
353 }
354 // xmul and ymul are each 12 bits (0 => 2^12)
355 // factor is thus 24 bits (0 => 2^24)
356 int factor = xmul * ymul;
357 if (factor != 0) {
358 // accum variables will accumulate 32 bits
359 // bytes extracted from rgb fit in 8 bits (0 => 255)
360 // byte * factor thus fits in 32 bits (0 => 255 * 2^24)
361 accumA += (((rgb >>> 24) ) * factor);
362 accumR += (((rgb >>> 16) & 0xff) * factor);
363 accumG += (((rgb >>> 8) & 0xff) * factor);
364 accumB += (((rgb ) & 0xff) * factor);
365 }
366 }
367 return ((((accumA + (1<<23)) >>> 24) << 24) |
368 (((accumR + (1<<23)) >>> 24) << 16) |
369 (((accumG + (1<<23)) >>> 24) << 8) |
370 (((accumB + (1<<23)) >>> 24) ));
371 }
372
373 static class Int extends TexturePaintContext {
374 IntegerInterleavedRaster srcRas;
375 int inData[];
376 int inOff;
377 int inSpan;
378 int outData[];
379 int outOff;
380 int outSpan;
381 boolean filter;
382
383 public Int(IntegerInterleavedRaster srcRas, ColorModel cm,
384 AffineTransform xform, int maxw, boolean filter)
385 {
386 super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
387 this.srcRas = srcRas;
388 this.inData = srcRas.getDataStorage();
389 this.inSpan = srcRas.getScanlineStride();
390 this.inOff = srcRas.getDataOffset(0);
391 this.filter = filter;
392 }
393
394 public WritableRaster makeRaster(int w, int h) {
395 WritableRaster ras = makeRaster(colorModel, srcRas, w, h);
396 IntegerInterleavedRaster iiRas = (IntegerInterleavedRaster) ras;
397 outData = iiRas.getDataStorage();
398 outSpan = iiRas.getScanlineStride();
405 int colincx, int colincxerr,
406 int colincy, int colincyerr,
407 int rowincx, int rowincxerr,
408 int rowincy, int rowincyerr) {
409 int[] inData = this.inData;
410 int[] outData = this.outData;
411 int out = outOff;
412 int inSpan = this.inSpan;
413 int inOff = this.inOff;
414 int outSpan = this.outSpan;
415 boolean filter = this.filter;
416 boolean normalx = (colincx == 1 && colincxerr == 0 &&
417 colincy == 0 && colincyerr == 0) && !filter;
418 int rowx = x;
419 int rowy = y;
420 int rowxerr = xerr;
421 int rowyerr = yerr;
422 if (normalx) {
423 outSpan -= w;
424 }
425 int rgbs[] = filter ? new int[4] : null;
426 for (int j = 0; j < h; j++) {
427 if (normalx) {
428 int in = inOff + rowy * inSpan + bWidth;
429 x = bWidth - rowx;
430 out += w;
431 if (bWidth >= 32) {
432 int i = w;
433 while (i > 0) {
434 int copyw = (i < x) ? i : x;
435 System.arraycopy(inData, in - x,
436 outData, out - i,
437 copyw);
438 i -= copyw;
439 if ((x -= copyw) == 0) {
440 x = bWidth;
441 }
442 }
443 } else {
444 for (int i = w; i > 0; i--) {
445 outData[out - i] = inData[in - x];
491 rowxerr &= Integer.MAX_VALUE;
492 rowx++;
493 }
494 if ((rowx += rowincx) >= bWidth) {
495 rowx -= bWidth;
496 }
497 if ((rowyerr += rowincyerr) < 0) {
498 rowyerr &= Integer.MAX_VALUE;
499 rowy++;
500 }
501 if ((rowy += rowincy) >= bHeight) {
502 rowy -= bHeight;
503 }
504 out += outSpan;
505 }
506 }
507 }
508
509 static class Byte extends TexturePaintContext {
510 ByteInterleavedRaster srcRas;
511 byte inData[];
512 int inOff;
513 int inSpan;
514 byte outData[];
515 int outOff;
516 int outSpan;
517
518 public Byte(ByteInterleavedRaster srcRas, ColorModel cm,
519 AffineTransform xform, int maxw)
520 {
521 super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
522 this.srcRas = srcRas;
523 this.inData = srcRas.getDataStorage();
524 this.inSpan = srcRas.getScanlineStride();
525 this.inOff = srcRas.getDataOffset(0);
526 }
527
528 public WritableRaster makeRaster(int w, int h) {
529 WritableRaster ras = makeByteRaster(srcRas, w, h);
530 ByteInterleavedRaster biRas = (ByteInterleavedRaster) ras;
531 outData = biRas.getDataStorage();
532 outSpan = biRas.getScanlineStride();
533 outOff = biRas.getDataOffset(0);
534 return ras;
611 rowxerr &= Integer.MAX_VALUE;
612 rowx++;
613 }
614 if ((rowx += rowincx) >= bWidth) {
615 rowx -= bWidth;
616 }
617 if ((rowyerr += rowincyerr) < 0) {
618 rowyerr &= Integer.MAX_VALUE;
619 rowy++;
620 }
621 if ((rowy += rowincy) >= bHeight) {
622 rowy -= bHeight;
623 }
624 out += outSpan;
625 }
626 }
627 }
628
629 static class ByteFilter extends TexturePaintContext {
630 ByteInterleavedRaster srcRas;
631 int inPalette[];
632 byte inData[];
633 int inOff;
634 int inSpan;
635 int outData[];
636 int outOff;
637 int outSpan;
638
639 public ByteFilter(ByteInterleavedRaster srcRas, ColorModel cm,
640 AffineTransform xform, int maxw)
641 {
642 super((cm.getTransparency() == Transparency.OPAQUE
643 ? xrgbmodel : argbmodel),
644 xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
645 this.inPalette = new int[256];
646 ((IndexColorModel) cm).getRGBs(this.inPalette);
647 this.srcRas = srcRas;
648 this.inData = srcRas.getDataStorage();
649 this.inSpan = srcRas.getScanlineStride();
650 this.inOff = srcRas.getDataOffset(0);
651 }
652
653 public WritableRaster makeRaster(int w, int h) {
654 // Note that we do not pass srcRas to makeRaster since it
655 // is a Byte Raster and this colorModel needs an Int Raster
660 outOff = iiRas.getDataOffset(0);
661 return ras;
662 }
663
664 public void setRaster(int x, int y, int xerr, int yerr,
665 int w, int h, int bWidth, int bHeight,
666 int colincx, int colincxerr,
667 int colincy, int colincyerr,
668 int rowincx, int rowincxerr,
669 int rowincy, int rowincyerr) {
670 byte[] inData = this.inData;
671 int[] outData = this.outData;
672 int out = outOff;
673 int inSpan = this.inSpan;
674 int inOff = this.inOff;
675 int outSpan = this.outSpan;
676 int rowx = x;
677 int rowy = y;
678 int rowxerr = xerr;
679 int rowyerr = yerr;
680 int rgbs[] = new int[4];
681 for (int j = 0; j < h; j++) {
682 x = rowx;
683 y = rowy;
684 xerr = rowxerr;
685 yerr = rowyerr;
686 for (int i = 0; i < w; i++) {
687 int nextx, nexty;
688 if ((nextx = x + 1) >= bWidth) {
689 nextx = 0;
690 }
691 if ((nexty = y + 1) >= bHeight) {
692 nexty = 0;
693 }
694 rgbs[0] = inPalette[0xff & inData[inOff + x +
695 inSpan * y]];
696 rgbs[1] = inPalette[0xff & inData[inOff + nextx +
697 inSpan * y]];
698 rgbs[2] = inPalette[0xff & inData[inOff + x +
699 inSpan * nexty]];
700 rgbs[3] = inPalette[0xff & inData[inOff + nextx +
747 this.filter = filter;
748 }
749
750 public WritableRaster makeRaster(int w, int h) {
751 return makeRaster(colorModel, srcRas, w, h);
752 }
753
754 public void setRaster(int x, int y, int xerr, int yerr,
755 int w, int h, int bWidth, int bHeight,
756 int colincx, int colincxerr,
757 int colincy, int colincyerr,
758 int rowincx, int rowincxerr,
759 int rowincy, int rowincyerr) {
760 Object data = null;
761 int rowx = x;
762 int rowy = y;
763 int rowxerr = xerr;
764 int rowyerr = yerr;
765 WritableRaster srcRas = this.srcRas;
766 WritableRaster outRas = this.outRas;
767 int rgbs[] = filter ? new int[4] : null;
768 for (int j = 0; j < h; j++) {
769 x = rowx;
770 y = rowy;
771 xerr = rowxerr;
772 yerr = rowyerr;
773 for (int i = 0; i < w; i++) {
774 data = srcRas.getDataElements(x, y, data);
775 if (filter) {
776 int nextx, nexty;
777 if ((nextx = x + 1) >= bWidth) {
778 nextx = 0;
779 }
780 if ((nexty = y + 1) >= bHeight) {
781 nexty = 0;
782 }
783 rgbs[0] = colorModel.getRGB(data);
784 data = srcRas.getDataElements(nextx, y, data);
785 rgbs[1] = colorModel.getRGB(data);
786 data = srcRas.getDataElements(x, nexty, data);
787 rgbs[2] = colorModel.getRGB(data);
|
1 /*
2 * Copyright (c) 1997, 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
318 int rowincx, int rowincxerr,
319 int rowincy, int rowincyerr);
320
321 /*
322 * Blends the four ARGB values in the rgbs array using the factors
323 * described by xmul and ymul in the following ratio:
324 *
325 * rgbs[0] * (1-xmul) * (1-ymul) +
326 * rgbs[1] * ( xmul) * (1-ymul) +
327 * rgbs[2] * (1-xmul) * ( ymul) +
328 * rgbs[3] * ( xmul) * ( ymul)
329 *
330 * xmul and ymul are integer values in the half-open range [0, 2^31)
331 * where 0 == 0.0 and 2^31 == 1.0.
332 *
333 * Note that since the range is half-open, the values are always
334 * logically less than 1.0. This makes sense because while choosing
335 * pixels to blend, when the error values reach 1.0 we move to the
336 * next pixel and reset them to 0.0.
337 */
338 public static int blend(int[] rgbs, int xmul, int ymul) {
339 // xmul/ymul are 31 bits wide, (0 => 2^31-1)
340 // shift them to 12 bits wide, (0 => 2^12-1)
341 xmul = (xmul >>> 19);
342 ymul = (ymul >>> 19);
343 int accumA, accumR, accumG, accumB;
344 accumA = accumR = accumG = accumB = 0;
345 for (int i = 0; i < 4; i++) {
346 int rgb = rgbs[i];
347 // The complement of the [xy]mul values (1-[xy]mul) can result
348 // in new values in the range (1 => 2^12). Thus for any given
349 // loop iteration, the values could be anywhere in (0 => 2^12).
350 xmul = (1<<12) - xmul;
351 if ((i & 1) == 0) {
352 ymul = (1<<12) - ymul;
353 }
354 // xmul and ymul are each 12 bits (0 => 2^12)
355 // factor is thus 24 bits (0 => 2^24)
356 int factor = xmul * ymul;
357 if (factor != 0) {
358 // accum variables will accumulate 32 bits
359 // bytes extracted from rgb fit in 8 bits (0 => 255)
360 // byte * factor thus fits in 32 bits (0 => 255 * 2^24)
361 accumA += (((rgb >>> 24) ) * factor);
362 accumR += (((rgb >>> 16) & 0xff) * factor);
363 accumG += (((rgb >>> 8) & 0xff) * factor);
364 accumB += (((rgb ) & 0xff) * factor);
365 }
366 }
367 return ((((accumA + (1<<23)) >>> 24) << 24) |
368 (((accumR + (1<<23)) >>> 24) << 16) |
369 (((accumG + (1<<23)) >>> 24) << 8) |
370 (((accumB + (1<<23)) >>> 24) ));
371 }
372
373 static class Int extends TexturePaintContext {
374 IntegerInterleavedRaster srcRas;
375 int[] inData;
376 int inOff;
377 int inSpan;
378 int[] outData;
379 int outOff;
380 int outSpan;
381 boolean filter;
382
383 public Int(IntegerInterleavedRaster srcRas, ColorModel cm,
384 AffineTransform xform, int maxw, boolean filter)
385 {
386 super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
387 this.srcRas = srcRas;
388 this.inData = srcRas.getDataStorage();
389 this.inSpan = srcRas.getScanlineStride();
390 this.inOff = srcRas.getDataOffset(0);
391 this.filter = filter;
392 }
393
394 public WritableRaster makeRaster(int w, int h) {
395 WritableRaster ras = makeRaster(colorModel, srcRas, w, h);
396 IntegerInterleavedRaster iiRas = (IntegerInterleavedRaster) ras;
397 outData = iiRas.getDataStorage();
398 outSpan = iiRas.getScanlineStride();
405 int colincx, int colincxerr,
406 int colincy, int colincyerr,
407 int rowincx, int rowincxerr,
408 int rowincy, int rowincyerr) {
409 int[] inData = this.inData;
410 int[] outData = this.outData;
411 int out = outOff;
412 int inSpan = this.inSpan;
413 int inOff = this.inOff;
414 int outSpan = this.outSpan;
415 boolean filter = this.filter;
416 boolean normalx = (colincx == 1 && colincxerr == 0 &&
417 colincy == 0 && colincyerr == 0) && !filter;
418 int rowx = x;
419 int rowy = y;
420 int rowxerr = xerr;
421 int rowyerr = yerr;
422 if (normalx) {
423 outSpan -= w;
424 }
425 int[] rgbs = filter ? new int[4] : null;
426 for (int j = 0; j < h; j++) {
427 if (normalx) {
428 int in = inOff + rowy * inSpan + bWidth;
429 x = bWidth - rowx;
430 out += w;
431 if (bWidth >= 32) {
432 int i = w;
433 while (i > 0) {
434 int copyw = (i < x) ? i : x;
435 System.arraycopy(inData, in - x,
436 outData, out - i,
437 copyw);
438 i -= copyw;
439 if ((x -= copyw) == 0) {
440 x = bWidth;
441 }
442 }
443 } else {
444 for (int i = w; i > 0; i--) {
445 outData[out - i] = inData[in - x];
491 rowxerr &= Integer.MAX_VALUE;
492 rowx++;
493 }
494 if ((rowx += rowincx) >= bWidth) {
495 rowx -= bWidth;
496 }
497 if ((rowyerr += rowincyerr) < 0) {
498 rowyerr &= Integer.MAX_VALUE;
499 rowy++;
500 }
501 if ((rowy += rowincy) >= bHeight) {
502 rowy -= bHeight;
503 }
504 out += outSpan;
505 }
506 }
507 }
508
509 static class Byte extends TexturePaintContext {
510 ByteInterleavedRaster srcRas;
511 byte[] inData;
512 int inOff;
513 int inSpan;
514 byte[] outData;
515 int outOff;
516 int outSpan;
517
518 public Byte(ByteInterleavedRaster srcRas, ColorModel cm,
519 AffineTransform xform, int maxw)
520 {
521 super(cm, xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
522 this.srcRas = srcRas;
523 this.inData = srcRas.getDataStorage();
524 this.inSpan = srcRas.getScanlineStride();
525 this.inOff = srcRas.getDataOffset(0);
526 }
527
528 public WritableRaster makeRaster(int w, int h) {
529 WritableRaster ras = makeByteRaster(srcRas, w, h);
530 ByteInterleavedRaster biRas = (ByteInterleavedRaster) ras;
531 outData = biRas.getDataStorage();
532 outSpan = biRas.getScanlineStride();
533 outOff = biRas.getDataOffset(0);
534 return ras;
611 rowxerr &= Integer.MAX_VALUE;
612 rowx++;
613 }
614 if ((rowx += rowincx) >= bWidth) {
615 rowx -= bWidth;
616 }
617 if ((rowyerr += rowincyerr) < 0) {
618 rowyerr &= Integer.MAX_VALUE;
619 rowy++;
620 }
621 if ((rowy += rowincy) >= bHeight) {
622 rowy -= bHeight;
623 }
624 out += outSpan;
625 }
626 }
627 }
628
629 static class ByteFilter extends TexturePaintContext {
630 ByteInterleavedRaster srcRas;
631 int[] inPalette;
632 byte[] inData;
633 int inOff;
634 int inSpan;
635 int[] outData;
636 int outOff;
637 int outSpan;
638
639 public ByteFilter(ByteInterleavedRaster srcRas, ColorModel cm,
640 AffineTransform xform, int maxw)
641 {
642 super((cm.getTransparency() == Transparency.OPAQUE
643 ? xrgbmodel : argbmodel),
644 xform, srcRas.getWidth(), srcRas.getHeight(), maxw);
645 this.inPalette = new int[256];
646 ((IndexColorModel) cm).getRGBs(this.inPalette);
647 this.srcRas = srcRas;
648 this.inData = srcRas.getDataStorage();
649 this.inSpan = srcRas.getScanlineStride();
650 this.inOff = srcRas.getDataOffset(0);
651 }
652
653 public WritableRaster makeRaster(int w, int h) {
654 // Note that we do not pass srcRas to makeRaster since it
655 // is a Byte Raster and this colorModel needs an Int Raster
660 outOff = iiRas.getDataOffset(0);
661 return ras;
662 }
663
664 public void setRaster(int x, int y, int xerr, int yerr,
665 int w, int h, int bWidth, int bHeight,
666 int colincx, int colincxerr,
667 int colincy, int colincyerr,
668 int rowincx, int rowincxerr,
669 int rowincy, int rowincyerr) {
670 byte[] inData = this.inData;
671 int[] outData = this.outData;
672 int out = outOff;
673 int inSpan = this.inSpan;
674 int inOff = this.inOff;
675 int outSpan = this.outSpan;
676 int rowx = x;
677 int rowy = y;
678 int rowxerr = xerr;
679 int rowyerr = yerr;
680 int[] rgbs = new int[4];
681 for (int j = 0; j < h; j++) {
682 x = rowx;
683 y = rowy;
684 xerr = rowxerr;
685 yerr = rowyerr;
686 for (int i = 0; i < w; i++) {
687 int nextx, nexty;
688 if ((nextx = x + 1) >= bWidth) {
689 nextx = 0;
690 }
691 if ((nexty = y + 1) >= bHeight) {
692 nexty = 0;
693 }
694 rgbs[0] = inPalette[0xff & inData[inOff + x +
695 inSpan * y]];
696 rgbs[1] = inPalette[0xff & inData[inOff + nextx +
697 inSpan * y]];
698 rgbs[2] = inPalette[0xff & inData[inOff + x +
699 inSpan * nexty]];
700 rgbs[3] = inPalette[0xff & inData[inOff + nextx +
747 this.filter = filter;
748 }
749
750 public WritableRaster makeRaster(int w, int h) {
751 return makeRaster(colorModel, srcRas, w, h);
752 }
753
754 public void setRaster(int x, int y, int xerr, int yerr,
755 int w, int h, int bWidth, int bHeight,
756 int colincx, int colincxerr,
757 int colincy, int colincyerr,
758 int rowincx, int rowincxerr,
759 int rowincy, int rowincyerr) {
760 Object data = null;
761 int rowx = x;
762 int rowy = y;
763 int rowxerr = xerr;
764 int rowyerr = yerr;
765 WritableRaster srcRas = this.srcRas;
766 WritableRaster outRas = this.outRas;
767 int[] rgbs = filter ? new int[4] : null;
768 for (int j = 0; j < h; j++) {
769 x = rowx;
770 y = rowy;
771 xerr = rowxerr;
772 yerr = rowyerr;
773 for (int i = 0; i < w; i++) {
774 data = srcRas.getDataElements(x, y, data);
775 if (filter) {
776 int nextx, nexty;
777 if ((nextx = x + 1) >= bWidth) {
778 nextx = 0;
779 }
780 if ((nexty = y + 1) >= bHeight) {
781 nexty = 0;
782 }
783 rgbs[0] = colorModel.getRGB(data);
784 data = srcRas.getDataElements(nextx, y, data);
785 rgbs[1] = colorModel.getRGB(data);
786 data = srcRas.getDataElements(x, nexty, data);
787 rgbs[2] = colorModel.getRGB(data);
|