aboutsummaryrefslogtreecommitdiffstats
path: root/src/jogl
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-09-30 23:07:50 +0200
committerSven Gothel <[email protected]>2014-09-30 23:07:50 +0200
commitbd24599b21f9787ac989e65b44dc1ba762162f22 (patch)
tree48bf52d4ebdd5e4172dd83a4d6d7f75f961c7574 /src/jogl
parentf197d38d0ea31416645ac69cebb3f9b3544d903f (diff)
Refine Graph/Font InputStream Capabilities (commit 628509b39ea7c16210315d191860511d6be4aa69)
FontFactory Remove: - Font get(final URLConnection conn) - Font get(final InputStream stream) FontFactory Add: - [1] Font get(final InputStream stream, final int streamLen, final boolean closeStream) - Direct usage of font InputStream w/ determined length, may instantiate BufferedInputStream in case given stream doesn't support mark/reset! - [2] Font get(final InputStream stream, final boolean closeStream) - Copy font InputStream w/o determined length, resulting in BufferedInputStream supporting mark/reset! Security Related: - Only perform priviledged code on determine InputStream, _not_ when parsing the font stream itself! - Hence PrivilegedAction only happens in FontFactory's InputStream preparation. Misc: - Use Uri class
Diffstat (limited to 'src/jogl')
-rw-r--r--src/jogl/classes/com/jogamp/graph/font/FontFactory.java108
-rw-r--r--src/jogl/classes/jogamp/graph/font/FontConstructor.java6
-rw-r--r--src/jogl/classes/jogamp/graph/font/JavaFontLoader.java45
-rw-r--r--src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java102
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java74
-rw-r--r--src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java55
6 files changed, 226 insertions, 164 deletions
diff --git a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
index cfd06cf6c..ba355f4e6 100644
--- a/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
+++ b/src/jogl/classes/com/jogamp/graph/font/FontFactory.java
@@ -27,12 +27,15 @@
*/
package com.jogamp.graph.font;
+import java.io.BufferedInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URI;
-import java.net.URLConnection;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import com.jogamp.common.net.Uri;
import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
@@ -88,32 +91,113 @@ public class FontFactory {
}
}
+ /**
+ * Creates a Font instance.
+ * @param file font file
+ * @return the new Font instance
+ * @throws IOException
+ */
public static final Font get(final File file) throws IOException {
return fontConstr.create(file);
}
- public static final Font get(final InputStream stream) throws IOException {
- return fontConstr.create(stream);
+ /**
+ * Creates a Font instance based on a determinated font stream with its given length
+ * of the font segment.
+ * <p>
+ * No explicit stream copy is performed as in {@link #get(InputStream, boolean)}
+ * due to the known {@code streamLen}.
+ * </p>
+ * @param stream font stream
+ * @param streamLen length of the font segment within this font stream
+ * @param closeStream {@code true} to close the {@code stream}
+ * @return the new Font instance
+ * @throws IOException
+ */
+ public static final Font get(final InputStream stream, final int streamLen, final boolean closeStream) throws IOException {
+ try {
+ return fontConstr.create(stream, streamLen);
+ } finally {
+ if( closeStream ) {
+ stream.close();
+ }
+ }
}
- public static final Font get(final URLConnection conn) throws IOException {
- return fontConstr.create(conn);
+ /**
+ * Creates a Font instance based on an undeterminated font stream length.
+ * <p>
+ * The font stream is temporarily copied into a temp file
+ * to gather it's size and to gain random access.
+ * The temporary file will be deleted at exit.
+ * </p>
+ * @param stream dedicated font stream
+ * @param closeStream {@code true} to close the {@code stream}
+ * @return the new Font instance
+ * @throws IOException
+ */
+ public static final Font get(final InputStream stream, final boolean closeStream) throws IOException {
+ final IOException[] ioe = { null };
+ final int[] streamLen = { 0 };
+ final File tempFile[] = { null };
+
+ final InputStream bis = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
+ @Override
+ public InputStream run() {
+ InputStream bis = null;
+ try {
+ tempFile[0] = IOUtil.createTempFile( "jogl.font", ".ttf", false);
+ streamLen[0] = IOUtil.copyStream2File(stream, tempFile[0], -1);
+ if( 0 == streamLen[0] ) {
+ throw new IOException("Font stream has zero bytes");
+ }
+ bis = new BufferedInputStream(new FileInputStream(tempFile[0]), streamLen[0]);
+ } catch (final IOException e) {
+ ioe[0] = e;
+ if( null != tempFile[0] ) {
+ tempFile[0].delete();
+ tempFile[0] = null;
+ }
+ streamLen[0] = 0;
+ } finally {
+ if( closeStream ) {
+ IOUtil.close(stream, ioe, System.err);
+ }
+ }
+ return bis;
+ } });
+ if( null != ioe[0] ) {
+ throw ioe[0];
+ }
+ if( null == bis ) {
+ throw new IOException("Could not cache font stream"); // should not be reached
+ }
+ try {
+ return fontConstr.create(bis, streamLen[0]);
+ } finally {
+ if( null != bis ) {
+ bis.close();
+ }
+ if( null != tempFile[0] ) {
+ tempFile[0].delete();
+ }
+ }
}
public static final Font get(final Class<?> context, final String fname, final boolean useTempJarCache) throws IOException {
- URLConnection conn = null;
+ InputStream stream = null;
if( useTempJarCache ) {
try {
- final URI uri = TempJarCache.getResource(fname);
- conn = null != uri ? uri.toURL().openConnection() : null;
+ final Uri uri = TempJarCache.getResourceUri(fname);
+ stream = null != uri ? uri.toURL().openConnection().getInputStream() : null;
} catch (final Exception e) {
throw new IOException(e);
}
} else {
- conn = IOUtil.getResource(context, fname);
+ stream = IOUtil.getResource(context, fname).getInputStream();
}
- if(null != conn) {
- return FontFactory.get ( conn ) ;
+ if( null != stream ) {
+ return FontFactory.get ( stream, true ) ;
}
return null;
}
diff --git a/src/jogl/classes/jogamp/graph/font/FontConstructor.java b/src/jogl/classes/jogamp/graph/font/FontConstructor.java
index 76b5dbb8b..fa176ead9 100644
--- a/src/jogl/classes/jogamp/graph/font/FontConstructor.java
+++ b/src/jogl/classes/jogamp/graph/font/FontConstructor.java
@@ -30,12 +30,10 @@ package jogamp.graph.font;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URLConnection;
import com.jogamp.graph.font.Font;
public interface FontConstructor {
- Font create(File file) throws IOException ;
- Font create(InputStream stream) throws IOException ;
- Font create(URLConnection url) throws IOException ;
+ Font create(final File file) throws IOException ;
+ Font create(final InputStream stream, int streamLen) throws IOException ;
}
diff --git a/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java b/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java
index 1bb2bb5f3..da651cca9 100644
--- a/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java
+++ b/src/jogl/classes/jogamp/graph/font/JavaFontLoader.java
@@ -27,8 +27,11 @@
*/
package jogamp.graph.font;
+import java.io.BufferedInputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -89,6 +92,9 @@ public class JavaFontLoader implements FontSet {
@Override
public Font get(final int family, final int style) throws IOException {
+ if(null == javaFontPath) {
+ throw new GLException("java font path undefined");
+ }
Font font = (Font)fontMap.get( ( family << 8 ) | style );
if (font != null) {
return font;
@@ -139,20 +145,41 @@ public class JavaFontLoader implements FontSet {
}
Font abspath(final String fname, final int family, final int style) throws IOException {
- if(null == javaFontPath) {
- throw new GLException("java font path undefined");
- }
- final String err = "Problem loading font "+fname+", file "+javaFontPath+fname ;
-
try {
- final Font f = FontFactory.get( new File(javaFontPath+fname) );
+ final Font f = abspathImpl(javaFontPath+fname, family, style);
if(null != f) {
- fontMap.put( ( family << 8 ) | style, f );
return f;
}
- throw new IOException (err);
+ throw new IOException (String.format("Problem loading font %s, file %s%s", fname, javaFontPath, fname));
} catch (final IOException ioe) {
- throw new IOException(err, ioe);
+ throw new IOException(String.format("Problem loading font %s, file %s%s", fname, javaFontPath, fname), ioe);
+ }
+ }
+ private Font abspathImpl(final String fname, final int family, final int style) throws IOException {
+ final Exception[] privErr = { null };
+ final int[] streamLen = { 0 };
+ final InputStream stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
+ @Override
+ public InputStream run() {
+ try {
+ final File file = new File(fname);
+ streamLen[0] = (int) file.length();
+ return new BufferedInputStream(new FileInputStream(file), streamLen[0]);
+ } catch (final Exception e) {
+ privErr[0] = e;
+ return null;
+ }
+ } } );
+ if( null != privErr[0] ) {
+ throw new IOException(privErr[0]);
+ }
+ if(null != stream) {
+ final Font f= FontFactory.get ( stream, streamLen[0], true ) ;
+ if(null != f) {
+ fontMap.put( ( family << 8 ) | style, f );
+ return f;
+ }
}
+ return null;
}
}
diff --git a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java
index 76947873e..bbf022657 100644
--- a/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java
+++ b/src/jogl/classes/jogamp/graph/font/UbuntuFontLoader.java
@@ -28,18 +28,17 @@
package jogamp.graph.font;
import java.io.IOException;
+import java.io.InputStream;
+import com.jogamp.common.net.Uri;
import com.jogamp.common.os.Platform;
import com.jogamp.common.util.IntObjectHashMap;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.common.util.JarUtil;
import com.jogamp.common.util.cache.TempJarCache;
import com.jogamp.graph.font.Font;
import com.jogamp.graph.font.FontSet;
import com.jogamp.graph.font.FontFactory;
-import java.net.URI;
-import java.net.URLConnection;
import java.security.AccessController;
import java.security.PrivilegedAction;
@@ -48,8 +47,8 @@ public class UbuntuFontLoader implements FontSet {
// FIXME: Add cache size to limit memory usage
private static final IntObjectHashMap fontMap = new IntObjectHashMap();
- private static final String jarSubDir = "atomic/" ;
- private static final String jarName = "jogl-fonts-p0.jar" ;
+ private static final Uri.Encoded jarSubDir = Uri.Encoded.cast("atomic/");
+ private static final Uri.Encoded jarName = Uri.Encoded.cast("jogl-fonts-p0.jar");
private static final String relFontPath = "fonts/ubuntu/" ;
private static final String absFontPath = "jogamp/graph/font/fonts/ubuntu/" ;
@@ -130,71 +129,64 @@ public class UbuntuFontLoader implements FontSet {
}
private static boolean attemptedJARLoading = false;
- private static boolean useTempJarCache = false;
+ private static boolean useTempJARCache = false;
private synchronized Font abspath(final String fname, final int family, final int style) throws IOException {
- final String err = "Problem loading font "+fname+", stream "+relFontPath+fname;
- final Exception[] privErr = { null };
- try {
- final Font f0 = abspathImpl(fname, family, style);
- if(null != f0) {
- return f0;
- }
- if( !attemptedJARLoading ) {
- attemptedJARLoading = true;
- Platform.initSingleton();
- if( TempJarCache.isInitialized() ) {
- final URI uri = JarUtil.getRelativeOf(UbuntuFontLoader.class, jarSubDir, jarName);
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ if( !attemptedJARLoading ) {
+ attemptedJARLoading = true;
+ Platform.initSingleton();
+ if( TempJarCache.isInitialized() ) {
+ try {
+ final Uri uri = JarUtil.getRelativeOf(UbuntuFontLoader.class, jarSubDir, jarName);
+ final Exception e0 = AccessController.doPrivileged(new PrivilegedAction<Exception>() {
@Override
- public Object run() {
+ public Exception run() {
try {
TempJarCache.addResources(UbuntuFontLoader.class, uri);
- } catch (final Exception e) { privErr[0] = e; }
- return null;
+ useTempJARCache = true;
+ return null;
+ } catch (final Exception e) {
+ return e;
+ }
} } );
- if( null == privErr[0] ) {
- useTempJarCache = true;
- final Font f1 = abspathImpl(fname, family, style);
- if(null != f1) {
- return f1;
- }
+ if( null != e0 ) {
+ throw e0;
}
+ } catch(final Exception e1) {
+ System.err.println("Caught "+e1.getMessage());
+ e1.printStackTrace();
}
}
- } catch(final Exception e) {
- throw new IOException(err, e);
}
- if( null != privErr[0] ) {
- throw new IOException(err, privErr[0]);
+ final String path = useTempJARCache ? absFontPath : relFontPath;
+ try {
+ final Font f = abspathImpl(path+fname, family, style);
+ if( null != f ) {
+ return f;
+ }
+ throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname));
+ } catch(final Exception e) {
+ throw new IOException(String.format("Problem loading font %s, stream %s%s", fname, path, fname), e);
}
- throw new IOException(err);
}
private Font abspathImpl(final String fname, final int family, final int style) throws IOException {
- final URLConnection conn;
- if( useTempJarCache ) {
- // this code-path throws .. all exceptions
- final Exception[] privErr = { null };
- final URLConnection[] privConn = { null };
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- try {
- final URI uri = TempJarCache.getResource(absFontPath+fname);
- privConn[0] = null != uri ? uri.toURL().openConnection() : null;
- } catch (final Exception e) { privErr[0] = e; }
+ final Exception[] privErr = { null };
+ final InputStream stream = AccessController.doPrivileged(new PrivilegedAction<InputStream>() {
+ @Override
+ public InputStream run() {
+ try {
+ final Uri uri = TempJarCache.getResourceUri(fname);
+ return null != uri ? uri.toURL().openConnection().getInputStream() : null;
+ } catch (final Exception e) {
+ privErr[0] = e;
return null;
- } } );
- if( null != privErr[0] ) {
- throw new IOException(privErr[0]);
- }
- conn = privConn[0];
- } else {
- // no exceptions ..
- conn = IOUtil.getResource(UbuntuFontLoader.class, relFontPath+fname);
+ }
+ } } );
+ if( null != privErr[0] ) {
+ throw new IOException(privErr[0]);
}
- if(null != conn) {
- final Font f= FontFactory.get ( conn ) ;
+ if(null != stream) {
+ final Font f= FontFactory.get ( stream, true ) ;
if(null != f) {
fontMap.put( ( family << 8 ) | style, f );
return f;
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
index 0b42a65d4..ef7f38e64 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/TypecastFontConstructor.java
@@ -30,89 +30,21 @@ package jogamp.graph.font.typecast;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URLConnection;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-
-import javax.media.opengl.GLException;
import jogamp.graph.font.FontConstructor;
import jogamp.graph.font.typecast.ot.OTFontCollection;
-import com.jogamp.common.util.IOUtil;
import com.jogamp.graph.font.Font;
public class TypecastFontConstructor implements FontConstructor {
@Override
public Font create(final File ffile) throws IOException {
- final Object o = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- OTFontCollection fontset;
- try {
- fontset = OTFontCollection.create(ffile);
- return new TypecastFont(fontset);
- } catch (final IOException e) {
- return e;
- }
- }
- });
- if(o instanceof Font) {
- return (Font)o;
- }
- if(o instanceof IOException) {
- throw (IOException)o;
- }
- throw new InternalError("Unexpected Object: "+o);
+ return new TypecastFont( OTFontCollection.create(ffile) );
}
@Override
- public Font create(final InputStream istream) throws IOException {
- final Object o = AccessController.doPrivileged(new PrivilegedAction<Object>() {
- @Override
- public Object run() {
- OTFontCollection fontset;
- try {
- fontset = OTFontCollection.create(istream);
- return new TypecastFont(fontset);
- } catch (final IOException e) {
- return e;
- }
- }
- });
- if(o instanceof Font) {
- return (Font)o;
- }
- if(o instanceof IOException) {
- throw (IOException)o;
- }
- throw new InternalError("Unexpected Object: "+o);
+ public Font create(final InputStream istream, final int streamLen) throws IOException {
+ return new TypecastFont( OTFontCollection.create(istream, streamLen) );
}
-
- @Override
- public Font create(final URLConnection fconn) throws IOException {
- return AccessController.doPrivileged(new PrivilegedAction<Font>() {
- @Override
- public Font run() {
- File tf = null;
- int len=0;
- Font f = null;
- try {
- tf = IOUtil.createTempFile( "jogl.font", ".ttf", false);
- len = IOUtil.copyURLConn2File(fconn, tf);
- if(len==0) {
- tf.delete();
- throw new GLException("Font of stream "+fconn.getURL()+" was zero bytes");
- }
- f = create(tf);
- tf.delete();
- } catch (final IOException e) {
- e.printStackTrace();
- }
- return f;
- }
- });
- }
-
}
diff --git a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java
index 87c68eae8..be84a951c 100644
--- a/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java
+++ b/src/jogl/classes/jogamp/graph/font/typecast/ot/OTFontCollection.java
@@ -59,9 +59,19 @@ public class OTFontCollection {
/**
* @param file The OpenType font file
*/
- public static OTFontCollection create(final InputStream istream) throws IOException {
+ public static OTFontCollection create(final File file) throws IOException {
final OTFontCollection fc = new OTFontCollection();
- fc.read(istream);
+ fc.read(file);
+ return fc;
+ }
+
+ /**
+ * @param istream The OpenType font input stream
+ * @param streamLen TODO
+ */
+ public static OTFontCollection create(final InputStream istream, final int streamLen) throws IOException {
+ final OTFontCollection fc = new OTFontCollection();
+ fc.read(istream, streamLen);
return fc;
}
@@ -120,20 +130,40 @@ public class OTFontCollection {
}
_resourceFork = true;
}
-
- read(new FileInputStream(file));
+ final int streamLen = (int) file.length();
+ final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file), streamLen);
+ try {
+ readImpl(bis, streamLen);
+ } finally {
+ bis.close();
+ }
}
-
+
/**
- * @param inputstream The OpenType font stream
+ * @param is The OpenType font stream
+ * @param streamLen the total length of the stream
*/
- protected void read(InputStream file) throws IOException {
-
- final DataInputStream dis = new DataInputStream(
- new BufferedInputStream(
- file));
- //dis.mark((int) file.length());
+ protected void read(final InputStream is, final int streamLen) throws IOException {
+ _pathName = "";
+ _fileName = "";
+ final InputStream bis;
+ if( is.markSupported() ) {
+ bis = is;
+ } else {
+ bis = new BufferedInputStream(is, streamLen);
+ }
+ readImpl(bis, streamLen);
+ }
+ /**
+ * @param is The OpenType font stream, must {@link InputStream#markSupported() support mark}!
+ */
+ private void readImpl(final InputStream bis, final int streamLen) throws IOException {
+ if( !bis.markSupported() ) {
+ throw new IllegalArgumentException("stream of type "+bis.getClass().getName()+" doesn't support mark");
+ }
+ bis.mark(streamLen);
+ final DataInputStream dis = new DataInputStream(bis);
if (_resourceFork || _pathName.endsWith(".dfont")) {
// This is a Macintosh font suitcase resource
@@ -174,6 +204,5 @@ public class OTFontCollection {
_fonts[0] = new OTFont(this);
_fonts[0].read(dis, 0, 0);
}
- dis.close();
}
}