/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.g2d.image; import java.net.URL; import org.simantics.g2d.image.impl.CacheProvider; import org.simantics.g2d.image.impl.ImageBundleFactory; import org.simantics.g2d.image.impl.ImageProxy; import org.simantics.g2d.image.impl.ImageURLFactory; import org.simantics.g2d.image.impl.ProviderAsyncronizer; import org.simantics.g2d.image.impl.ProviderProxier; import org.simantics.g2d.image.impl.RasterizingProvider; import org.simantics.utils.datastructures.cache.IFactory; import org.simantics.utils.datastructures.cache.IProvider; import org.simantics.utils.datastructures.cache.WeakCachedProvider; /** * Image Provider Utilities offers methods for constructing chains of * provider {@link Image} providers. *

* The nature of IProvider<Image> is at the same time * (a) description of the source of an image * e.g. at("https://www.simantics.org/simantics/simantics/logo.jpg") * * (b) method of acquiring the image from its source * e.g. Image i = provider.get(); *

* IProviders are equals-comparable and can be used as keys in a map. * eg. *

 *   map.put( at("https://www.simantics.org/simantics/simantics/logo.jpg"), obj1 );
 *   ...
 *   Object obj2 = map.get( at("https://www.simantics.org/simantics/simantics/logo.jpg") );
 * 
*

* The difference between IProvider<Image> and IFactory<Image> is Factory * always constructs a new instance and provider may either instantiate new instance * or return cached result. * * In typical scenario the result of IFactory<Image> is cached using cacheResult(). * The cached result is stored weakly and therefore strong references are required. * proxy() adds strong reference ({@link ImageProxy}) factory. *

* Example: *

 *  IFactory<Image> prov = reference(weakCache(rasterize(asynchronize(at("https://www.simantics.org/simantics/simantics/logo.jpg")))));
 * 
 *  Image handle = prov.get();
 *  handle.addImageListener();
 *  handle.paint();
 *  handle = null;
 * 
* * handle instance would be a composition of the following instances: *
 *    ImageProxy
 *      AsyncImage
 *        AWTImage
 *          java.awt.image.BufferedImage
 *  
* * @See {@link ImageUtils} * @author Toni Kalajainen */ public class ProviderUtils { /** * Create provider that retrieves symbol from URL. * Bitmap and SVG symbols are supported. The format of the image is determined * by the suffix of the url. * * @param url * @return */ public static IFactory at(URL url) { return new ImageURLFactory(url); } /** * Create image from bundle address. The bundle address is in format: * "" * Image type is determined from the suffix (.svg .png .jpg etc supported). * * @param filename bundle address * @return bundle image constructor */ public static IFactory bundle(String filename) { return new ImageBundleFactory(filename); } /** * Caches the result of the provided image with a weak reference. * The cached result will be garbage collected with out strong reference * (See reference() ). * * @return cache */ public static IProvider cache(IProvider provider) { return WeakCachedProvider.cache(provider); } /** * Creates a memory buffer backed raster of provided vector based image. * For non-vector images this provider changes nothing. * * @param prov image provider * @return provider that rasterizes the image */ public static IFactory rasterize(IProvider prov) { return new RasterizingProvider(prov); } /** * Converts provider into asynchronized provider. It returns non-blocking result * while at the same time acquires the actual image of the source provider * in a thread. Once the image is complete the content of the result will be changed. * Due to this model, the result is Volatile. * * @param prov original provider * @return asynchronous provider (constructs new image every time) */ public static IFactory asynchronize(IProvider prov) { return new ProviderAsyncronizer(prov); } /** * Adds a strong reference (proxy instance) to the provider chain. * Proxy handles are used with cache to ensure strong references to the * weakly cached result. * * @param prov original provider (cache provider) * @return asynchronous provider (constructs new image every time) */ public static IFactory reference(IProvider prov) { return new ProviderProxier(prov); } /** * Caches the constructed image weakly. Use proxy provider to create * strong references to the cached image. * * @param prov * @return caching provider */ public static IProvider cache(IFactory prov) { return new CacheProvider(prov); } /** * Convenience method that * 1. acquires image asynchronously in a thread * 2. rasterizes the image to memory buffer, if necessary (it is vector format) * 3. caches the resulted image * 4. creates a strong reference for the cached image * * The result of the factory instantiates proxy handles. * Proxy handle returns constructed or cached image. * The underlying image will be remain in memory until all handles are * released (nulled). * * Usage example: * IFactory i = convenience( at("https://www.simantics.org/simantics/simantics/logo.jpg") ); * i.paint(); * i = null; * * @param originalFactory * @return factory that instantiates disposable (nullable) handles */ public static IFactory convenience(IFactory originalFactory) { return reference(cache(rasterize(asynchronize(originalFactory)))); } public static IFactory convenience(URL url) { return reference(cache(rasterize(asynchronize(at(url))))); } public static IFactory convenience(String bundleAddress) { return reference(cache(rasterize(asynchronize(bundle(bundleAddress))))); } }