/* * $Id: Cache.java,v 1.4 2009-02-12 13:53:56 tomoke Exp $ * * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ package com.sun.pdfview; import java.awt.image.BufferedImage; import java.lang.ref.SoftReference; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * A cache of PDF pages and images. */ public class Cache { /** the pages in the cache, mapped by page number */ private Map<Integer,SoftReference> pages; /** Creates a new instance of a Cache */ public Cache() { pages = Collections.synchronizedMap(new HashMap<Integer,SoftReference>()); } /** * Add a page to the cache. This method should be used for * pages which have already been completely rendered. * * @param pageNumber the page number of this page * @param page the page to add */ public void addPage(Integer pageNumber, PDFPage page) { addPageRecord(pageNumber, page, null); } /** * Add a page to the cache. This method should be used for * pages which are still in the process of being rendered. * * @param pageNumber the page number of this page * @param page the page to add * @param parser the parser which is parsing this page */ public void addPage(Integer pageNumber, PDFPage page, PDFParser parser) { addPageRecord(pageNumber, page, parser); } /** * Add an image to the cache. This method should be used for images * which have already been completely rendered * * @param page page this image is associated with * @param info the image info associated with this image * @param image the image to add */ public void addImage(PDFPage page, ImageInfo info, BufferedImage image) { addImageRecord(page, info, image, null); } /** * Add an image to the cache. This method should be used for images * which are still in the process of being rendered. * * @param page the page this image is associated with * @param info the image info associated with this image * @param image the image to add * @param renderer the renderer which is rendering this page */ public void addImage(PDFPage page, ImageInfo info, BufferedImage image, PDFRenderer renderer) { addImageRecord(page, info, image, renderer); } /** * Get a page from the cache * * @param pageNumber the number of the page to get * @return the page, if it is in the cache, or null if not */ public PDFPage getPage(Integer pageNumber) { PageRecord rec = getPageRecord(pageNumber); if (rec != null) { return (PDFPage) rec.value; } // not found return null; } /** * Get a page's parser from the cache * * @param pageNumber the number of the page to get the parser for * @return the parser, or null if it is not in the cache */ public PDFParser getPageParser(Integer pageNumber) { PageRecord rec = getPageRecord(pageNumber); if (rec != null) { return (PDFParser) rec.generator; } // not found return null; } /** * Get an image from the cache * * @param page the page the image is associated with * @param info the image info that describes the image * * @return the image if it is in the cache, or null if not */ public BufferedImage getImage(PDFPage page, ImageInfo info) { Record rec = getImageRecord(page, info); if (rec != null) { return (BufferedImage) rec.value; } // not found return null; } /** * Get an image's renderer from the cache * * @param page the page this image was generated from * @param info the image info describing the image * @return the renderer, or null if it is not in the cache */ public PDFRenderer getImageRenderer(PDFPage page, ImageInfo info) { Record rec = getImageRecord(page, info); if (rec != null) { return (PDFRenderer) rec.generator; } // not found return null; } /** * Remove a page and all its associated images, as well as its parser * and renderers, from the cache * * @param pageNumber the number of the page to remove */ public void removePage(Integer pageNumber) { removePageRecord(pageNumber); } /** * Remove an image and its associated renderer from the cache * * @param page the page the image is generated from * @param info the image info of the image to remove */ public void removeImage(PDFPage page, ImageInfo info) { removeImageRecord(page, info); } /** * The internal routine to add a page to the cache, and return the * page record which was generated */ PageRecord addPageRecord(Integer pageNumber, PDFPage page, PDFParser parser) { PageRecord rec = new PageRecord(); rec.value = page; rec.generator = parser; pages.put(pageNumber, new SoftReference<Record>(rec)); return rec; } /** * Get a page's record from the cache * * @return the record, or null if it's not in the cache */ PageRecord getPageRecord(Integer pageNumber) { // System.out.println("Request for page " + pageNumber); SoftReference ref = pages.get(pageNumber); if (ref != null) { String val = (ref.get() == null) ? " not in " : " in "; // System.out.println("Page " + pageNumber + val + "cache"); return (PageRecord) ref.get(); } // System.out.println("Page " + pageNumber + " not in cache"); // not in cache return null; } /** * Remove a page's record from the cache */ PageRecord removePageRecord(Integer pageNumber) { SoftReference ref = pages.remove(pageNumber); if (ref != null) { return (PageRecord) ref.get(); } // not in cache return null; } /** * The internal routine to add an image to the cache and return the * record that was generated. */ Record addImageRecord(PDFPage page, ImageInfo info, BufferedImage image, PDFRenderer renderer) { // first, find or create the relevant page record Integer pageNumber = new Integer(page.getPageNumber()); PageRecord pageRec = getPageRecord(pageNumber); if (pageRec == null) { pageRec = addPageRecord(pageNumber, page, null); } // next, create the image record Record rec = new Record(); rec.value = image; rec.generator = renderer; // add it to the cache pageRec.images.put(info, new SoftReference<Record>(rec)); return rec; } /** * Get an image's record from the cache * * @return the record, or null if it's not in the cache */ Record getImageRecord(PDFPage page, ImageInfo info) { // first find the relevant page record Integer pageNumber = new Integer(page.getPageNumber()); // System.out.println("Request for image on page " + pageNumber); PageRecord pageRec = getPageRecord(pageNumber); if (pageRec != null) { SoftReference ref = pageRec.images.get(info); if (ref != null) { String val = (ref.get() == null) ? " not in " : " in "; // System.out.println("Image on page " + pageNumber + val + " cache"); return (Record) ref.get(); } } // System.out.println("Image on page " + pageNumber + " not in cache"); // not found return null; } /** * Remove an image's record from the cache */ Record removeImageRecord(PDFPage page, ImageInfo info) { // first find the relevant page record Integer pageNumber = new Integer(page.getPageNumber()); PageRecord pageRec = getPageRecord(pageNumber); if (pageRec != null) { SoftReference ref = pageRec.images.remove(info); if (ref != null) { return (Record) ref.get(); } } return null; } /** the basic information about a page or image */ class Record { /** the page or image itself */ Object value; /** the thing generating the page, or null if done/not provided */ BaseWatchable generator; } /** the record stored for each page in the cache */ class PageRecord extends Record { /** any images associated with the page */ Map<ImageInfo, SoftReference<Record>> images; /** create a new page record */ public PageRecord() { images = Collections.synchronizedMap(new HashMap<ImageInfo, SoftReference<Record>>()); } } }