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 java.awt; 27 28 import java.awt.Component; 29 import java.awt.Image; 30 import java.awt.image.ImageObserver; 31 import sun.awt.image.MultiResolutionToolkitImage; 32 33 /** 34 * The {@code MediaTracker} class is a utility class to track 35 * the status of a number of media objects. Media objects could 36 * include audio clips as well as images, though currently only 37 * images are supported. 38 * <p> 39 * To use a media tracker, create an instance of 40 * {@code MediaTracker} and call its {@code addImage} 41 * method for each image to be tracked. In addition, each image can 42 * be assigned a unique identifier. This identifier controls the 43 * priority order in which the images are fetched. It can also be used 44 * to identify unique subsets of the images that can be waited on 45 * independently. Images with a lower ID are loaded in preference to 46 * those with a higher ID number. 47 * 48 * <p> 49 * 50 * Tracking an animated image 51 * might not always be useful 207 * (unscaled) size. 208 * @param image the image to be tracked 209 * @param id an identifier used to track this image 210 */ 211 public void addImage(Image image, int id) { 212 addImage(image, id, -1, -1); 213 } 214 215 /** 216 * Adds a scaled image to the list of images being tracked 217 * by this media tracker. The image will eventually be 218 * rendered at the indicated width and height. 219 * 220 * @param image the image to be tracked 221 * @param id an identifier that can be used to track this image 222 * @param w the width at which the image is rendered 223 * @param h the height at which the image is rendered 224 */ 225 public synchronized void addImage(Image image, int id, int w, int h) { 226 addImageImpl(image, id, w, h); 227 Image rvImage = getResolutionVariant(image); 228 if (rvImage != null) { 229 addImageImpl(rvImage, id, 230 w == -1 ? -1 : 2 * w, 231 h == -1 ? -1 : 2 * h); 232 } 233 } 234 235 private void addImageImpl(Image image, int id, int w, int h) { 236 head = MediaEntry.insert(head, 237 new ImageMediaEntry(this, image, id, w, h)); 238 } 239 /** 240 * Flag indicating that media is currently being loaded. 241 * @see java.awt.MediaTracker#statusAll 242 * @see java.awt.MediaTracker#statusID 243 */ 244 public static final int LOADING = 1; 245 246 /** 247 * Flag indicating that the downloading of media was aborted. 248 * @see java.awt.MediaTracker#statusAll 249 * @see java.awt.MediaTracker#statusID 250 */ 251 public static final int ABORTED = 2; 252 253 /** 254 * Flag indicating that the downloading of media encountered 715 while (cur != null) { 716 if (cur.getID() == id) { 717 status = status | cur.getStatus(load, verify); 718 } 719 cur = cur.next; 720 } 721 return status; 722 } 723 724 /** 725 * Removes the specified image from this media tracker. 726 * All instances of the specified image are removed, 727 * regardless of scale or ID. 728 * @param image the image to be removed 729 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int) 730 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int) 731 * @since 1.1 732 */ 733 public synchronized void removeImage(Image image) { 734 removeImageImpl(image); 735 Image rvImage = getResolutionVariant(image); 736 if (rvImage != null) { 737 removeImageImpl(rvImage); 738 } 739 notifyAll(); // Notify in case remaining images are "done". 740 } 741 742 private void removeImageImpl(Image image) { 743 MediaEntry cur = head; 744 MediaEntry prev = null; 745 while (cur != null) { 746 MediaEntry next = cur.next; 747 if (cur.getMedia() == image) { 748 if (prev == null) { 749 head = next; 750 } else { 751 prev.next = next; 752 } 753 cur.cancel(); 754 } else { 755 prev = cur; 756 } 757 cur = next; 758 } 759 } 760 761 /** 762 * Removes the specified image from the specified tracking 763 * ID of this media tracker. 764 * All instances of {@code Image} being tracked 765 * under the specified ID are removed regardless of scale. 766 * @param image the image to be removed 767 * @param id the tracking ID from which to remove the image 768 * @see java.awt.MediaTracker#removeImage(java.awt.Image) 769 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int) 770 * @since 1.1 771 */ 772 public synchronized void removeImage(Image image, int id) { 773 removeImageImpl(image, id); 774 Image rvImage = getResolutionVariant(image); 775 if (rvImage != null) { 776 removeImageImpl(rvImage, id); 777 } 778 notifyAll(); // Notify in case remaining images are "done". 779 } 780 781 private void removeImageImpl(Image image, int id) { 782 MediaEntry cur = head; 783 MediaEntry prev = null; 784 while (cur != null) { 785 MediaEntry next = cur.next; 786 if (cur.getID() == id && cur.getMedia() == image) { 787 if (prev == null) { 788 head = next; 789 } else { 790 prev.next = next; 791 } 792 cur.cancel(); 793 } else { 794 prev = cur; 795 } 796 cur = next; 797 } 798 } 799 800 /** 801 * Removes the specified image with the specified 802 * width, height, and ID from this media tracker. 803 * Only the specified instance (with any duplicates) is removed. 804 * @param image the image to be removed 805 * @param id the tracking ID from which to remove the image 806 * @param width the width to remove (-1 for unscaled) 807 * @param height the height to remove (-1 for unscaled) 808 * @see java.awt.MediaTracker#removeImage(java.awt.Image) 809 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int) 810 * @since 1.1 811 */ 812 public synchronized void removeImage(Image image, int id, 813 int width, int height) { 814 removeImageImpl(image, id, width, height); 815 Image rvImage = getResolutionVariant(image); 816 if (rvImage != null) { 817 removeImageImpl(rvImage, id, 818 width == -1 ? -1 : 2 * width, 819 height == -1 ? -1 : 2 * height); 820 } 821 notifyAll(); // Notify in case remaining images are "done". 822 } 823 824 private void removeImageImpl(Image image, int id, int width, int height) { 825 MediaEntry cur = head; 826 MediaEntry prev = null; 827 while (cur != null) { 828 MediaEntry next = cur.next; 829 if (cur.getID() == id && cur instanceof ImageMediaEntry 830 && ((ImageMediaEntry) cur).matches(image, width, height)) 831 { 832 if (prev == null) { 833 head = next; 834 } else { 835 prev.next = next; 836 } 837 cur.cancel(); 838 } else { 839 prev = cur; 840 } 841 cur = next; 842 } 843 } 844 845 synchronized void setDone() { 846 notifyAll(); 847 } 848 849 private static Image getResolutionVariant(Image image) { 850 if (image instanceof MultiResolutionToolkitImage) { 851 return ((MultiResolutionToolkitImage) image).getResolutionVariant(); 852 } 853 return null; 854 } 855 } 856 857 abstract class MediaEntry { 858 MediaTracker tracker; 859 int ID; 860 MediaEntry next; 861 862 int status; 863 boolean cancelled; 864 865 MediaEntry(MediaTracker mt, int id) { 866 tracker = mt; 867 ID = id; 868 } 869 870 abstract Object getMedia(); 871 872 static MediaEntry insert(MediaEntry head, MediaEntry me) { 873 MediaEntry cur = head; | 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 java.awt; 27 28 import java.awt.Component; 29 import java.awt.Image; 30 import java.awt.image.ImageObserver; 31 import sun.awt.image.MultiResolutionToolkitImage; 32 import java.util.stream.Stream; 33 import java.util.List; 34 import sun.awt.image.MultiResolutionToolkitImage.ResolutionVariantItem; 35 36 /** 37 * The {@code MediaTracker} class is a utility class to track 38 * the status of a number of media objects. Media objects could 39 * include audio clips as well as images, though currently only 40 * images are supported. 41 * <p> 42 * To use a media tracker, create an instance of 43 * {@code MediaTracker} and call its {@code addImage} 44 * method for each image to be tracked. In addition, each image can 45 * be assigned a unique identifier. This identifier controls the 46 * priority order in which the images are fetched. It can also be used 47 * to identify unique subsets of the images that can be waited on 48 * independently. Images with a lower ID are loaded in preference to 49 * those with a higher ID number. 50 * 51 * <p> 52 * 53 * Tracking an animated image 54 * might not always be useful 210 * (unscaled) size. 211 * @param image the image to be tracked 212 * @param id an identifier used to track this image 213 */ 214 public void addImage(Image image, int id) { 215 addImage(image, id, -1, -1); 216 } 217 218 /** 219 * Adds a scaled image to the list of images being tracked 220 * by this media tracker. The image will eventually be 221 * rendered at the indicated width and height. 222 * 223 * @param image the image to be tracked 224 * @param id an identifier that can be used to track this image 225 * @param w the width at which the image is rendered 226 * @param h the height at which the image is rendered 227 */ 228 public synchronized void addImage(Image image, int id, int w, int h) { 229 addImageImpl(image, id, w, h); 230 231 if (image instanceof MultiResolutionToolkitImage) { 232 getRVItems(image).forEach(rvItem -> 233 addImageImpl(rvItem.getImage(), id, 234 scale(w, rvItem.getScaleX()), 235 scale(h, rvItem.getScaleY()) 236 )); 237 } 238 } 239 240 private static int scale(int size, double scale) { 241 return (size == -1 || scale == 1) ? size : (int) Math.ceil(scale * size); 242 } 243 244 private void addImageImpl(Image image, int id, int w, int h) { 245 head = MediaEntry.insert(head, 246 new ImageMediaEntry(this, image, id, w, h)); 247 } 248 /** 249 * Flag indicating that media is currently being loaded. 250 * @see java.awt.MediaTracker#statusAll 251 * @see java.awt.MediaTracker#statusID 252 */ 253 public static final int LOADING = 1; 254 255 /** 256 * Flag indicating that the downloading of media was aborted. 257 * @see java.awt.MediaTracker#statusAll 258 * @see java.awt.MediaTracker#statusID 259 */ 260 public static final int ABORTED = 2; 261 262 /** 263 * Flag indicating that the downloading of media encountered 724 while (cur != null) { 725 if (cur.getID() == id) { 726 status = status | cur.getStatus(load, verify); 727 } 728 cur = cur.next; 729 } 730 return status; 731 } 732 733 /** 734 * Removes the specified image from this media tracker. 735 * All instances of the specified image are removed, 736 * regardless of scale or ID. 737 * @param image the image to be removed 738 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int) 739 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int) 740 * @since 1.1 741 */ 742 public synchronized void removeImage(Image image) { 743 removeImageImpl(image); 744 if (image instanceof MultiResolutionToolkitImage) { 745 getRVItems(image).forEach(rvItem -> 746 removeImageImpl(rvItem.getImage())); 747 } 748 notifyAll(); // Notify in case remaining images are "done". 749 } 750 751 private void removeImageImpl(Image image) { 752 MediaEntry cur = head; 753 MediaEntry prev = null; 754 while (cur != null) { 755 MediaEntry next = cur.next; 756 if (cur.getMedia() == image) { 757 if (prev == null) { 758 head = next; 759 } else { 760 prev.next = next; 761 } 762 cur.cancel(); 763 } else { 764 prev = cur; 765 } 766 cur = next; 767 } 768 } 769 770 /** 771 * Removes the specified image from the specified tracking 772 * ID of this media tracker. 773 * All instances of {@code Image} being tracked 774 * under the specified ID are removed regardless of scale. 775 * @param image the image to be removed 776 * @param id the tracking ID from which to remove the image 777 * @see java.awt.MediaTracker#removeImage(java.awt.Image) 778 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int) 779 * @since 1.1 780 */ 781 public synchronized void removeImage(Image image, int id) { 782 removeImageImpl(image, id); 783 784 if (image instanceof MultiResolutionToolkitImage) { 785 getRVItems(image).forEach(rvItem -> 786 removeImageImpl(rvItem.getImage(), id)); 787 } 788 notifyAll(); // Notify in case remaining images are "done". 789 } 790 791 private void removeImageImpl(Image image, int id) { 792 MediaEntry cur = head; 793 MediaEntry prev = null; 794 while (cur != null) { 795 MediaEntry next = cur.next; 796 if (cur.getID() == id && cur.getMedia() == image) { 797 if (prev == null) { 798 head = next; 799 } else { 800 prev.next = next; 801 } 802 cur.cancel(); 803 } else { 804 prev = cur; 805 } 806 cur = next; 807 } 808 } 809 810 /** 811 * Removes the specified image with the specified 812 * width, height, and ID from this media tracker. 813 * Only the specified instance (with any duplicates) is removed. 814 * @param image the image to be removed 815 * @param id the tracking ID from which to remove the image 816 * @param width the width to remove (-1 for unscaled) 817 * @param height the height to remove (-1 for unscaled) 818 * @see java.awt.MediaTracker#removeImage(java.awt.Image) 819 * @see java.awt.MediaTracker#removeImage(java.awt.Image, int) 820 * @since 1.1 821 */ 822 public synchronized void removeImage(Image image, int id, 823 int width, int height) { 824 removeImageImpl(image, id, width, height); 825 826 if (image instanceof MultiResolutionToolkitImage) { 827 828 getRVItems(image).forEach(rvItem -> 829 removeImageImpl(rvItem.getImage(), id, 830 scale(width, rvItem.getScaleX()), 831 scale(height, rvItem.getScaleY()) 832 )); 833 } 834 notifyAll(); // Notify in case remaining images are "done". 835 } 836 837 private void removeImageImpl(Image image, int id, int width, int height) { 838 MediaEntry cur = head; 839 MediaEntry prev = null; 840 while (cur != null) { 841 MediaEntry next = cur.next; 842 if (cur.getID() == id && cur instanceof ImageMediaEntry 843 && ((ImageMediaEntry) cur).matches(image, width, height)) 844 { 845 if (prev == null) { 846 head = next; 847 } else { 848 prev.next = next; 849 } 850 cur.cancel(); 851 } else { 852 prev = cur; 853 } 854 cur = next; 855 } 856 } 857 858 synchronized void setDone() { 859 notifyAll(); 860 } 861 862 private static Stream<ResolutionVariantItem> getRVItems(Image image) { 863 return ((MultiResolutionToolkitImage) image) 864 .getResolutionVariantItems().stream(); 865 } 866 } 867 868 abstract class MediaEntry { 869 MediaTracker tracker; 870 int ID; 871 MediaEntry next; 872 873 int status; 874 boolean cancelled; 875 876 MediaEntry(MediaTracker mt, int id) { 877 tracker = mt; 878 ID = id; 879 } 880 881 abstract Object getMedia(); 882 883 static MediaEntry insert(MediaEntry head, MediaEntry me) { 884 MediaEntry cur = head; |