+++ /dev/null
-/*
- * Copyright (c) 2009, Takeyuki Nagao
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the
- * following conditions are met:
- *
- * * Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the
- * following disclaimer in the documentation and/or other
- * materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
- * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
- * OF SUCH DAMAGE.
- */
-
-package jp.sourceforge.dvibrowser.dvicore.ctx;
-
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-import java.security.AccessControlException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.TreeSet;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.logging.Logger;
-
-import jp.sourceforge.dvibrowser.dvicore.DviException;
-import jp.sourceforge.dvibrowser.dvicore.DviFontSpec;
-import jp.sourceforge.dvibrowser.dvicore.DviPaperSize;
-import jp.sourceforge.dvibrowser.dvicore.DviResolution;
-import jp.sourceforge.dvibrowser.dvicore.MetafontMode;
-import jp.sourceforge.dvibrowser.dvicore.api.CharacterCodeMapper;
-import jp.sourceforge.dvibrowser.dvicore.api.DevicePainter;
-import jp.sourceforge.dvibrowser.dvicore.api.DviContext;
-import jp.sourceforge.dvibrowser.dvicore.api.DviData;
-import jp.sourceforge.dvibrowser.dvicore.api.DviDocument;
-import jp.sourceforge.dvibrowser.dvicore.api.DviExecutor;
-import jp.sourceforge.dvibrowser.dvicore.api.DviExecutorHandler;
-import jp.sourceforge.dvibrowser.dvicore.api.DviFont;
-import jp.sourceforge.dvibrowser.dvicore.api.FullMetrics;
-import jp.sourceforge.dvibrowser.dvicore.api.Glyph;
-import jp.sourceforge.dvibrowser.dvicore.api.SimpleMetrics;
-import jp.sourceforge.dvibrowser.dvicore.doc.DirectFileDviDocument;
-import jp.sourceforge.dvibrowser.dvicore.doc.StreamDviDocument;
-import jp.sourceforge.dvibrowser.dvicore.doc.URLDviDocument;
-import jp.sourceforge.dvibrowser.dvicore.font.DviFontResolver;
-import jp.sourceforge.dvibrowser.dvicore.font.FullMetricsResolver;
-import jp.sourceforge.dvibrowser.dvicore.font.LogicalFont;
-import jp.sourceforge.dvibrowser.dvicore.gs.GhostscriptUtils;
-import jp.sourceforge.dvibrowser.dvicore.render.BasicExecutor;
-import jp.sourceforge.dvibrowser.dvicore.render.DefaultDevicePainter;
-import jp.sourceforge.dvibrowser.dvicore.util.DviCache;
-import jp.sourceforge.dvibrowser.dvicore.util.DviUtils;
-import jp.sourceforge.dvibrowser.dvicore.util.concurrent.Computation;
-import jp.sourceforge.dvibrowser.dvicore.util.progress.ManagedProgressItem;
-import jp.sourceforge.dvibrowser.dvicore.util.progress.ProgressRecorder;
-
-
-public class DefaultDviContext
-implements DviContext
-{
- private static final Logger LOGGER = Logger.getLogger(DefaultDviContext.class.getName());
-
- private static final String DVICORE_INTERNAL_FILENAME_PREFIX = "dvicore-";
-
- private final Map<String, Glyph> glyphCache = new DviCache<String, Glyph>(16384);
- private final CharacterCodeMapper characterCodeMapper
- = new SimpleJisToUnicodeMapper();
-
- private boolean recordResources = false;
- private final Set<URL> resources = new TreeSet<URL>(new Comparator<URL>() {
- public int compare(URL arg0, URL arg1) {
- return arg0.toString().compareTo(arg1.toString());
- }
- });
-
- private final ProgressRecorder recorder = new ProgressRecorder(this) {
- @Override
- protected boolean removeEldestElement(ManagedProgressItem item)
- {
- List<ManagedProgressItem> list = getProgressItems();
- if (list.size() > 10) {
- return true;
- }
- return false;
- }
- };
-
- private AsyncComputers asyncComputers;
-
-
- public DefaultDviContext()
- throws DviException
- {
- this(null);
- }
-
- public DefaultDviContext(Properties prop)
- throws DviException
- {
- if (prop == null)
- prop = getDefaultProperties();
- this.prop = prop;
- initializeComputers();
- initializeFontMapper();
- populatePaperSizes();
- initializeDirs();
- }
-
- protected void initializeComputers() {
- this.setAsyncComputers(new AsyncComputers(prop));
- }
-
- protected void initializeDirs()
- throws DviException
- {
- File cacheDir = getCacheDirectory();
- if (cacheDir != null && !cacheDir.exists()) {
- if (!cacheDir.mkdirs()) {
- throw new DviException("Failed to create cache directory: " + cacheDir);
- }
- }
- File tmpDir = getTemporaryDirectory();
- if (tmpDir != null && !tmpDir.exists()) {
- if (!tmpDir.mkdirs()) {
- throw new DviException("Failed to create temporary directory: " + tmpDir);
- }
- }
- }
-
- protected Properties getDefaultProperties()
- throws DviException
- {
- try {
- URL url = DefaultDviContext.class.getResource("default-context.properties");
- Properties prop = new Properties();
- if (null != url) {
- prop.load(url.openStream());
- } else {
- LOGGER.warning("Failed to load default-context.properties");
- }
- return prop;
- } catch (Exception e) {
- throw new DviException(e);
- }
- }
-
- private final Properties prop;
-
- public Properties getProperties()
- {
- return prop;
- }
-
- public void execute(DviData data, DviExecutorHandler handler)
- throws DviException
- {
- newDviExecutor().execute(data, handler);
- }
-
-// TODO: delete
-// private static final CachedComputer<String, Collection<DviFont>> dviFontComputer
-// = new CachedComputer<String, Collection<DviFont>>
-// (new ThreadedComputer<String, Collection<DviFont>>(1)) {
-// @Override
-// protected boolean removeEldestEntry(Map.Entry<String, CacheEntry<String, Collection<DviFont>>> entry)
-// {
-// boolean remove = getCache().size() > 64;
-// return remove;
-// }
-// };
-
- public DviFont findDviFont(LogicalFont logicalFont) throws DviException
- {
- Computation<String, Collection<DviFont>> computation
- = new DviFontResolver(this, logicalFont);
- try {
- Collection<DviFont> fonts = getAsyncComputers().getDviFontComputer()
- .compute(computation).get();
- for (DviFont font : fonts) {
- return font;
- }
- return null;
- } catch (InterruptedException e) {
- throw new DviException(e);
- } catch (ExecutionException e) {
- throw new DviException(e);
- }
- }
-
- public SimpleMetrics findDviSimpleMetrics(DviFontSpec fs) throws DviException
- {
- return findDviFullMetrics(fs);
- }
-
-// private static final CachedComputer<String, Collection<FullMetrics>> fullMetricsComputer
-// = new CachedComputer<String, Collection<FullMetrics>>
-// (new ThreadedComputer<String, Collection<FullMetrics>>(1));
-
- public FullMetrics findDviFullMetrics(DviFontSpec fs) throws DviException
- {
- Computation<String, Collection<FullMetrics>> computation = new FullMetricsResolver(
- this, fs);
- try {
- Collection<FullMetrics> fonts = getAsyncComputers().getFullMetricsComputer()
- .compute(computation).get();
- if (fonts != null) {
- for (FullMetrics font : fonts) {
- return font;
- }
- }
- return null;
- } catch (InterruptedException e) {
- throw new DviException(e);
- } catch (ExecutionException e) {
- throw new DviException(e);
- }
- }
-
- public CharacterCodeMapper getCharacterCodeMapper(LogicalFont logicalFont) throws DviException
- {
- return characterCodeMapper;
- }
-
- public DviContext getDviContext() { return this; }
-
- public Map<String, Glyph> getGlyphCache() throws DviException
- {
- return Collections.synchronizedMap(glyphCache);
- }
-
- protected void initializeFontMapper()
- {
- }
-
- public DevicePainter newDevicePainter() throws DviException
- {
- return new DefaultDevicePainter(this);
- }
-
- public DviExecutor newDviExecutor() throws DviException
- {
- return new BasicExecutor(this);
- }
-
- public DviDocument openDviDocument(File file) throws DviException
- {
- return new DirectFileDviDocument(this, file);
- }
-
- public DviDocument openDviDocument(InputStream is) throws DviException
- {
- return new StreamDviDocument(this, is);
- }
-
- // TODO: implement async resource loading
- public DviDocument openDviDocument(URL url) throws DviException
- {
- return new URLDviDocument(this, url);
- }
-
- public ProgressRecorder getProgressRecorder()
- {
- return recorder;
- }
-
- private static final Map<String, DviPaperSize> paperSizes = new TreeMap<String, DviPaperSize>();
-
- protected void populatePaperSizes()
- {
- // ISO 216 sizes
- // TODO: implement B and C serieses. A4 Japanese, too.
- // TOOD: outsource the configuration.
- addPaperSize(new DviPaperSize(841.0, 1189.0, "A0"));
- addPaperSize(new DviPaperSize(594.0, 841.0, "A1"));
- addPaperSize(new DviPaperSize(420.0, 594.0, "A2"));
- addPaperSize(new DviPaperSize(297.0, 420.0, "A3"));
- addPaperSize(new DviPaperSize(210.0, 297.0, "A4"));
- addPaperSize(new DviPaperSize(148.0, 210.0, "A5"));
- addPaperSize(new DviPaperSize(105.0, 148.0, "A6"));
- addPaperSize(new DviPaperSize(74.0, 105.0, "A7"));
- addPaperSize(new DviPaperSize(52.0, 74.0, "A8"));
- addPaperSize(new DviPaperSize(37.0, 52.0, "A9"));
- addPaperSize(new DviPaperSize(26.0, 37.0, "A10"));
- }
-
- protected void addPaperSize(DviPaperSize dviPaperSize)
- {
- if (dviPaperSize == null) return;
- paperSizes.put(dviPaperSize.description().toLowerCase(), dviPaperSize);
- }
-
- public DviPaperSize findPaperSizeByName(String name) throws DviException
- {
- if (name == null) return null;
- return paperSizes.get(name.toLowerCase());
- }
-
- public DviPaperSize getDefaultPaperSize() throws DviException
- {
- return findPaperSizeByName("A4");
- }
-
- public DviPaperSize [] listPaperSizes() throws DviException
- {
- return paperSizes.values().toArray(new DviPaperSize[0]);
- }
-
- private static final DviResolution defaultResolution = new DviResolution(2400, 20);
-
- public DviResolution getDefaultResolution() throws DviException
- {
- return defaultResolution;
- }
-
-// TODO: delete
-// private static final CachedComputer<String, Collection<URL>> dviResourceComputer
-// = new CachedComputer<String, Collection<URL>>
-// (new ThreadedComputer<String, Collection<URL>>(1));
-
- public URL getDviResource(String filename) throws DviException
- {
- if (filename.startsWith(DVICORE_INTERNAL_FILENAME_PREFIX)) {
- // The resource name starting with "dvicore-" are only for internal use.
- // So there is no local file corresponding to such a filename.
- // We answer null.
- return null;
- }
-
- Computation<String, Collection<URL>> c
- = new FileLocationResolver(this, "/dvi/builtin", filename);
- final Future<Collection<URL>> future
- = getAsyncComputers().getDviResourceComputer().compute(c);
- try {
- final Collection<URL> list = future.get();
- for (URL url : list) {
- if (recordResources) {
- LOGGER.info("resolved resource: filename=" + filename + " url=" + url);
- resources.add(url);
- } else {
- LOGGER.finest("resolved resource: filename=" + filename + " url=" + url);
- }
- return url;
- }
- return null;
- } catch (InterruptedException e) {
- LOGGER.warning(e.toString());
- throw new DviException(e);
- } catch (ExecutionException e) {
- LOGGER.warning(e.toString());
- throw new DviException(e);
- }
- }
-
- public LogicalFont mapLogicalFont(LogicalFont logicalFont)
- throws DviException
- {
- LogicalFont mapped = logicalFont;
- if (logicalFont != null) {
- String prefix = getClass().getName();
- String faceKey = prefix + ".fontMap." + logicalFont.fontSpec().name();
- LOGGER.info("Face key: " + faceKey);
- String face = getProperties().getProperty(faceKey);
- LOGGER.info("Properties: " + getProperties());
- if (face != null) {
- mapped = logicalFont.renameTo(face);
- LOGGER.info("Rename logical font: " + logicalFont + " => " + mapped);
- }
- }
- LOGGER.info("Map logical font: " + logicalFont + " => " + mapped);
- return mapped;
- }
-
- // N.B. System.getProperty() throws an exception when invoked
- // from inside an applet.
- private static String getSystemProperty(String key) {
- try {
- return System.getProperty(key);
- } catch (AccessControlException ex) {
- return null;
- }
- }
-
- private static final String userDir = getSystemProperty("user.dir");
- private static final String ioTmpDir = getSystemProperty("java.io.tmpdir");
-
- // TODO: externalize the string "dvibrowser.jar".
- public File getApplicationHomeDir()
- throws DviException
- {
- if (userDir != null) {
- File home = new File(userDir);
- File markFile = new File(home, "dvibrowser.jar");
- if (markFile.exists()) {
- // It seems that we are using DviContext from within dvibrowser.
- return home;
- }
- }
- return null;
- }
-
- public File getCacheDirectory() throws DviException
- {
- File appHome = getApplicationHomeDir();
- if (appHome == null) {
- File tmpDir = getTemporaryDirectory();
- if (tmpDir != null) {
- return new File(tmpDir, "cache");
- }
- } else {
- if (userDir != null) {
- File var = new File(userDir, "var");
- return new File(var, "cache");
- }
- }
- return null;
- }
-
- public File getTemporaryDirectory() throws DviException
- {
- File appHome = getApplicationHomeDir();
- if (appHome == null) {
- if (ioTmpDir != null) {
- return new File(ioTmpDir, "dvicontext");
- }
- } else {
- return new File(appHome, "tmp");
- }
- return null;
- }
-
- private volatile String [] ghostscriptExecutables = null;
-
- public String getExecutableName(String name) throws DviException
- {
- if ("gs".equals(name)) {
- if (ghostscriptExecutables == null) {
- // The following code might be called in pararell when we invoke
- // this method from within multiple threads.
- // It might be better to use some atomic classes.
- ghostscriptExecutables = GhostscriptUtils.listGhostscriptExecutables();
- if (ghostscriptExecutables.length == 0) {
- LOGGER.warning("You don't seem to have a Ghostscript installed. dvibrowser needs it to render PS, EPS, and PDF.");
- } else {
- LOGGER.info("Ghostscript executables found: " + DviUtils.join(" ", ghostscriptExecutables));
- }
- }
- if (ghostscriptExecutables.length > 0) {
- return ghostscriptExecutables[0];
- }
- }
-
- return name;
- }
-
- private final DviToolkit dviToolkit = new DviToolkit(this);
- public DviToolkit getDviToolkit()
- {
- return dviToolkit;
- }
-
- private final MetafontMode libraryDefaultMetafontMode = MetafontMode.FALLBACK;
- public MetafontMode getDefaultMetafontMode() throws DviException {
- return libraryDefaultMetafontMode;
- }
-
- public void setRecordResources(boolean recordResources) {
- this.recordResources = recordResources;
- }
-
- public boolean wantRecordResources() {
- return recordResources;
- }
-
- public Set<URL> getRecordedResources() {
- return resources;
- }
-
- protected void setAsyncComputers(AsyncComputers asyncComputers) {
- this.asyncComputers = asyncComputers;
- }
-
- public AsyncComputers getAsyncComputers() {
- return asyncComputers;
- }
-}