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