1. /*
  2. * @(#)SyntheticImage.java 1.24 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.swing.colorchooser;
  8. import java.awt.*;
  9. import java.awt.image.*;
  10. /** A helper class to make computing synthetic images a little easier.
  11. * All you need to do is define a subclass that overrides computeRow
  12. * to compute a row of the image. It is passed the y coordinate of the
  13. * row and an array into which to put the pixels in
  14. * <a href="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.image.ColorModel.html#getRGBdefault()">
  15. * standard ARGB format</a>.
  16. * <p>Normal usage looks something like this:
  17. * <pre> Image i = createImage(new SyntheticImage(200, 100) {
  18. *   protected void computeRow(int y, int[] row) {
  19. *   for(int i = width; --i>=0; ) {
  20. *   int grey = i*255/(width-1);
  21. *   row[i] = (255<<24)|(grey<<16)|(grey<<8)|grey;
  22. *   }
  23. *   }
  24. *  }
  25. * </pre>This creates a image 200 pixels wide and 100 pixels high
  26. * that is a horizontal grey ramp, going from black on the left to
  27. * white on the right.
  28. * <p>
  29. * If the image is to be a movie, override isStatic to return false,
  30. * <i>y</i> cycling back to 0 is computeRow's signal that the next
  31. * frame has started. It is acceptable (expected?) for computeRow(0,r)
  32. * to pause until the appropriate time to start the next frame.
  33. *
  34. * @version 1.24 12/19/03
  35. * @author James Gosling
  36. */
  37. abstract class SyntheticImage implements ImageProducer {
  38. private SyntheticImageGenerator root;
  39. protected int width=10, height=100;
  40. static final ColorModel cm = ColorModel.getRGBdefault();
  41. public static final int pixMask = 0xFF;
  42. private Thread runner;
  43. protected SyntheticImage() { }
  44. protected SyntheticImage(int w, int h) { width = w; height = h; }
  45. protected void computeRow(int y, int[] row) {
  46. int p = 255-255*y(height-1);
  47. p = (pixMask<<24)|(p<<16)|(p<<8)|p;
  48. for (int i = row.length; --i>=0; ) row[i] = p;
  49. }
  50. public synchronized void addConsumer(ImageConsumer ic){
  51. for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next)
  52. if (ics.ic == ic) return;
  53. root = new SyntheticImageGenerator(ic, root, this);
  54. }
  55. public synchronized boolean isConsumer(ImageConsumer ic){
  56. for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next)
  57. if (ics.ic == ic) return true;
  58. return false;
  59. }
  60. public synchronized void removeConsumer(ImageConsumer ic) {
  61. SyntheticImageGenerator prev = null;
  62. for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next) {
  63. if (ics.ic == ic) {
  64. ics.useful = false;
  65. if (prev!=null) prev.next = ics.next;
  66. else root = ics.next;
  67. return;
  68. }
  69. prev = ics;
  70. }
  71. }
  72. public synchronized void startProduction(ImageConsumer ic) {
  73. addConsumer(ic);
  74. for (SyntheticImageGenerator ics = root; ics != null; ics = ics.next)
  75. if (ics.useful && !ics.isAlive())
  76. ics.start();
  77. }
  78. protected boolean isStatic() { return true; }
  79. public void nextFrame(int param) {}//Override if !isStatic
  80. public void requestTopDownLeftRightResend(ImageConsumer ic){}
  81. protected volatile boolean aborted = false;
  82. }
  83. class SyntheticImageGenerator extends Thread {
  84. ImageConsumer ic;
  85. boolean useful;
  86. SyntheticImageGenerator next;
  87. SyntheticImage parent;
  88. SyntheticImageGenerator(ImageConsumer ic, SyntheticImageGenerator next,
  89. SyntheticImage parent) {
  90. super("SyntheticImageGenerator");
  91. this.ic = ic;
  92. this.next = next;
  93. this.parent = parent;
  94. useful = true;
  95. setDaemon(true);
  96. }
  97. public void run() {
  98. ImageConsumer ic = this.ic;
  99. int w = parent.width;
  100. int h = parent.height;
  101. int hints = ic.SINGLEPASS|ic.COMPLETESCANLINES|ic.TOPDOWNLEFTRIGHT;
  102. if (parent.isStatic())
  103. hints |= ic.SINGLEFRAME;
  104. ic.setHints(hints);
  105. ic.setDimensions(w, h);
  106. ic.setProperties(null);
  107. ic.setColorModel(parent.cm);
  108. if (useful) {
  109. int[] row=new int[w];
  110. doPrivileged( new Runnable() {
  111. public void run() {
  112. Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
  113. }
  114. });
  115. do {
  116. for (int y = 0; y<h && useful; y++) {
  117. parent.computeRow(y,row);
  118. if (parent.aborted) {
  119. ic.imageComplete(ic.IMAGEABORTED);
  120. return;
  121. }
  122. ic.setPixels(0, y, w, 1, parent.cm, row, 0, w);
  123. }
  124. ic.imageComplete(parent.isStatic() ? ic.STATICIMAGEDONE
  125. : ic.SINGLEFRAMEDONE );
  126. } while(!parent.isStatic() && useful);
  127. }
  128. }
  129. private final static void doPrivileged(final Runnable doRun) {
  130. java.security.AccessController.doPrivileged(
  131. new java.security.PrivilegedAction() {
  132. public Object run() {
  133. doRun.run();
  134. return null;
  135. }
  136. }
  137. );
  138. }
  139. }