// (c): Tuomas J. Lukka package gzz.gfx.gl; import java.util.*; import java.io.File; import java.io.IOException; import java.awt.Point; import java.awt.Dimension; import gzz.mem.*; import gzz.media.PageSpan; import gzz.media.impl.PageImageScroll; import gzz.util.ImageSize; public class GLSpanner { public static boolean dbg = false; private static void pa(String s) { System.err.println(s); } static MemoryPartitioner pool = new MemoryPartitioner(40 * 1024 * 1024); private static class SpanSB { PageImageScroll sb; SpanPage[] pages; SpanSB(PageImageScroll sb) { this.sb = sb; PageSpan sp = (PageSpan)sb.getCurrent(); pages = new SpanPage[sp.length()]; } SpanPage getPage(int i) { if(i < 0 || i >= pages.length) return null; if(pages[i] == null) { pages[i] = new SpanPage(sb, i); } return pages[i]; } } private static class SpanPage { /** The consumer inside which this page is loaded. */ private MipzipMemoryConsumer consumer; /** The width and height of the real page inside * the texture. */ float x1, y1; /** The width and height in pagespan units of the real page. */ int w, h; float getX(int spx) { return spx / (float)w * x1; } float getY(int spy) { return spy / (float)h * y1; } /** Cause the texture to be * requested. * @param importance 0..1, how much focus * this texture has. * @param pixels The maximum measure on screen * of the drawn area. */ public GL.Texture getTexture(float importance, float pixels) { return consumer.getTexture(importance, pixels); } SpanPage(PageImageScroll sb, int page) { String file = sb.imageFilename(page); float resmult = sb.imageFileResolution(page) / sb.coordinateResolution() ; // Get the size of the orig. image Dimension d = ImageSize.readSize(new File(file)); if(d == null) { pa("Image cannot be loaded: "+file); throw new Error(); } w = (int)(d.width / resmult); h = (int)(d.height / resmult); MipzipLoader l; try { l = new MipzipLoader(new File(file+".mipzip")); } catch(IOException e) { throw new Error("ARGH"); } Dimension largest = l.getLevelSize(0); x1 = d.width / (float)largest.width; y1 = d.height / (float)largest.height; consumer = new MipzipMemoryConsumer(pool, l); } } public static class SpanRect { private SpanPage page; /** The coordinates of this rectangle. */ public final float x0, y0, x1, y1; private float pixelmult; /** Cause the texture to be * requested. * @param importance 0..1, how much focus * this texture has. * @param pixels The maximum measure on screen * of the drawn area. */ public GL.Texture getTexture(float importance, float pixels) { return page.getTexture(importance, pixelmult * pixels); } private SpanRect(SpanPage page, PageSpan sp) { this.page = page; Point p =sp.getLocation(); Dimension s =sp.getSize(); x0 = page.getX(p.x); y0 = page.getY(p.y); x1 = page.getX(p.x + s.width); y1 = page.getY(p.y + s.height); pixelmult = (float)Math.max( 1.0 / (.0001 + (x1 - x0)), 1.0 / (.0001 + (y1 - y0))); } } Map span2rect = new WeakHashMap(); Map sb2spansb = new WeakHashMap(); /** Get the texrect for a given pagespan. * This method will return immediately, either * with the texrect for the right texrect or with null, * if no texture is currently obtainable. * @param sp The span * @param importance The importance of the request, to be given to MemoryPartitioner. * 1 = at focus, 0 = very peripheral * @param pixScale The number of pixels per imagespan unit: the resolution needed. */ SpanRect getSpanRect(PageSpan sp, float importance, float pixScale) { SpanRect r = (SpanRect)span2rect.get(sp); if(r == null) { PageImageScroll sb = (PageImageScroll)sp.getScrollBlock(); SpanSB ssb = (SpanSB)sb2spansb.get(sb); if(ssb == null) { ssb = new SpanSB(sb); sb2spansb.put(sb, ssb); } SpanPage p = ssb.getPage(sp.offset()); r = new SpanRect(p, sp); span2rect.put(sp, r); } return r; } }