Skip to content

Commit

Permalink
Merge pull request #249 from danfickle/font_metrics_cache
Browse files Browse the repository at this point in the history
Cache PDF font metrics across runs to avoid loading fallback fonts
  • Loading branch information
danfickle authored Jul 20, 2018
2 parents 8a3168d + 87a1a9c commit 16201df
Show file tree
Hide file tree
Showing 10 changed files with 418 additions and 133 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.openhtmltopdf.extend;

import java.util.concurrent.Callable;

public interface FSCacheEx<K, V> {
public void put(K key, V value);
public V get(K key, Callable<? extends V> loader);
public V get(K key);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.openhtmltopdf.extend;

/**
* Note: Classes implementing this interface should be thread safe as we document the cache being useable accross threads.
*/
public interface FSCacheValue {
/**
* @return the (very) approximate weight of a cache value in bytes if known or -1 otherwise.
*/
public int weight();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.openhtmltopdf.extend.impl;

import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;

import com.openhtmltopdf.extend.FSCacheEx;
import com.openhtmltopdf.extend.FSCacheValue;
import com.openhtmltopdf.util.XRLog;


/**
* A simple default cache implementation, mainly for testing. For production you will probably want to wrap Guava's cache implementation
* or something similar. This implementation does not use synchronisation beyond using a <code>ConcurrentHashMap<code> internally.
* Specifically, the {@link #get(String, Callable)} may call the loader multiple times if called in close succession.
*/
public class FSDefaultCacheStore implements FSCacheEx<String, FSCacheValue> {
private final Map<String, FSCacheValue> _store = new ConcurrentHashMap<String, FSCacheValue>();

@Override
public void put(String key, FSCacheValue value) {
XRLog.load(Level.INFO, "Putting key(" + key + ") in cache.");
_store.put(key, value);
}

@Override
public FSCacheValue get(String key, Callable<? extends FSCacheValue> loader) {
if (_store.containsKey(key)) {
return this.get(key);
}

FSCacheValue value;
try {
value = loader.call();

if (value != null) {
_store.put(key, value);
}
} catch (Exception e) {
XRLog.exception("Could not load cache value for key(" + key + ")", e);
value = null;
}

XRLog.load(Level.INFO, (value == null ? "Missed" : "Hit") + " key(" + key + ") from cache.");
return value;
}

@Override
public FSCacheValue get(String key) {
FSCacheValue value = _store.get(key);
XRLog.load(Level.INFO, (value == null ? "Missed" : "Hit") + " key(" + key + ") from cache.");
return value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.openhtmltopdf.extend.impl;

import java.util.concurrent.Callable;

import com.openhtmltopdf.extend.FSCacheEx;
import com.openhtmltopdf.extend.FSCacheValue;

public class FSNoOpCacheStore implements FSCacheEx<String, FSCacheValue> {
public final static FSNoOpCacheStore INSTANCE = new FSNoOpCacheStore();

@Override
public void put(String key, FSCacheValue value) {
}

@Override
public FSCacheValue get(String key, Callable<? extends FSCacheValue> loader) {
return null;
}

@Override
public FSCacheValue get(String key) {
return null;
}
}
Loading

0 comments on commit 16201df

Please sign in to comment.