提交 f7473898 编写于 作者: A asaha

Merge

...@@ -274,11 +274,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) ...@@ -274,11 +274,6 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
$(JDK_TOPDIR)/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java \ $(JDK_TOPDIR)/src/solaris/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java \
$(JDK_TOPDIR)/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java $(JDK_TOPDIR)/src/solaris/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java
# JObjC.jar contains 1.5 byte-code...so skip it here :-(
# MACOSX_SRC_DIRS += $(JDK_TOPDIR)/src/macosx/native/jobjc/src
# EXCLUDES += tests/java/com/apple/jobjc
EXCLUDES += com/apple/jobjc
endif endif
# The security classes should not end up in the classes directory as that will prevent them # The security classes should not end up in the classes directory as that will prevent them
...@@ -354,44 +349,6 @@ $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin: ...@@ -354,44 +349,6 @@ $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.tools.xjc.Plugin:
########################################################################################## ##########################################################################################
ifeq ($(OPENJDK_TARGET_OS), macosx)
#
# JObjC.jar is compiled with BOOT_JAVAC which (may) not support the "-h" flag.
# so we first compile classes with BOOT_JAVAC and then with JDK_JAVAC :-(
#
$(eval $(call SetupJavaCompiler,GENERATE_15BYTECODE, \
JAVAC := $(JAVAC), \
FLAGS := -source 1.5 -target 1.5 -g -bootclasspath $(BOOT_RTJAR) -cp $(JDK_OUTPUTDIR)/../langtools/dist/lib/classes.jar $(DISABLE_WARNINGS), \
SERVER_DIR := $(SJAVAC_SERVER_DIR), \
SERVER_JVM := $(SJAVAC_SERVER_JAVA)))
$(eval $(call SetupJavaCompilation,BUILD_JOBJC, \
SETUP := GENERATE_15BYTECODE, \
DISABLE_SJAVAC := true, \
SRC := $(JDK_TOPDIR)/src/macosx/native/jobjc/src/core/java \
$(JDK_TOPDIR)/src/macosx/native/jobjc/src/runtime-additions/java \
$(JDK_OUTPUTDIR)/gensrc_jobjc/src, \
INCLUDES := com/apple/jobjc, \
EXCLUDES := tests/java/com/apple/jobjc, \
BIN := $(JDK_OUTPUTDIR)/jobjc_classes, \
JAR := $(JDK_OUTPUTDIR)/lib/JObjC.jar, \
JARINDEX := true))
$(BUILD_JOBJC): $(BUILD_JDK)
$(eval $(call SetupJavaCompilation,BUILD_JOBJC_HEADERS, \
SETUP := GENERATE_JDKBYTECODE, \
SRC := $(JDK_TOPDIR)/src/macosx/native/jobjc/src/core/java \
$(JDK_TOPDIR)/src/macosx/native/jobjc/src/runtime-additions/java \
$(JDK_OUTPUTDIR)/gensrc_jobjc/src, \
INCLUDES := com/apple/jobjc, \
EXCLUDES := tests/java/com/apple/jobjc, \
BIN := $(JDK_OUTPUTDIR)/jobjc_classes_headers, \
HEADERS := $(JDK_OUTPUTDIR)/gensrc_headers_jobjc))
$(BUILD_JOBJC_HEADERS): $(BUILD_JDK)
endif
########################################################################################## ##########################################################################################
......
...@@ -693,13 +693,6 @@ $(IMAGES_OUTPUTDIR)/lib/ext/zipfs.jar: $(JDK_OUTPUTDIR)/demo/nio/zipfs/zipfs.jar ...@@ -693,13 +693,6 @@ $(IMAGES_OUTPUTDIR)/lib/ext/zipfs.jar: $(JDK_OUTPUTDIR)/demo/nio/zipfs/zipfs.jar
########################################################################################## ##########################################################################################
ifeq ($(OPENJDK_TARGET_OS), macosx)
$(eval $(call SetupArchive,BUILD_JOBJC_JAR, , \
SRCS := $(JDK_OUTPUTDIR)/jobjc_classes, \
JAR := $(IMAGES_OUTPUTDIR)/lib/JObjC.jar, \
JARINDEX := true))
endif
# This file is imported from hotspot in Import.gmk. Copying it into images/lib so that # This file is imported from hotspot in Import.gmk. Copying it into images/lib so that
# all jars can be found in one place when creating images in Images.gmk. It needs to be # all jars can be found in one place when creating images in Images.gmk. It needs to be
# done here so that clean targets can be simple and accurate. # done here so that clean targets can be simple and accurate.
......
...@@ -85,11 +85,6 @@ GENSRC += $(GENSRC_CLDR) ...@@ -85,11 +85,6 @@ GENSRC += $(GENSRC_CLDR)
include gensrc/GensrcSwing.gmk include gensrc/GensrcSwing.gmk
GENSRC += $(GENSRC_SWING_BEANINFO) $(GENSRC_SWING_NIMBUS) GENSRC += $(GENSRC_SWING_BEANINFO) $(GENSRC_SWING_NIMBUS)
ifeq ($(OPENJDK_TARGET_OS), macosx)
include gensrc/GensrcJObjC.gmk
GENSRC += $(GENSRC_JOBJC)
endif
$(GENSRC): $(BUILD_TOOLS) $(GENSRC): $(BUILD_TOOLS)
all: $(GENSRC) all: $(GENSRC)
......
...@@ -303,14 +303,13 @@ $(JDK_IMAGE_DIR)/jre/lib/applet: ...@@ -303,14 +303,13 @@ $(JDK_IMAGE_DIR)/jre/lib/applet:
$(ECHO) $(LOG_INFO) Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(ECHO) $(LOG_INFO) Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
$(MKDIR) -p $@ $(MKDIR) -p $@
# In the old build, JObjC.jar is not part of the meta-index
$(JRE_IMAGE_DIR)/lib/meta-index: $(JRE_LIB_TARGETS) $(JRE_IMAGE_DIR)/lib/meta-index: $(JRE_LIB_TARGETS)
$(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
$(CD) $(@D) && $(TOOL_BUILDMETAINDEX) -o meta-index `$(LS) *.jar | $(SED) 's/JObjC\.jar//g'` $(CD) $(@D) && $(TOOL_BUILDMETAINDEX) -o meta-index *.jar
$(JDK_IMAGE_DIR)/jre/lib/meta-index: $(JDKJRE_LIB_TARGETS) $(JDK_IMAGE_DIR)/jre/lib/meta-index: $(JDKJRE_LIB_TARGETS)
$(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
$(CD) $(@D) && $(TOOL_BUILDMETAINDEX) -o meta-index `$(LS) *.jar | $(SED) 's/JObjC\.jar//g'` $(CD) $(@D) && $(TOOL_BUILDMETAINDEX) -o meta-index *.jar
$(JRE_IMAGE_DIR)/lib/ext/meta-index: $(JRE_LIB_TARGETS) $(JRE_IMAGE_DIR)/lib/ext/meta-index: $(JRE_LIB_TARGETS)
$(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@) $(ECHO) $(LOG_INFO) Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@)
......
...@@ -105,10 +105,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows) ...@@ -105,10 +105,6 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
ALL_JARS += $(IMAGES_OUTPUTDIR)/lib/ext/sunmscapi.jar ALL_JARS += $(IMAGES_OUTPUTDIR)/lib/ext/sunmscapi.jar
endif endif
ifeq ($(OPENJDK_TARGET_OS), macosx)
ALL_JARS += $(IMAGES_OUTPUTDIR)/lib/JObjC.jar
endif
ifeq ($(PROFILE), profile_1) ifeq ($(PROFILE), profile_1)
PROFILE_JARS := $(PROFILE_1_JARS) PROFILE_JARS := $(PROFILE_1_JARS)
else ifeq ($(PROFILE), profile_2) else ifeq ($(PROFILE), profile_2)
......
...@@ -136,64 +136,6 @@ endif ...@@ -136,64 +136,6 @@ endif
########################################################################################## ##########################################################################################
ifeq ($(OPENJDK_TARGET_OS), macosx)
$(eval $(call SetupNativeCompilation,BUILD_LIBJOBJC32, \
LIBRARY := JObjC, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/objs/libjobjc32, \
SRC := $(JDK_TOPDIR)/src/macosx/native/jobjc/src/core/native \
$(JDK_TOPDIR)/src/macosx/native/jobjc/src/runtime-additions/native, \
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := -fpascal-strings \
-fobjc-gc \
-gdwarf-2 \
$(CFLAGS_JDKLIB) -I$(JDK_OUTPUTDIR)/gensrc_headers_jobjc \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-m32, \
LDFLAGS := $(LDFLAGS_JDKLIB) \
-m32, \
LDFLAGS_SUFFIX := -framework Foundation -framework JavaVM \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-lffi, \
OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libjobjc32, \
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
$(eval $(call SetupNativeCompilation,BUILD_LIBJOBJC64, \
LIBRARY := JObjC, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/objs/libjobjc64, \
SRC := $(JDK_TOPDIR)/src/macosx/native/jobjc/src/core/native \
$(JDK_TOPDIR)/src/macosx/native/jobjc/src/runtime-additions/native, \
LANG := C, \
OPTIMIZATION := LOW, \
CFLAGS := -fpascal-strings \
-fobjc-gc \
-gdwarf-2 \
$(CFLAGS_JDKLIB) -I$(JDK_OUTPUTDIR)/gensrc_headers_jobjc \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
, \
LDFLAGS := -fpascal-strings \
-fobjc-gc \
-gdwarf-2 \
$(LDFLAGS_JDKLIB) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_SUFFIX := -framework Foundation -framework JavaVM \
-F/System/Library/Frameworks/JavaVM.framework/Frameworks \
-framework JavaNativeFoundation \
-lffi, \
OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libjobjc64, \
DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
$(INSTALL_LIBRARIES_HERE)/$(LIBRARY_PREFIX)JObjC$(SHARED_LIBRARY_SUFFIX): $(BUILD_LIBJOBJC32) $(BUILD_LIBJOBJC64)
$(LIPO) -create -output $@ $(BUILD_LIBJOBJC32) $(BUILD_LIBJOBJC64)
BUILD_LIBRARIES += $(INSTALL_LIBRARIES_HERE)/$(LIBRARY_PREFIX)JObjC$(SHARED_LIBRARY_SUFFIX)
endif
##########################################################################################
ifndef OPENJDK ifndef OPENJDK
ifeq ($(OPENJDK_TARGET_OS), windows) ifeq ($(OPENJDK_TARGET_OS), windows)
......
...@@ -290,8 +290,8 @@ SplashEventLoop(Splash * splash) { ...@@ -290,8 +290,8 @@ SplashEventLoop(Splash * splash) {
SplashUnlock(splash); SplashUnlock(splash);
rc = poll(pfd, 1, timeout); rc = poll(pfd, 1, timeout);
SplashLock(splash); SplashLock(splash);
if (splash->isVisible>0 && SplashTime() >= splash->time + if (splash->isVisible > 0 && splash->currentFrame >= 0 &&
splash->frames[splash->currentFrame].delay) { SplashTime() >= splash->time + splash->frames[splash->currentFrame].delay) {
SplashNextFrame(splash); SplashNextFrame(splash);
SplashRedrawWindow(splash); SplashRedrawWindow(splash);
} }
......
...@@ -29,6 +29,7 @@ import com.sun.beans.finder.ClassFinder; ...@@ -29,6 +29,7 @@ import com.sun.beans.finder.ClassFinder;
import java.beans.ExceptionListener; import java.beans.ExceptionListener;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader;
import java.lang.ref.Reference; import java.lang.ref.Reference;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
...@@ -245,6 +246,14 @@ public final class DocumentHandler extends DefaultHandler { ...@@ -245,6 +246,14 @@ public final class DocumentHandler extends DefaultHandler {
this.objects.add(object); this.objects.add(object);
} }
/**
* Disables any external entities.
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
/** /**
* Prepares this handler to read objects from XML document. * Prepares this handler to read objects from XML document.
*/ */
......
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -72,13 +72,17 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -72,13 +72,17 @@ public final class TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
throw new IllegalStateException( throw new IllegalStateException(
"TlsRsaPremasterSecretGenerator must be initialized"); "TlsRsaPremasterSecretGenerator must be initialized");
} }
if (random == null) { byte[] b = spec.getEncodedSecret();
random = new SecureRandom(); if (b == null) {
if (random == null) {
random = new SecureRandom();
}
b = new byte[48];
random.nextBytes(b);
b[0] = (byte)spec.getMajorVersion();
b[1] = (byte)spec.getMinorVersion();
} }
byte[] b = new byte[48];
random.nextBytes(b);
b[0] = (byte)spec.getMajorVersion();
b[1] = (byte)spec.getMinorVersion();
return new SecretKeySpec(b, "TlsRsaPremasterSecret"); return new SecretKeySpec(b, "TlsRsaPremasterSecret");
} }
......
...@@ -27,17 +27,9 @@ package com.sun.jmx.snmp.agent; ...@@ -27,17 +27,9 @@ package com.sun.jmx.snmp.agent;
// java imports // java imports
// //
import com.sun.jmx.snmp.SnmpDefinitions;
import java.io.Serializable; import java.io.Serializable;
import java.util.Hashtable;
import java.util.Enumeration;
// jmx imports
//
import com.sun.jmx.snmp.SnmpValue;
import com.sun.jmx.snmp.SnmpVarBind;
import com.sun.jmx.snmp.SnmpStatusException; import com.sun.jmx.snmp.SnmpStatusException;
import com.sun.jmx.snmp.agent.SnmpMibOid;
import com.sun.jmx.snmp.agent.SnmpMibNode;
/** /**
* Represents a node in an SNMP MIB which corresponds to a table entry * Represents a node in an SNMP MIB which corresponds to a table entry
...@@ -99,7 +91,9 @@ public abstract class SnmpMibEntry extends SnmpMibNode ...@@ -99,7 +91,9 @@ public abstract class SnmpMibEntry extends SnmpMibNode
*/ */
public void validateVarId(long arc, Object userData) public void validateVarId(long arc, Object userData)
throws SnmpStatusException { throws SnmpStatusException {
if (isVariable(arc) == false) throw noSuchNameException; if (isVariable(arc) == false) {
throw new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName);
}
} }
/** /**
......
...@@ -108,8 +108,9 @@ public abstract class SnmpMibGroup extends SnmpMibOid ...@@ -108,8 +108,9 @@ public abstract class SnmpMibGroup extends SnmpMibOid
*/ */
public void validateVarId(long arc, Object userData) public void validateVarId(long arc, Object userData)
throws SnmpStatusException { throws SnmpStatusException {
if (isVariable(arc) == false) if (isVariable(arc) == false) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
} }
...@@ -360,17 +361,20 @@ public abstract class SnmpMibGroup extends SnmpMibOid ...@@ -360,17 +361,20 @@ public abstract class SnmpMibGroup extends SnmpMibOid
validateVarId(arc, data); validateVarId(arc, data);
// The trailing .0 is missing in the OID // The trailing .0 is missing in the OID
if (depth+2 > length) if (depth+2 > length) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
// There are too many arcs left in the OID (there should remain // There are too many arcs left in the OID (there should remain
// a single trailing .0) // a single trailing .0)
if (depth+2 < length) if (depth+2 < length) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
// The last trailing arc is not .0 // The last trailing arc is not .0
if (oid[depth+1] != 0L) if (oid[depth+1] != 0L) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
// It's one of our variable, register this node. // It's one of our variable, register this node.
handlers.add(this,depth,varbind); handlers.add(this,depth,varbind);
...@@ -389,12 +393,13 @@ public abstract class SnmpMibGroup extends SnmpMibOid ...@@ -389,12 +393,13 @@ public abstract class SnmpMibGroup extends SnmpMibOid
int length = oid.length; int length = oid.length;
SnmpMibNode node = null; SnmpMibNode node = null;
if (handlers == null) if (handlers == null) {
// This should be considered as a genErr, but we do not want to // This should be considered as a genErr, but we do not want to
// abort the whole request, so we're going to throw // abort the whole request, so we're going to throw
// a noSuchObject... // a noSuchObject...
// //
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
final Object data = handlers.getUserData(); final Object data = handlers.getUserData();
final int pduVersion = handlers.getRequestPduVersion(); final int pduVersion = handlers.getRequestPduVersion();
...@@ -430,7 +435,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid ...@@ -430,7 +435,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid
depth+1,handlers, depth+1,handlers,
checker); checker);
}catch(SnmpStatusException ex) { }catch(SnmpStatusException ex) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} finally { } finally {
checker.remove(depth); checker.remove(depth);
} }
...@@ -455,7 +460,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid ...@@ -455,7 +460,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid
try { try {
checker.checkCurrentOid(); checker.checkCurrentOid();
} catch(SnmpStatusException e) { } catch(SnmpStatusException e) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} finally { } finally {
checker.remove(depth,2); checker.remove(depth,2);
} }
...@@ -500,7 +505,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid ...@@ -500,7 +505,7 @@ public abstract class SnmpMibGroup extends SnmpMibOid
// The oid is not valid, we will throw an exception in order // The oid is not valid, we will throw an exception in order
// to try with the next valid identifier... // to try with the next valid identifier...
// //
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} catch (SnmpStatusException e) { } catch (SnmpStatusException e) {
// We didn't find anything at the given arc, so we're going // We didn't find anything at the given arc, so we're going
......
...@@ -155,7 +155,7 @@ public abstract class SnmpMibNode implements Serializable { ...@@ -155,7 +155,7 @@ public abstract class SnmpMibNode implements Serializable {
long[] oid, int depth, long[] oid, int depth,
SnmpRequestTree handlers) SnmpRequestTree handlers)
throws SnmpStatusException { throws SnmpStatusException {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} }
/** /**
...@@ -183,7 +183,7 @@ public abstract class SnmpMibNode implements Serializable { ...@@ -183,7 +183,7 @@ public abstract class SnmpMibNode implements Serializable {
long[] oid, int pos, int depth, long[] oid, int pos, int depth,
SnmpRequestTree handlers, AcmChecker checker) SnmpRequestTree handlers, AcmChecker checker)
throws SnmpStatusException { throws SnmpStatusException {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} }
/** /**
...@@ -346,8 +346,9 @@ public abstract class SnmpMibNode implements Serializable { ...@@ -346,8 +346,9 @@ public abstract class SnmpMibNode implements Serializable {
final int[] a = table; final int[] a = table;
final int val= (int) value; final int val= (int) value;
if (a == null) if (a == null) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
int low= 0; int low= 0;
int max= a.length; int max= a.length;
...@@ -356,11 +357,13 @@ public abstract class SnmpMibNode implements Serializable { ...@@ -356,11 +357,13 @@ public abstract class SnmpMibNode implements Serializable {
// Basic check // Basic check
// //
if (max < 1) if (max < 1) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
if (a[max-1] <= val) if (a[max-1] <= val) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
while (low <= max) { while (low <= max) {
elmt= a[curr]; elmt= a[curr];
...@@ -400,15 +403,4 @@ public abstract class SnmpMibNode implements Serializable { ...@@ -400,15 +403,4 @@ public abstract class SnmpMibNode implements Serializable {
* Contains the list of variable identifiers. * Contains the list of variable identifiers.
*/ */
protected int[] varList; protected int[] varList;
/**
* Contains a predefined exception that is often fired when an
* object is not found in the MIB.
*/
static final protected SnmpStatusException noSuchInstanceException =
new SnmpStatusException(SnmpStatusException.noSuchInstance);
static final protected SnmpStatusException noSuchObjectException =
new SnmpStatusException(SnmpStatusException.noSuchObject);
static final protected SnmpStatusException noSuchNameException =
new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName);
} }
...@@ -160,12 +160,10 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { ...@@ -160,12 +160,10 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable {
if (depth > length) { if (depth > length) {
// Nothing is left... the oid is not valid // Nothing is left... the oid is not valid
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} else if (depth == length) { } else if (depth == length) {
// The oid is not complete... // The oid is not complete...
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
} else { } else {
// Some children variable or subobject is being querried // Some children variable or subobject is being querried
// getChild() will raise an exception if no child is found. // getChild() will raise an exception if no child is found.
...@@ -205,12 +203,13 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { ...@@ -205,12 +203,13 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable {
final int length = oid.length; final int length = oid.length;
SnmpMibNode node = null; SnmpMibNode node = null;
long[] result = null; long[] result = null;
if (handlers == null) if (handlers == null) {
// This should be considered as a genErr, but we do not want to // This should be considered as a genErr, but we do not want to
// abort the whole request, so we're going to throw // abort the whole request, so we're going to throw
// a noSuchObject... // a noSuchObject...
// //
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
final Object data = handlers.getUserData(); final Object data = handlers.getUserData();
final int pduVersion = handlers.getRequestPduVersion(); final int pduVersion = handlers.getRequestPduVersion();
...@@ -235,7 +234,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { ...@@ -235,7 +234,7 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable {
// SnmpOid result = null; // SnmpOid result = null;
if (child == null) { if (child == null) {
// shouldn't happen // shouldn't happen
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
// validateVarId(index); // validateVarId(index);
// handlers.add(this,varbind,depth); // handlers.add(this,varbind,depth);
// result = new SnmpOid(0); // result = new SnmpOid(0);
...@@ -444,11 +443,13 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { ...@@ -444,11 +443,13 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable {
// first we need to retrieve the identifier in the list of children // first we need to retrieve the identifier in the list of children
// //
final int pos= getInsertAt(id); final int pos= getInsertAt(id);
if (pos >= nbChildren) if (pos >= nbChildren) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
if (varList[pos] != (int) id) if (varList[pos] != (int) id) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
// Access the node // Access the node
// //
...@@ -456,10 +457,11 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable { ...@@ -456,10 +457,11 @@ public class SnmpMibOid extends SnmpMibNode implements Serializable {
try { try {
child = children.elementAtNonSync(pos); child = children.elementAtNonSync(pos);
} catch(ArrayIndexOutOfBoundsException e) { } catch(ArrayIndexOutOfBoundsException e) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
if (child == null) {
throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
} }
if (child == null)
throw noSuchInstanceException;
return child; return child;
} }
......
...@@ -280,7 +280,7 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -280,7 +280,7 @@ public abstract class SnmpMibTable extends SnmpMibNode
SnmpVarBind var; SnmpVarBind var;
for (Enumeration<SnmpVarBind> e= r.getElements(); e.hasMoreElements();) { for (Enumeration<SnmpVarBind> e= r.getElements(); e.hasMoreElements();) {
var = e.nextElement(); var = e.nextElement();
r.registerGetException(var,noSuchInstanceException); r.registerGetException(var,new SnmpStatusException(SnmpStatusException.noSuchInstance));
} }
} }
...@@ -1607,8 +1607,9 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1607,8 +1607,9 @@ public abstract class SnmpMibTable extends SnmpMibNode
protected SnmpOid getNextOid(SnmpOid oid, Object userData) protected SnmpOid getNextOid(SnmpOid oid, Object userData)
throws SnmpStatusException { throws SnmpStatusException {
if (size == 0) if (size == 0) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
final SnmpOid resOid = oid; final SnmpOid resOid = oid;
...@@ -1619,7 +1620,7 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1619,7 +1620,7 @@ public abstract class SnmpMibTable extends SnmpMibNode
if (last.equals(resOid)) { if (last.equals(resOid)) {
// Last element of the table ... // Last element of the table ...
// //
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
} }
// First find the oid. This will allow to speed up retrieval process // First find the oid. This will allow to speed up retrieval process
...@@ -1641,12 +1642,12 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1641,12 +1642,12 @@ public abstract class SnmpMibTable extends SnmpMibNode
// XX last = (SnmpOid) oids.elementAt(newPos); // XX last = (SnmpOid) oids.elementAt(newPos);
last = tableoids[newPos]; last = tableoids[newPos];
} catch(ArrayIndexOutOfBoundsException e) { } catch(ArrayIndexOutOfBoundsException e) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
} }
} else { } else {
// We are dealing with the last element of the table .. // We are dealing with the last element of the table ..
// //
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
} }
...@@ -1668,8 +1669,9 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1668,8 +1669,9 @@ public abstract class SnmpMibTable extends SnmpMibNode
*/ */
protected SnmpOid getNextOid(Object userData) protected SnmpOid getNextOid(Object userData)
throws SnmpStatusException { throws SnmpStatusException {
if (size == 0) if (size == 0) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
// XX return (SnmpOid) oids.firstElement(); // XX return (SnmpOid) oids.firstElement();
return tableoids[0]; return tableoids[0];
} }
...@@ -1875,10 +1877,10 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1875,10 +1877,10 @@ public abstract class SnmpMibTable extends SnmpMibNode
// not support creation. // not support creation.
// We know that the entry does not exists if (isentry == false). // We know that the entry does not exists if (isentry == false).
if (!hasEntry) { if (!hasEntry) {
if (!handlers.isCreationAllowed()) if (!handlers.isCreationAllowed()) {
// we're not doing a set // we're not doing a set
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
else if (!isCreationEnabled()) } else if (!isCreationEnabled())
// we're doing a set but creation is disabled. // we're doing a set but creation is disabled.
throw new throw new
SnmpStatusException(SnmpStatusException.snmpRspNoAccess); SnmpStatusException(SnmpStatusException.snmpRspNoAccess);
...@@ -1922,12 +1924,13 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1922,12 +1924,13 @@ public abstract class SnmpMibTable extends SnmpMibNode
int length = oid.length; int length = oid.length;
if (handlers == null) if (handlers == null) {
// This should be considered as a genErr, but we do not want to // This should be considered as a genErr, but we do not want to
// abort the whole request, so we're going to throw // abort the whole request, so we're going to throw
// a noSuchObject... // a noSuchObject...
// //
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
final Object data = handlers.getUserData(); final Object data = handlers.getUserData();
final int pduVersion = handlers.getRequestPduVersion(); final int pduVersion = handlers.getRequestPduVersion();
...@@ -1961,7 +1964,7 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -1961,7 +1964,7 @@ public abstract class SnmpMibTable extends SnmpMibNode
// so we won't find the next element in this table... (any // so we won't find the next element in this table... (any
// element in this table will have a smaller OID) // element in this table will have a smaller OID)
// //
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
} else if (oid[pos] < nodeId) { } else if (oid[pos] < nodeId) {
// we must return the first leaf under the first columnar // we must return the first leaf under the first columnar
// object, so we are back to our first case where pos was // object, so we are back to our first case where pos was
...@@ -2051,8 +2054,9 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -2051,8 +2054,9 @@ public abstract class SnmpMibTable extends SnmpMibNode
// in tables can't be properly supported (all rows // in tables can't be properly supported (all rows
// must have the same holes) // must have the same holes)
// //
if (skipEntryVariable(entryoid,var,data,pduVersion)) if (skipEntryVariable(entryoid,var,data,pduVersion)) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
} catch(SnmpStatusException se) { } catch(SnmpStatusException se) {
entryoid = getNextOid(data); entryoid = getNextOid(data);
var = getNextVarEntryId(entryoid,var,data,pduVersion); var = getNextVarEntryId(entryoid,var,data,pduVersion);
...@@ -2085,8 +2089,9 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -2085,8 +2089,9 @@ public abstract class SnmpMibTable extends SnmpMibNode
// So we throw the exception. // So we throw the exception.
// => will skip to next node in the MIB tree. // => will skip to next node in the MIB tree.
// //
if (entryoid == null || var == -1 ) throw noSuchObjectException; if (entryoid == null || var == -1 ) {
throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
// So here we know both the row (entryoid) and the column (var) // So here we know both the row (entryoid) and the column (var)
// //
...@@ -2097,8 +2102,9 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -2097,8 +2102,9 @@ public abstract class SnmpMibTable extends SnmpMibNode
// for this specific entry, it is not readable for any // for this specific entry, it is not readable for any
// other entry => skip to next column. // other entry => skip to next column.
// //
if (!isReadableEntryId(entryoid,var,data)) if (!isReadableEntryId(entryoid,var,data)) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
// Prepare the result and the ACM checker. // Prepare the result and the ACM checker.
// //
...@@ -2161,8 +2167,9 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -2161,8 +2167,9 @@ public abstract class SnmpMibTable extends SnmpMibNode
// No need to continue, we throw an exception. // No need to continue, we throw an exception.
// => will skip to next node in the MIB tree. // => will skip to next node in the MIB tree.
// //
if (entryoid == null || var == -1 ) if (entryoid == null || var == -1 ) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
} }
} }
...@@ -2182,14 +2189,15 @@ public abstract class SnmpMibTable extends SnmpMibNode ...@@ -2182,14 +2189,15 @@ public abstract class SnmpMibTable extends SnmpMibNode
// Control the length of the oid // Control the length of the oid
// //
if (pos +2 >= length) if (pos +2 >= length) {
throw noSuchInstanceException; throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
}
// Check that the entry identifier is specified // Check that the entry identifier is specified
// //
if (oid[pos] != nodeId) if (oid[pos] != nodeId) {
throw noSuchObjectException; throw new SnmpStatusException(SnmpStatusException.noSuchObject);
}
} }
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
......
...@@ -1146,7 +1146,4 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions { ...@@ -1146,7 +1146,4 @@ class SnmpRequestHandler extends ClientHandler implements SnmpDefinitions {
static final private String InterruptSysCallMsg = static final private String InterruptSysCallMsg =
"Interrupted system call"; "Interrupted system call";
static final private SnmpStatusException noSuchNameException =
new SnmpStatusException(SnmpDefinitions.snmpRspNoSuchName) ;
} }
...@@ -56,9 +56,12 @@ public final class FactoryEnumeration { ...@@ -56,9 +56,12 @@ public final class FactoryEnumeration {
* references so as not to prevent GC of the class loader. Each * references so as not to prevent GC of the class loader. Each
* weak reference is tagged with the factory's class name so the * weak reference is tagged with the factory's class name so the
* class can be reloaded if the reference is cleared. * class can be reloaded if the reference is cleared.
*
* @param factories A non-null list * @param factories A non-null list
* @param loader The class loader of the list's contents * @param loader The class loader of the list's contents
*
* This internal method is used with Thread Context Class Loader (TCCL),
* please don't expose this method as public.
*/ */
FactoryEnumeration(List<NamedWeakReference<Object>> factories, FactoryEnumeration(List<NamedWeakReference<Object>> factories,
ClassLoader loader) { ClassLoader loader) {
...@@ -79,7 +82,9 @@ public final class FactoryEnumeration { ...@@ -79,7 +82,9 @@ public final class FactoryEnumeration {
try { try {
if (answer == null) { // reload class if weak ref cleared if (answer == null) { // reload class if weak ref cleared
answer = Class.forName(className, true, loader); Class<?> cls = Class.forName(className, true, loader);
VersionHelper12.checkPackageAccess(cls);
answer = cls;
} }
// Instantiate Class to get factory // Instantiate Class to get factory
answer = ((Class) answer).newInstance(); answer = ((Class) answer).newInstance();
......
...@@ -39,6 +39,7 @@ import java.util.NoSuchElementException; ...@@ -39,6 +39,7 @@ import java.util.NoSuchElementException;
import java.util.Properties; import java.util.Properties;
import javax.naming.*; import javax.naming.*;
import sun.reflect.misc.ReflectUtil;
/** /**
* VersionHelper was used by JNDI to accommodate differences between * VersionHelper was used by JNDI to accommodate differences between
...@@ -53,21 +54,39 @@ import javax.naming.*; ...@@ -53,21 +54,39 @@ import javax.naming.*;
final class VersionHelper12 extends VersionHelper { final class VersionHelper12 extends VersionHelper {
private boolean getSystemPropsFailed = false; // workaround to disable additional package access control with
// Thread Context Class Loader (TCCL).
private final static boolean noPackageAccessWithTCCL = "true".equals(
AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return System.getProperty(
"com.sun.naming.untieAccessContextWithTCCL");
}
}
));
VersionHelper12() {} // Disallow external from creating one of these. // Disallow external from creating one of these.
VersionHelper12() {
}
public Class<?> loadClass(String className) throws ClassNotFoundException { public Class<?> loadClass(String className) throws ClassNotFoundException {
ClassLoader cl = getContextClassLoader(); return loadClass(className, getContextClassLoader());
return Class.forName(className, true, cl);
} }
/** /**
* Package private. * Package private.
*/ *
* This internal method is used with Thread Context Class Loader (TCCL),
* please don't expose this method as public.
*/
Class<?> loadClass(String className, ClassLoader cl) Class<?> loadClass(String className, ClassLoader cl)
throws ClassNotFoundException { throws ClassNotFoundException {
return Class.forName(className, true, cl); Class<?> cls = Class.forName(className, true, cl);
if (!noPackageAccessWithTCCL) {
checkPackageAccess(cls);
}
return cls;
} }
/** /**
...@@ -75,13 +94,42 @@ final class VersionHelper12 extends VersionHelper { ...@@ -75,13 +94,42 @@ final class VersionHelper12 extends VersionHelper {
* @param codebase A non-null, space-separated list of URL strings. * @param codebase A non-null, space-separated list of URL strings.
*/ */
public Class<?> loadClass(String className, String codebase) public Class<?> loadClass(String className, String codebase)
throws ClassNotFoundException, MalformedURLException { throws ClassNotFoundException, MalformedURLException {
ClassLoader cl;
ClassLoader parent = getContextClassLoader(); ClassLoader parent = getContextClassLoader();
cl = URLClassLoader.newInstance(getUrlArray(codebase), parent); ClassLoader cl =
URLClassLoader.newInstance(getUrlArray(codebase), parent);
return Class.forName(className, true, cl); return loadClass(className, cl);
}
/**
* check package access of a class that is loaded with Thread Context
* Class Loader (TCCL).
*
* Similar to java.lang.ClassLoader.checkPackageAccess()
*/
static void checkPackageAccess(Class<?> cls) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(cls)) {
for (Class<?> intf: cls.getInterfaces()) {
checkPackageAccess(intf);
}
return;
}
final String name = cls.getName();
final int i = name.lastIndexOf('.');
if (i != -1) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
sm.checkPackageAccess(name.substring(0, i));
return null;
}
}, AccessController.getContext());
}
}
} }
String getJndiProperty(final int i) { String getJndiProperty(final int i) {
...@@ -99,16 +147,12 @@ final class VersionHelper12 extends VersionHelper { ...@@ -99,16 +147,12 @@ final class VersionHelper12 extends VersionHelper {
} }
String[] getJndiProperties() { String[] getJndiProperties() {
if (getSystemPropsFailed) {
return null; // after one failure, don't bother trying again
}
Properties sysProps = AccessController.doPrivileged( Properties sysProps = AccessController.doPrivileged(
new PrivilegedAction<Properties>() { new PrivilegedAction<Properties>() {
public Properties run() { public Properties run() {
try { try {
return System.getProperties(); return System.getProperties();
} catch (SecurityException e) { } catch (SecurityException e) {
getSystemPropsFailed = true;
return null; return null;
} }
} }
...@@ -173,7 +217,17 @@ final class VersionHelper12 extends VersionHelper { ...@@ -173,7 +217,17 @@ final class VersionHelper12 extends VersionHelper {
return new InputStreamEnumeration(urls); return new InputStreamEnumeration(urls);
} }
/**
* Package private.
*
* This internal method makes use of Thread Context Class Loader (TCCL),
* please don't expose this method as public.
*
* Please take care of package access control on the current context
* whenever using TCCL.
*/
ClassLoader getContextClassLoader() { ClassLoader getContextClassLoader() {
return AccessController.doPrivileged( return AccessController.doPrivileged(
new PrivilegedAction<ClassLoader>() { new PrivilegedAction<ClassLoader>() {
public ClassLoader run() { public ClassLoader run() {
...@@ -183,7 +237,6 @@ final class VersionHelper12 extends VersionHelper { ...@@ -183,7 +237,6 @@ final class VersionHelper12 extends VersionHelper {
); );
} }
/** /**
* Given an enumeration of URLs, an instance of this class represents * Given an enumeration of URLs, an instance of this class represents
* an enumeration of their InputStreams. Each operation on the URL * an enumeration of their InputStreams. Each operation on the URL
......
...@@ -382,7 +382,8 @@ public abstract class Canonicalizer11 extends CanonicalizerBase { ...@@ -382,7 +382,8 @@ public abstract class Canonicalizer11 extends CanonicalizerBase {
} else if (!isVisible(xmlns)) { } else if (!isVisible(xmlns)) {
//There is a definition but the xmlns is not selected by the xpath. //There is a definition but the xmlns is not selected by the xpath.
//then xmlns="" //then xmlns=""
n = ns.addMappingAndRender(XMLNS, "", nullNode); n = ns.addMappingAndRender(
XMLNS, "", getNullNode(xmlns.getOwnerDocument()));
} }
//output the xmlns def if needed. //output the xmlns def if needed.
if (n != null) { if (n != null) {
......
...@@ -327,7 +327,8 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase { ...@@ -327,7 +327,8 @@ public abstract class Canonicalizer20010315 extends CanonicalizerBase {
} else if (!isVisible(xmlns)) { } else if (!isVisible(xmlns)) {
//There is a definition but the xmlns is not selected by the xpath. //There is a definition but the xmlns is not selected by the xpath.
//then xmlns="" //then xmlns=""
n = ns.addMappingAndRender(XMLNS, "", nullNode); n = ns.addMappingAndRender(
XMLNS, "", getNullNode(xmlns.getOwnerDocument()));
} }
//output the xmlns def if needed. //output the xmlns def if needed.
if (n != null) { if (n != null) {
......
...@@ -292,7 +292,7 @@ public abstract class Canonicalizer20010315Excl extends CanonicalizerBase { ...@@ -292,7 +292,7 @@ public abstract class Canonicalizer20010315Excl extends CanonicalizerBase {
if (xmlns != null && !isVisible(xmlns)) { if (xmlns != null && !isVisible(xmlns)) {
// There is a definition but the xmlns is not selected by the // There is a definition but the xmlns is not selected by the
// xpath. then xmlns="" // xpath. then xmlns=""
ns.addMapping(XMLNS, "", nullNode); ns.addMapping(XMLNS, "", getNullNode(xmlns.getOwnerDocument()));
} }
String prefix = null; String prefix = null;
......
...@@ -34,8 +34,6 @@ import java.util.ListIterator; ...@@ -34,8 +34,6 @@ import java.util.ListIterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
...@@ -49,6 +47,7 @@ import com.sun.org.apache.xml.internal.security.utils.XMLUtils; ...@@ -49,6 +47,7 @@ import com.sun.org.apache.xml.internal.security.utils.XMLUtils;
import org.w3c.dom.Attr; import org.w3c.dom.Attr;
import org.w3c.dom.Comment; import org.w3c.dom.Comment;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap; import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node; import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.ProcessingInstruction;
...@@ -64,7 +63,6 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { ...@@ -64,7 +63,6 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi {
public static final String XMLNS = "xmlns"; public static final String XMLNS = "xmlns";
protected static final AttrCompare COMPARE = new AttrCompare(); protected static final AttrCompare COMPARE = new AttrCompare();
protected static final Attr nullNode;
private static final byte[] END_PI = {'?','>'}; private static final byte[] END_PI = {'?','>'};
private static final byte[] BEGIN_PI = {'<','?'}; private static final byte[] BEGIN_PI = {'<','?'};
...@@ -84,21 +82,11 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { ...@@ -84,21 +82,11 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi {
protected static final int NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT = 0; protected static final int NODE_NOT_BEFORE_OR_AFTER_DOCUMENT_ELEMENT = 0;
protected static final int NODE_AFTER_DOCUMENT_ELEMENT = 1; protected static final int NODE_AFTER_DOCUMENT_ELEMENT = 1;
static {
// The null xmlns definition.
try {
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
nullNode = documentBuilder.newDocument().createAttributeNS(Constants.NamespaceSpecNS, XMLNS);
nullNode.setValue("");
} catch (Exception e) {
throw new RuntimeException("Unable to create nullNode: " + e);
}
}
private List<NodeFilter> nodeFilter; private List<NodeFilter> nodeFilter;
private boolean includeComments; private boolean includeComments;
private Set<Node> xpathNodeSet; private Set<Node> xpathNodeSet;
/** /**
* The node to be skipped/excluded from the DOM tree * The node to be skipped/excluded from the DOM tree
* in subtree canonicalizations. * in subtree canonicalizations.
...@@ -106,6 +94,11 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { ...@@ -106,6 +94,11 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi {
private Node excludeNode; private Node excludeNode;
private OutputStream writer = new ByteArrayOutputStream(); private OutputStream writer = new ByteArrayOutputStream();
/**
* The null xmlns definition.
*/
private Attr nullNode;
/** /**
* Constructor CanonicalizerBase * Constructor CanonicalizerBase
* *
...@@ -641,8 +634,9 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { ...@@ -641,8 +634,9 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi {
parents.clear(); parents.clear();
Attr nsprefix; Attr nsprefix;
if (((nsprefix = ns.getMappingWithoutRendered(XMLNS)) != null) if (((nsprefix = ns.getMappingWithoutRendered(XMLNS)) != null)
&& "".equals(nsprefix.getValue())) { && "".equals(nsprefix.getValue())) {
ns.addMappingAndRender(XMLNS, "", nullNode); ns.addMappingAndRender(
XMLNS, "", getNullNode(nsprefix.getOwnerDocument()));
} }
} }
...@@ -879,4 +873,18 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { ...@@ -879,4 +873,18 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi {
} }
} }
// The null xmlns definition.
protected Attr getNullNode(Document ownerDocument) {
if (nullNode == null) {
try {
nullNode = ownerDocument.createAttributeNS(
Constants.NamespaceSpecNS, XMLNS);
nullNode.setValue("");
} catch (Exception e) {
throw new RuntimeException("Unable to create nullNode: " + e);
}
}
return nullNode;
}
} }
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -660,7 +660,7 @@ public class XmlReaderContentHandler extends DefaultHandler { ...@@ -660,7 +660,7 @@ public class XmlReaderContentHandler extends DefaultHandler {
//Added the handling for Class tags to take care of maps //Added the handling for Class tags to take care of maps
//Makes an entry into the map upon end of class tag //Makes an entry into the map upon end of class tag
try{ try{
typeMap.put(Key_map,Class.forName(Value_map)); typeMap.put(Key_map,sun.reflect.misc.ReflectUtil.forName(Value_map));
}catch(ClassNotFoundException ex) { }catch(ClassNotFoundException ex) {
throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmap").toString(), ex.getMessage())); throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmap").toString(), ex.getMessage()));
......
...@@ -53,6 +53,13 @@ import sun.misc.SharedSecrets; ...@@ -53,6 +53,13 @@ import sun.misc.SharedSecrets;
* or method in this class will cause a {@link NullPointerException} to be * or method in this class will cause a {@link NullPointerException} to be
* thrown. * thrown.
* *
* If the verify flag is on when opening a signed jar file, the content of the
* file is verified against its signature embedded inside the file. Please note
* that the verification process does not include validating the signer's
* certificate. A caller should inspect the return value of
* {@link JarEntry#getCodeSigners()} to further determine if the signature
* can be trusted.
*
* @author David Connelly * @author David Connelly
* @see Manifest * @see Manifest
* @see java.util.zip.ZipFile * @see java.util.zip.ZipFile
......
...@@ -179,7 +179,9 @@ class JarVerifier { ...@@ -179,7 +179,9 @@ class JarVerifier {
name = name.substring(1); name = name.substring(1);
// only set the jev object for entries that have a signature // only set the jev object for entries that have a signature
if (sigFileSigners.get(name) != null) { // (either verified or not)
if (sigFileSigners.get(name) != null ||
verifiedSigners.get(name) != null) {
mev.setEntry(name, je); mev.setEntry(name, je);
return; return;
} }
......
...@@ -241,6 +241,11 @@ public class LogManager { ...@@ -241,6 +241,11 @@ public class LogManager {
* retrieved by calling LogManager.getLogManager. * retrieved by calling LogManager.getLogManager.
*/ */
protected LogManager() { protected LogManager() {
this(checkSubclassPermissions());
}
private LogManager(Void checked) {
// Add a shutdown hook to close the global handlers. // Add a shutdown hook to close the global handlers.
try { try {
Runtime.getRuntime().addShutdownHook(new Cleaner()); Runtime.getRuntime().addShutdownHook(new Cleaner());
...@@ -250,6 +255,19 @@ public class LogManager { ...@@ -250,6 +255,19 @@ public class LogManager {
} }
} }
private static Void checkSubclassPermissions() {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// These permission will be checked in the LogManager constructor,
// in order to register the Cleaner() thread as a shutdown hook.
// Check them here to avoid the penalty of constructing the object
// etc...
sm.checkPermission(new RuntimePermission("shutdownHooks"));
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
return null;
}
/** /**
* Lazy initialization: if this instance of manager is the global * Lazy initialization: if this instance of manager is the global
* manager then this method will read the initial configuration and * manager then this method will read the initial configuration and
......
...@@ -91,7 +91,10 @@ public final class SimpleDoc implements Doc { ...@@ -91,7 +91,10 @@ public final class SimpleDoc implements Doc {
Class repClass = null; Class repClass = null;
try { try {
repClass = Class.forName(flavor.getRepresentationClassName()); String className = flavor.getRepresentationClassName();
sun.reflect.misc.ReflectUtil.checkPackageAccess(className);
repClass = Class.forName(className, false,
Thread.currentThread().getContextClassLoader());
} catch (Throwable e) { } catch (Throwable e) {
throw new IllegalArgumentException("unknown representation class"); throw new IllegalArgumentException("unknown representation class");
} }
......
...@@ -26,6 +26,10 @@ ...@@ -26,6 +26,10 @@
package javax.security.auth; package javax.security.auth;
import java.security.Security; import java.security.Security;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;
import java.util.Objects;
import sun.security.util.Debug; import sun.security.util.Debug;
/** /**
...@@ -155,22 +159,15 @@ import sun.security.util.Debug; ...@@ -155,22 +159,15 @@ import sun.security.util.Debug;
public abstract class Policy { public abstract class Policy {
private static Policy policy; private static Policy policy;
private static ClassLoader contextClassLoader;
private final static String AUTH_POLICY = private final static String AUTH_POLICY =
"sun.security.provider.AuthPolicyFile"; "sun.security.provider.AuthPolicyFile";
private final java.security.AccessControlContext acc =
java.security.AccessController.getContext();
// true if a custom (not AUTH_POLICY) system-wide policy object is set // true if a custom (not AUTH_POLICY) system-wide policy object is set
private static boolean isCustomPolicy; private static boolean isCustomPolicy;
static {
contextClassLoader = java.security.AccessController.doPrivileged
(new java.security.PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
};
/** /**
* Sole constructor. (For invocation by subclass constructors, typically * Sole constructor. (For invocation by subclass constructors, typically
* implicit.) * implicit.)
...@@ -213,8 +210,8 @@ public abstract class Policy { ...@@ -213,8 +210,8 @@ public abstract class Policy {
if (policy == null) { if (policy == null) {
String policy_class = null; String policy_class = null;
policy_class = java.security.AccessController.doPrivileged policy_class = AccessController.doPrivileged
(new java.security.PrivilegedAction<String>() { (new PrivilegedAction<String>() {
public String run() { public String run() {
return java.security.Security.getProperty return java.security.Security.getProperty
("auth.policy.provider"); ("auth.policy.provider");
...@@ -226,18 +223,28 @@ public abstract class Policy { ...@@ -226,18 +223,28 @@ public abstract class Policy {
try { try {
final String finalClass = policy_class; final String finalClass = policy_class;
policy = java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<Policy>() { Policy untrustedImpl = AccessController.doPrivileged(
public Policy run() throws ClassNotFoundException, new PrivilegedExceptionAction<Policy>() {
InstantiationException, public Policy run() throws ClassNotFoundException,
IllegalAccessException { InstantiationException,
return (Policy) Class.forName IllegalAccessException {
(finalClass, Class<? extends Policy> implClass = Class.forName(
true, finalClass, false,
contextClassLoader).newInstance(); Thread.currentThread().getContextClassLoader()
} ).asSubclass(Policy.class);
}); return implClass.newInstance();
isCustomPolicy = !finalClass.equals(AUTH_POLICY); }
});
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() {
setPolicy(untrustedImpl);
isCustomPolicy = !finalClass.equals(AUTH_POLICY);
return null;
}
}, Objects.requireNonNull(untrustedImpl.acc)
);
} catch (Exception e) { } catch (Exception e) {
throw new SecurityException throw new SecurityException
(sun.security.util.ResourcesMgr.getString (sun.security.util.ResourcesMgr.getString
......
...@@ -964,6 +964,10 @@ public final class Subject implements java.io.Serializable { ...@@ -964,6 +964,10 @@ public final class Subject implements java.io.Serializable {
s.defaultReadObject(); s.defaultReadObject();
// Rewrap the principals into a SecureSet
principals = Collections.synchronizedSet(new SecureSet<Principal>
(this, PRINCIPAL_SET, principals));
// The Credential {@code Set} is not serialized, but we do not // The Credential {@code Set} is not serialized, but we do not
// want the default deserialization routine to set it to null. // want the default deserialization routine to set it to null.
this.pubCredentials = Collections.synchronizedSet this.pubCredentials = Collections.synchronizedSet
......
...@@ -27,9 +27,6 @@ package javax.security.auth.login; ...@@ -27,9 +27,6 @@ package javax.security.auth.login;
import javax.security.auth.AuthPermission; import javax.security.auth.AuthPermission;
import java.io.*;
import java.util.*;
import java.net.URI;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
...@@ -38,7 +35,7 @@ import java.security.NoSuchAlgorithmException; ...@@ -38,7 +35,7 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException; import java.security.NoSuchProviderException;
import java.security.Provider; import java.security.Provider;
import java.security.Security; import java.security.Security;
import java.security.SecurityPermission; import java.util.Objects;
import sun.security.jca.GetInstance; import sun.security.jca.GetInstance;
...@@ -191,16 +188,9 @@ import sun.security.jca.GetInstance; ...@@ -191,16 +188,9 @@ import sun.security.jca.GetInstance;
public abstract class Configuration { public abstract class Configuration {
private static Configuration configuration; private static Configuration configuration;
private static ClassLoader contextClassLoader;
static { private final java.security.AccessControlContext acc =
contextClassLoader = AccessController.doPrivileged java.security.AccessController.getContext();
(new PrivilegedAction<ClassLoader>() {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
});
};
private static void checkPermission(String type) { private static void checkPermission(String type) {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
...@@ -253,17 +243,26 @@ public abstract class Configuration { ...@@ -253,17 +243,26 @@ public abstract class Configuration {
try { try {
final String finalClass = config_class; final String finalClass = config_class;
configuration = AccessController.doPrivileged Configuration untrustedImpl = AccessController.doPrivileged(
(new PrivilegedExceptionAction<Configuration>() { new PrivilegedExceptionAction<Configuration>() {
public Configuration run() throws ClassNotFoundException, public Configuration run() throws ClassNotFoundException,
InstantiationException, InstantiationException,
IllegalAccessException { IllegalAccessException {
return (Configuration)Class.forName Class<? extends Configuration> implClass = Class.forName(
(finalClass, finalClass, false,
true, Thread.currentThread().getContextClassLoader()
contextClassLoader).newInstance(); ).asSubclass(Configuration.class);
} return implClass.newInstance();
}); }
});
AccessController.doPrivileged(
new PrivilegedExceptionAction<Void>() {
public Void run() {
setConfiguration(untrustedImpl);
return null;
}
}, Objects.requireNonNull(untrustedImpl.acc)
);
} catch (PrivilegedActionException e) { } catch (PrivilegedActionException e) {
Exception ee = e.getException(); Exception ee = e.getException();
if (ee instanceof InstantiationException) { if (ee instanceof InstantiationException) {
......
...@@ -37,8 +37,10 @@ import javax.security.auth.AuthPermission; ...@@ -37,8 +37,10 @@ import javax.security.auth.AuthPermission;
import javax.security.auth.callback.*; import javax.security.auth.callback.*;
import java.security.AccessController; import java.security.AccessController;
import java.security.AccessControlContext; import java.security.AccessControlContext;
import java.security.PrivilegedAction;
import sun.security.util.PendingException; import sun.security.util.PendingException;
import sun.security.util.ResourcesMgr; import sun.security.util.ResourcesMgr;
import sun.reflect.misc.ReflectUtil;
/** /**
* <p> The {@code LoginContext} class describes the basic methods used * <p> The {@code LoginContext} class describes the basic methods used
...@@ -209,8 +211,7 @@ public class LoginContext { ...@@ -209,8 +211,7 @@ public class LoginContext {
private Map<String,?> state = new HashMap<String,Object>(); private Map<String,?> state = new HashMap<String,Object>();
private Configuration config; private Configuration config;
private boolean configProvided = false; private AccessControlContext creatorAcc = null; // customized config only
private AccessControlContext creatorAcc = null;
private ModuleInfo[] moduleStack; private ModuleInfo[] moduleStack;
private ClassLoader contextClassLoader = null; private ClassLoader contextClassLoader = null;
private static final Class<?>[] PARAMS = { }; private static final Class<?>[] PARAMS = { };
...@@ -226,10 +227,23 @@ public class LoginContext { ...@@ -226,10 +227,23 @@ public class LoginContext {
private static final sun.security.util.Debug debug = private static final sun.security.util.Debug debug =
sun.security.util.Debug.getInstance("logincontext", "\t[LoginContext]"); sun.security.util.Debug.getInstance("logincontext", "\t[LoginContext]");
// workaround to disable additional package access control with
// Thread Context Class Loader (TCCL).
private static final boolean noPackageAccessWithTCCL = "true".equals(
AccessController.doPrivileged(
new PrivilegedAction<String>() {
public String run() {
return System.getProperty(
"auth.login.untieAccessContextWithTCCL");
}
}
));
private void init(String name) throws LoginException { private void init(String name) throws LoginException {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null && !configProvided) { if (sm != null && creatorAcc == null) {
sm.checkPermission(new AuthPermission sm.checkPermission(new AuthPermission
("createLoginContext." + name)); ("createLoginContext." + name));
} }
...@@ -252,7 +266,7 @@ public class LoginContext { ...@@ -252,7 +266,7 @@ public class LoginContext {
AppConfigurationEntry[] entries = config.getAppConfigurationEntry(name); AppConfigurationEntry[] entries = config.getAppConfigurationEntry(name);
if (entries == null) { if (entries == null) {
if (sm != null && !configProvided) { if (sm != null && creatorAcc == null) {
sm.checkPermission(new AuthPermission sm.checkPermission(new AuthPermission
("createLoginContext." + OTHER)); ("createLoginContext." + OTHER));
} }
...@@ -298,10 +312,10 @@ public class LoginContext { ...@@ -298,10 +312,10 @@ public class LoginContext {
(DEFAULT_HANDLER); (DEFAULT_HANDLER);
if (defaultHandler == null || defaultHandler.length() == 0) if (defaultHandler == null || defaultHandler.length() == 0)
return null; return null;
Class<?> c = Class.forName(defaultHandler, Class<? extends CallbackHandler> c = Class.forName(
true, defaultHandler, true,
finalLoader); finalLoader).asSubclass(CallbackHandler.class);
return (CallbackHandler)c.newInstance(); return c.newInstance();
} }
}); });
} catch (java.security.PrivilegedActionException pae) { } catch (java.security.PrivilegedActionException pae) {
...@@ -309,7 +323,7 @@ public class LoginContext { ...@@ -309,7 +323,7 @@ public class LoginContext {
} }
// secure it with the caller's ACC // secure it with the caller's ACC
if (this.callbackHandler != null && !configProvided) { if (this.callbackHandler != null && creatorAcc == null) {
this.callbackHandler = new SecureCallbackHandler this.callbackHandler = new SecureCallbackHandler
(java.security.AccessController.getContext(), (java.security.AccessController.getContext(),
this.callbackHandler); this.callbackHandler);
...@@ -498,8 +512,7 @@ public class LoginContext { ...@@ -498,8 +512,7 @@ public class LoginContext {
CallbackHandler callbackHandler, CallbackHandler callbackHandler,
Configuration config) throws LoginException { Configuration config) throws LoginException {
this.config = config; this.config = config;
configProvided = (config != null) ? true : false; if (config != null) {
if (configProvided) {
creatorAcc = java.security.AccessController.getContext(); creatorAcc = java.security.AccessController.getContext();
} }
...@@ -510,7 +523,7 @@ public class LoginContext { ...@@ -510,7 +523,7 @@ public class LoginContext {
} }
if (callbackHandler == null) { if (callbackHandler == null) {
loadDefaultCallbackHandler(); loadDefaultCallbackHandler();
} else if (!configProvided) { } else if (creatorAcc == null) {
this.callbackHandler = new SecureCallbackHandler this.callbackHandler = new SecureCallbackHandler
(java.security.AccessController.getContext(), (java.security.AccessController.getContext(),
callbackHandler); callbackHandler);
...@@ -577,23 +590,13 @@ public class LoginContext { ...@@ -577,23 +590,13 @@ public class LoginContext {
} }
try { try {
if (configProvided) { // module invoked in doPrivileged
// module invoked in doPrivileged with creatorAcc invokePriv(LOGIN_METHOD);
invokeCreatorPriv(LOGIN_METHOD); invokePriv(COMMIT_METHOD);
invokeCreatorPriv(COMMIT_METHOD);
} else {
// module invoked in doPrivileged
invokePriv(LOGIN_METHOD);
invokePriv(COMMIT_METHOD);
}
loginSucceeded = true; loginSucceeded = true;
} catch (LoginException le) { } catch (LoginException le) {
try { try {
if (configProvided) { invokePriv(ABORT_METHOD);
invokeCreatorPriv(ABORT_METHOD);
} else {
invokePriv(ABORT_METHOD);
}
} catch (LoginException le2) { } catch (LoginException le2) {
throw le; throw le;
} }
...@@ -628,13 +631,8 @@ public class LoginContext { ...@@ -628,13 +631,8 @@ public class LoginContext {
("null.subject.logout.called.before.login")); ("null.subject.logout.called.before.login"));
} }
if (configProvided) { // module invoked in doPrivileged
// module invoked in doPrivileged with creatorAcc invokePriv(LOGOUT_METHOD);
invokeCreatorPriv(LOGOUT_METHOD);
} else {
// module invoked in doPrivileged
invokePriv(LOGOUT_METHOD);
}
} }
/** /**
...@@ -677,35 +675,13 @@ public class LoginContext { ...@@ -677,35 +675,13 @@ public class LoginContext {
/** /**
* Invokes the login, commit, and logout methods * Invokes the login, commit, and logout methods
* from a LoginModule inside a doPrivileged block. * from a LoginModule inside a doPrivileged block restricted
* by creatorAcc (may be null).
* *
* This version is called if the caller did not instantiate * This version is called if the caller did not instantiate
* the LoginContext with a Configuration object. * the LoginContext with a Configuration object.
*/ */
private void invokePriv(final String methodName) throws LoginException { private void invokePriv(final String methodName) throws LoginException {
try {
java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<Void>() {
public Void run() throws LoginException {
invoke(methodName);
return null;
}
});
} catch (java.security.PrivilegedActionException pae) {
throw (LoginException)pae.getException();
}
}
/**
* Invokes the login, commit, and logout methods
* from a LoginModule inside a doPrivileged block restricted
* by creatorAcc
*
* This version is called if the caller instantiated
* the LoginContext with a Configuration object.
*/
private void invokeCreatorPriv(final String methodName)
throws LoginException {
try { try {
java.security.AccessController.doPrivileged java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<Void>() { (new java.security.PrivilegedExceptionAction<Void>() {
...@@ -735,24 +711,30 @@ public class LoginContext { ...@@ -735,24 +711,30 @@ public class LoginContext {
} else { } else {
// instantiate the LoginModule // instantiate the LoginModule
Class<?> c = Class.forName //
(moduleStack[i].entry.getLoginModuleName(), // Allow any object to be a LoginModule as long as it
// conforms to the interface if no customized config or
// noPackageAccessWithTCCL is true.
Class<?> c = Class.forName(
moduleStack[i].entry.getLoginModuleName(),
true, true,
contextClassLoader); contextClassLoader);
// check package access for customized config
if (!noPackageAccessWithTCCL && creatorAcc != null) {
c.asSubclass(javax.security.auth.spi.LoginModule.class);
checkPackageAccess(c, creatorAcc);
}
Constructor<?> constructor = c.getConstructor(PARAMS); Constructor<?> constructor = c.getConstructor(PARAMS);
Object[] args = { }; Object[] args = { };
// allow any object to be a LoginModule
// as long as it conforms to the interface
moduleStack[i].module = constructor.newInstance(args); moduleStack[i].module = constructor.newInstance(args);
methods = moduleStack[i].module.getClass().getMethods();
// call the LoginModule's initialize method // call the LoginModule's initialize method
methods = moduleStack[i].module.getClass().getMethods();
for (mIndex = 0; mIndex < methods.length; mIndex++) { for (mIndex = 0; mIndex < methods.length; mIndex++) {
if (methods[mIndex].getName().equals(INIT_METHOD)) if (methods[mIndex].getName().equals(INIT_METHOD)) {
break; break;
}
} }
Object[] initArgs = {subject, Object[] initArgs = {subject,
...@@ -760,19 +742,28 @@ public class LoginContext { ...@@ -760,19 +742,28 @@ public class LoginContext {
state, state,
moduleStack[i].entry.getOptions() }; moduleStack[i].entry.getOptions() };
// invoke the LoginModule initialize method // invoke the LoginModule initialize method
//
// Throws ArrayIndexOutOfBoundsException if no such
// method defined. May improve to use LoginException in
// the future.
methods[mIndex].invoke(moduleStack[i].module, initArgs); methods[mIndex].invoke(moduleStack[i].module, initArgs);
} }
// find the requested method in the LoginModule // find the requested method in the LoginModule
for (mIndex = 0; mIndex < methods.length; mIndex++) { for (mIndex = 0; mIndex < methods.length; mIndex++) {
if (methods[mIndex].getName().equals(methodName)) if (methods[mIndex].getName().equals(methodName)) {
break; break;
}
} }
// set up the arguments to be passed to the LoginModule method // set up the arguments to be passed to the LoginModule method
Object[] args = { }; Object[] args = { };
// invoke the LoginModule method // invoke the LoginModule method
//
// Throws ArrayIndexOutOfBoundsException if no such
// method defined. May improve to use LoginException in
// the future.
boolean status = ((Boolean)methods[mIndex].invoke boolean status = ((Boolean)methods[mIndex].invoke
(moduleStack[i].module, args)).booleanValue(); (moduleStack[i].module, args)).booleanValue();
...@@ -935,6 +926,35 @@ public class LoginContext { ...@@ -935,6 +926,35 @@ public class LoginContext {
} }
} }
/**
* check package access of a class that is loaded with Thread Context
* Class Loader (TCCL) with specified access control context.
*
* Similar to java.lang.ClassLoader.checkPackageAccess()
*/
static void checkPackageAccess(Class<?> cls, AccessControlContext context) {
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(cls)) {
for (Class<?> intf: cls.getInterfaces()) {
checkPackageAccess(intf, context);
}
return;
}
final String name = cls.getName();
final int i = name.lastIndexOf('.');
if (i != -1) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
sm.checkPackageAccess(name.substring(0, i));
return null;
}
}, context);
}
}
}
/** /**
* Wrap the caller-specified CallbackHandler in our own * Wrap the caller-specified CallbackHandler in our own
* and invoke it within a privileged block, constrained by * and invoke it within a privileged block, constrained by
......
...@@ -35,6 +35,8 @@ import java.io.FileInputStream; ...@@ -35,6 +35,8 @@ import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.io.IOException; import java.io.IOException;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.naming.*; import javax.naming.*;
...@@ -348,7 +350,17 @@ public class SyncFactory { ...@@ -348,7 +350,17 @@ public class SyncFactory {
/* /*
* Dependent on application * Dependent on application
*/ */
String strRowsetProperties = System.getProperty("rowset.properties"); String strRowsetProperties;
try {
strRowsetProperties = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("rowset.properties");
}
}, null, new PropertyPermission("rowset.properties","read"));
} catch (Exception ex) {
strRowsetProperties = null;
}
if (strRowsetProperties != null) { if (strRowsetProperties != null) {
// Load user's implementation of SyncProvider // Load user's implementation of SyncProvider
// here. -Drowset.properties=/abc/def/pqr.txt // here. -Drowset.properties=/abc/def/pqr.txt
...@@ -393,7 +405,16 @@ public class SyncFactory { ...@@ -393,7 +405,16 @@ public class SyncFactory {
* load additional properties from -D command line * load additional properties from -D command line
*/ */
properties.clear(); properties.clear();
String providerImpls = System.getProperty(ROWSET_SYNC_PROVIDER); String providerImpls;
try {
providerImpls = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty(ROWSET_SYNC_PROVIDER);
}
}, null, new PropertyPermission(ROWSET_SYNC_PROVIDER,"read"));
} catch (Exception ex) {
providerImpls = null;
}
if (providerImpls != null) { if (providerImpls != null) {
int i = 0; int i = 0;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
*/ */
package javax.swing; package javax.swing;
import sun.reflect.misc.ReflectUtil;
import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2;
import sun.swing.UIAction; import sun.swing.UIAction;
...@@ -33,9 +34,6 @@ import java.awt.*; ...@@ -33,9 +34,6 @@ import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
import java.awt.dnd.DropTarget; import java.awt.dnd.DropTarget;
import java.util.Vector;
import java.util.Hashtable;
import java.lang.reflect.*; import java.lang.reflect.*;
import javax.accessibility.*; import javax.accessibility.*;
...@@ -1872,6 +1870,7 @@ public class SwingUtilities implements SwingConstants ...@@ -1872,6 +1870,7 @@ public class SwingUtilities implements SwingConstants
static Class<?> loadSystemClass(String className) throws ClassNotFoundException { static Class<?> loadSystemClass(String className) throws ClassNotFoundException {
ReflectUtil.checkPackageAccess(className);
return Class.forName(className, true, Thread.currentThread(). return Class.forName(className, true, Thread.currentThread().
getContextClassLoader()); getContextClassLoader());
} }
......
...@@ -27,6 +27,7 @@ package javax.swing.event; ...@@ -27,6 +27,7 @@ package javax.swing.event;
import java.io.*; import java.io.*;
import java.util.*; import java.util.*;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import sun.reflect.misc.ReflectUtil;
/** /**
* A class that holds a list of EventListeners. A single instance * A class that holds a list of EventListeners. A single instance
...@@ -271,7 +272,9 @@ public class EventListenerList implements Serializable { ...@@ -271,7 +272,9 @@ public class EventListenerList implements Serializable {
while (null != (listenerTypeOrNull = s.readObject())) { while (null != (listenerTypeOrNull = s.readObject())) {
ClassLoader cl = Thread.currentThread().getContextClassLoader(); ClassLoader cl = Thread.currentThread().getContextClassLoader();
EventListener l = (EventListener)s.readObject(); EventListener l = (EventListener)s.readObject();
add((Class<EventListener>)Class.forName((String)listenerTypeOrNull, true, cl), l); String name = (String) listenerTypeOrNull;
ReflectUtil.checkPackageAccess(name);
add((Class<EventListener>)Class.forName(name, true, cl), l);
} }
} }
......
...@@ -28,7 +28,10 @@ package sun.reflect.generics.reflectiveObjects; ...@@ -28,7 +28,10 @@ package sun.reflect.generics.reflectiveObjects;
import java.lang.annotation.*; import java.lang.annotation.*;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericDeclaration; import java.lang.reflect.GenericDeclaration;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
...@@ -40,6 +43,7 @@ import sun.reflect.annotation.AnnotationType; ...@@ -40,6 +43,7 @@ import sun.reflect.annotation.AnnotationType;
import sun.reflect.generics.factory.GenericsFactory; import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.tree.FieldTypeSignature; import sun.reflect.generics.tree.FieldTypeSignature;
import sun.reflect.generics.visitor.Reifier; import sun.reflect.generics.visitor.Reifier;
import sun.reflect.misc.ReflectUtil;
/** /**
* Implementation of <tt>java.lang.reflect.TypeVariable</tt> interface * Implementation of <tt>java.lang.reflect.TypeVariable</tt> interface
...@@ -95,6 +99,13 @@ public class TypeVariableImpl<D extends GenericDeclaration> ...@@ -95,6 +99,13 @@ public class TypeVariableImpl<D extends GenericDeclaration>
TypeVariableImpl<T> make(T decl, String name, TypeVariableImpl<T> make(T decl, String name,
FieldTypeSignature[] bs, FieldTypeSignature[] bs,
GenericsFactory f) { GenericsFactory f) {
if (!((decl instanceof Class) ||
(decl instanceof Method) ||
(decl instanceof Constructor))) {
throw new AssertionError("Unexpected kind of GenericDeclaration" +
decl.getClass().toString());
}
return new TypeVariableImpl<T>(decl, name, bs, f); return new TypeVariableImpl<T>(decl, name, bs, f);
} }
...@@ -149,6 +160,13 @@ public class TypeVariableImpl<D extends GenericDeclaration> ...@@ -149,6 +160,13 @@ public class TypeVariableImpl<D extends GenericDeclaration>
* @since 1.5 * @since 1.5
*/ */
public D getGenericDeclaration(){ public D getGenericDeclaration(){
if (genericDeclaration instanceof Class)
ReflectUtil.checkPackageAccess((Class)genericDeclaration);
else if ((genericDeclaration instanceof Method) ||
(genericDeclaration instanceof Constructor))
ReflectUtil.conservativeCheckMemberAccess((Member)genericDeclaration);
else
throw new AssertionError("Unexpected kind of GenericDeclaration");
return genericDeclaration; return genericDeclaration;
} }
...@@ -164,7 +182,8 @@ public class TypeVariableImpl<D extends GenericDeclaration> ...@@ -164,7 +182,8 @@ public class TypeVariableImpl<D extends GenericDeclaration>
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (o instanceof TypeVariable) { if (o instanceof TypeVariable &&
o.getClass() == TypeVariableImpl.class) {
TypeVariable<?> that = (TypeVariable<?>) o; TypeVariable<?> that = (TypeVariable<?>) o;
GenericDeclaration thatDecl = that.getGenericDeclaration(); GenericDeclaration thatDecl = that.getGenericDeclaration();
......
...@@ -26,11 +26,13 @@ ...@@ -26,11 +26,13 @@
package sun.reflect.misc; package sun.reflect.misc;
import java.lang.reflect.Member;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Arrays; import java.util.Arrays;
import sun.reflect.Reflection; import sun.reflect.Reflection;
import sun.security.util.SecurityConstants;
public final class ReflectUtil { public final class ReflectUtil {
...@@ -117,6 +119,40 @@ public final class ReflectUtil { ...@@ -117,6 +119,40 @@ public final class ReflectUtil {
return false; return false;
} }
/**
* Does a conservative approximation of member access check. Use this if
* you don't have an actual 'userland' caller Class/ClassLoader available.
* This might be more restrictive than a precise member access check where
* you have a caller, but should never allow a member access that is
* forbidden.
*
* @param m the {@code Member} about to be accessed
*/
public static void conservativeCheckMemberAccess(Member m) throws SecurityException{
final SecurityManager sm = System.getSecurityManager();
if (sm == null)
return;
// Check for package access on the declaring class.
//
// In addition, unless the member and the declaring class are both
// public check for access declared member permissions.
//
// This is done regardless of ClassLoader relations between the {@code
// Member m} and any potential caller.
final Class<?> declaringClass = m.getDeclaringClass();
checkPackageAccess(declaringClass);
if (Modifier.isPublic(m.getModifiers()) &&
Modifier.isPublic(declaringClass.getModifiers()))
return;
// Check for declared member access.
sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION);
}
/** /**
* Checks package access on the given class. * Checks package access on the given class.
* *
......
/* /*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -45,11 +45,12 @@ public class TlsRsaPremasterSecretParameterSpec ...@@ -45,11 +45,12 @@ public class TlsRsaPremasterSecretParameterSpec
private final int majorVersion; private final int majorVersion;
private final int minorVersion; private final int minorVersion;
private final byte[] encodedSecret;
/** /**
* Constructs a new TlsRsaPremasterSecretParameterSpec. * Constructs a new TlsRsaPremasterSecretParameterSpec.
* * <P>
* <p>The version numbers will be placed inside the premaster secret to * The version numbers will be placed inside the premaster secret to
* detect version rollbacks attacks as described in the TLS specification. * detect version rollbacks attacks as described in the TLS specification.
* Note that they do not indicate the protocol version negotiated for * Note that they do not indicate the protocol version negotiated for
* the handshake. * the handshake.
...@@ -65,7 +66,42 @@ public class TlsRsaPremasterSecretParameterSpec ...@@ -65,7 +66,42 @@ public class TlsRsaPremasterSecretParameterSpec
this.majorVersion = this.majorVersion =
TlsMasterSecretParameterSpec.checkVersion(majorVersion); TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion = this.minorVersion =
TlsMasterSecretParameterSpec.checkVersion(minorVersion); } TlsMasterSecretParameterSpec.checkVersion(minorVersion);
this.encodedSecret = null;
}
/**
* Constructs a new TlsRsaPremasterSecretParameterSpec.
* <P>
* The version numbers will be placed inside the premaster secret to
* detect version rollbacks attacks as described in the TLS specification.
* Note that they do not indicate the protocol version negotiated for
* the handshake.
* <P>
* Usually, the encoded secret key is a random number that acts as
* dummy pre_master_secret to avoid vulnerabilities described by
* section 7.4.7.1, RFC 5246.
*
* @param majorVersion the major number of the protocol version
* @param minorVersion the minor number of the protocol version
* @param encodedSecret the encoded secret key
*
* @throws IllegalArgumentException if minorVersion or majorVersion are
* negative or larger than 255, or encodedSecret is not exactly 48 bytes.
*/
public TlsRsaPremasterSecretParameterSpec(int majorVersion,
int minorVersion, byte[] encodedSecret) {
this.majorVersion =
TlsMasterSecretParameterSpec.checkVersion(majorVersion);
this.minorVersion =
TlsMasterSecretParameterSpec.checkVersion(minorVersion);
if (encodedSecret == null || encodedSecret.length != 48) {
throw new IllegalArgumentException(
"Encoded secret is not exactly 48 bytes");
}
this.encodedSecret = encodedSecret.clone();
}
/** /**
* Returns the major version. * Returns the major version.
...@@ -84,4 +120,13 @@ public class TlsRsaPremasterSecretParameterSpec ...@@ -84,4 +120,13 @@ public class TlsRsaPremasterSecretParameterSpec
public int getMinorVersion() { public int getMinorVersion() {
return minorVersion; return minorVersion;
} }
/**
* Returns the encoded secret.
*
* @return the encoded secret, may be null if no encoded secret.
*/
public byte[] getEncodedSecret() {
return encodedSecret == null ? null : encodedSecret.clone();
}
} }
/* /*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -451,30 +451,7 @@ final class P11RSACipher extends CipherSpi { ...@@ -451,30 +451,7 @@ final class P11RSACipher extends CipherSpi {
// see JCE spec // see JCE spec
protected Key engineUnwrap(byte[] wrappedKey, String algorithm, protected Key engineUnwrap(byte[] wrappedKey, String algorithm,
int type) throws InvalidKeyException, NoSuchAlgorithmException { int type) throws InvalidKeyException, NoSuchAlgorithmException {
if (algorithm.equals("TlsRsaPremasterSecret")) {
// the instance variable "session" has been initialized for
// decrypt mode, so use a local variable instead.
Session s = null;
try {
s = token.getObjSession();
long keyType = CKK_GENERIC_SECRET;
CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[] {
new CK_ATTRIBUTE(CKA_CLASS, CKO_SECRET_KEY),
new CK_ATTRIBUTE(CKA_KEY_TYPE, keyType),
};
attributes = token.getAttributes
(O_IMPORT, CKO_SECRET_KEY, keyType, attributes);
long keyID = token.p11.C_UnwrapKey(s.id(),
new CK_MECHANISM(mechanism), p11Key.keyID, wrappedKey,
attributes);
return P11Key.secretKey(s, keyID, algorithm, 48 << 3,
attributes);
} catch (PKCS11Exception e) {
throw new InvalidKeyException("unwrap() failed", e);
} finally {
token.releaseSession(s);
}
}
// XXX implement unwrap using C_Unwrap() for all keys // XXX implement unwrap using C_Unwrap() for all keys
implInit(Cipher.DECRYPT_MODE, p11Key); implInit(Cipher.DECRYPT_MODE, p11Key);
if (wrappedKey.length > maxInputSize) { if (wrappedKey.length > maxInputSize) {
......
/* /*
* Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -88,23 +88,33 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { ...@@ -88,23 +88,33 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi {
throw new IllegalStateException throw new IllegalStateException
("TlsRsaPremasterSecretGenerator must be initialized"); ("TlsRsaPremasterSecretGenerator must be initialized");
} }
CK_VERSION version =
new CK_VERSION(spec.getMajorVersion(), spec.getMinorVersion()); byte[] b = spec.getEncodedSecret();
Session session = null; if (b == null) {
try { CK_VERSION version = new CK_VERSION(
session = token.getObjSession(); spec.getMajorVersion(), spec.getMinorVersion());
CK_ATTRIBUTE[] attributes = token.getAttributes Session session = null;
(O_GENERATE, CKO_SECRET_KEY, CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]); try {
long keyID = token.p11.C_GenerateKey session = token.getObjSession();
(session.id(), new CK_MECHANISM(mechanism, version), attributes); CK_ATTRIBUTE[] attributes = token.getAttributes(
SecretKey key = P11Key.secretKey O_GENERATE, CKO_SECRET_KEY,
(session, keyID, "TlsRsaPremasterSecret", 48 << 3, attributes); CKK_GENERIC_SECRET, new CK_ATTRIBUTE[0]);
return key; long keyID = token.p11.C_GenerateKey(session.id(),
} catch (PKCS11Exception e) { new CK_MECHANISM(mechanism, version), attributes);
throw new ProviderException("Could not generate premaster secret", e); SecretKey key = P11Key.secretKey(session,
} finally { keyID, "TlsRsaPremasterSecret", 48 << 3, attributes);
token.releaseSession(session); return key;
} catch (PKCS11Exception e) {
throw new ProviderException(
"Could not generate premaster secret", e);
} finally {
token.releaseSession(session);
}
} }
// Won't worry, the TlsRsaPremasterSecret will be soon converted to
// TlsMasterSecret.
return new SecretKeySpec(b, "TlsRsaPremasterSecret");
} }
} }
/* /*
* Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -43,10 +43,8 @@ import sun.misc.Unsafe; ...@@ -43,10 +43,8 @@ import sun.misc.Unsafe;
* These are the only platforms we currently support, but other optimized * These are the only platforms we currently support, but other optimized
* variants could be added as needed. * variants could be added as needed.
* *
* NOTE that because this code performs unchecked direct memory access, it * NOTE that ArrayIndexOutOfBoundsException will be thrown if the bounds checks
* MUST be restricted to trusted code. It is imperative that the caller protects * failed.
* against out of bounds memory access by performing the necessary bounds
* checks before calling methods in this class.
* *
* This class may also be helpful in improving the performance of the * This class may also be helpful in improving the performance of the
* crypto code in the SunJCE provider. However, for now it is only accessible by * crypto code in the SunJCE provider. However, for now it is only accessible by
...@@ -103,6 +101,10 @@ final class ByteArrayAccess { ...@@ -103,6 +101,10 @@ final class ByteArrayAccess {
* byte[] to int[] conversion, little endian byte order. * byte[] to int[] conversion, little endian byte order.
*/ */
static void b2iLittle(byte[] in, int inOfs, int[] out, int outOfs, int len) { static void b2iLittle(byte[] in, int inOfs, int[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
(outOfs < 0) || ((out.length - outOfs) < len/4)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
inOfs += byteArrayOfs; inOfs += byteArrayOfs;
len += inOfs; len += inOfs;
...@@ -131,6 +133,10 @@ final class ByteArrayAccess { ...@@ -131,6 +133,10 @@ final class ByteArrayAccess {
// Special optimization of b2iLittle(in, inOfs, out, 0, 64) // Special optimization of b2iLittle(in, inOfs, out, 0, 64)
static void b2iLittle64(byte[] in, int inOfs, int[] out) { static void b2iLittle64(byte[] in, int inOfs, int[] out) {
if ((inOfs < 0) || ((in.length - inOfs) < 64) ||
(out.length < 16)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
inOfs += byteArrayOfs; inOfs += byteArrayOfs;
out[ 0] = unsafe.getInt(in, (long)(inOfs )); out[ 0] = unsafe.getInt(in, (long)(inOfs ));
...@@ -176,6 +182,10 @@ final class ByteArrayAccess { ...@@ -176,6 +182,10 @@ final class ByteArrayAccess {
* int[] to byte[] conversion, little endian byte order. * int[] to byte[] conversion, little endian byte order.
*/ */
static void i2bLittle(int[] in, int inOfs, byte[] out, int outOfs, int len) { static void i2bLittle(int[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/4) ||
(outOfs < 0) || ((out.length - outOfs) < len)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
outOfs += byteArrayOfs; outOfs += byteArrayOfs;
len += outOfs; len += outOfs;
...@@ -204,6 +214,9 @@ final class ByteArrayAccess { ...@@ -204,6 +214,9 @@ final class ByteArrayAccess {
// Store one 32-bit value into out[outOfs..outOfs+3] in little endian order. // Store one 32-bit value into out[outOfs..outOfs+3] in little endian order.
static void i2bLittle4(int val, byte[] out, int outOfs) { static void i2bLittle4(int val, byte[] out, int outOfs) {
if ((outOfs < 0) || ((out.length - outOfs) < 4)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), val); unsafe.putInt(out, (long)(byteArrayOfs + outOfs), val);
} else if (bigEndian && ((outOfs & 3) == 0)) { } else if (bigEndian && ((outOfs & 3) == 0)) {
...@@ -220,6 +233,10 @@ final class ByteArrayAccess { ...@@ -220,6 +233,10 @@ final class ByteArrayAccess {
* byte[] to int[] conversion, big endian byte order. * byte[] to int[] conversion, big endian byte order.
*/ */
static void b2iBig(byte[] in, int inOfs, int[] out, int outOfs, int len) { static void b2iBig(byte[] in, int inOfs, int[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
(outOfs < 0) || ((out.length - outOfs) < len/4)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
inOfs += byteArrayOfs; inOfs += byteArrayOfs;
len += inOfs; len += inOfs;
...@@ -248,6 +265,10 @@ final class ByteArrayAccess { ...@@ -248,6 +265,10 @@ final class ByteArrayAccess {
// Special optimization of b2iBig(in, inOfs, out, 0, 64) // Special optimization of b2iBig(in, inOfs, out, 0, 64)
static void b2iBig64(byte[] in, int inOfs, int[] out) { static void b2iBig64(byte[] in, int inOfs, int[] out) {
if ((inOfs < 0) || ((in.length - inOfs) < 64) ||
(out.length < 16)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
inOfs += byteArrayOfs; inOfs += byteArrayOfs;
out[ 0] = reverseBytes(unsafe.getInt(in, (long)(inOfs ))); out[ 0] = reverseBytes(unsafe.getInt(in, (long)(inOfs )));
...@@ -293,6 +314,10 @@ final class ByteArrayAccess { ...@@ -293,6 +314,10 @@ final class ByteArrayAccess {
* int[] to byte[] conversion, big endian byte order. * int[] to byte[] conversion, big endian byte order.
*/ */
static void i2bBig(int[] in, int inOfs, byte[] out, int outOfs, int len) { static void i2bBig(int[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/4) ||
(outOfs < 0) || ((out.length - outOfs) < len)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
outOfs += byteArrayOfs; outOfs += byteArrayOfs;
len += outOfs; len += outOfs;
...@@ -321,6 +346,9 @@ final class ByteArrayAccess { ...@@ -321,6 +346,9 @@ final class ByteArrayAccess {
// Store one 32-bit value into out[outOfs..outOfs+3] in big endian order. // Store one 32-bit value into out[outOfs..outOfs+3] in big endian order.
static void i2bBig4(int val, byte[] out, int outOfs) { static void i2bBig4(int val, byte[] out, int outOfs) {
if ((outOfs < 0) || ((out.length - outOfs) < 4)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
unsafe.putInt(out, (long)(byteArrayOfs + outOfs), reverseBytes(val)); unsafe.putInt(out, (long)(byteArrayOfs + outOfs), reverseBytes(val));
} else if (bigEndian && ((outOfs & 3) == 0)) { } else if (bigEndian && ((outOfs & 3) == 0)) {
...@@ -337,6 +365,10 @@ final class ByteArrayAccess { ...@@ -337,6 +365,10 @@ final class ByteArrayAccess {
* byte[] to long[] conversion, big endian byte order. * byte[] to long[] conversion, big endian byte order.
*/ */
static void b2lBig(byte[] in, int inOfs, long[] out, int outOfs, int len) { static void b2lBig(byte[] in, int inOfs, long[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len) ||
(outOfs < 0) || ((out.length - outOfs) < len/8)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
inOfs += byteArrayOfs; inOfs += byteArrayOfs;
len += inOfs; len += inOfs;
...@@ -378,6 +410,10 @@ final class ByteArrayAccess { ...@@ -378,6 +410,10 @@ final class ByteArrayAccess {
// Special optimization of b2lBig(in, inOfs, out, 0, 128) // Special optimization of b2lBig(in, inOfs, out, 0, 128)
static void b2lBig128(byte[] in, int inOfs, long[] out) { static void b2lBig128(byte[] in, int inOfs, long[] out) {
if ((inOfs < 0) || ((in.length - inOfs) < 128) ||
(out.length < 16)) {
throw new ArrayIndexOutOfBoundsException();
}
if (littleEndianUnaligned) { if (littleEndianUnaligned) {
inOfs += byteArrayOfs; inOfs += byteArrayOfs;
out[ 0] = reverseBytes(unsafe.getLong(in, (long)(inOfs ))); out[ 0] = reverseBytes(unsafe.getLong(in, (long)(inOfs )));
...@@ -406,6 +442,10 @@ final class ByteArrayAccess { ...@@ -406,6 +442,10 @@ final class ByteArrayAccess {
* long[] to byte[] conversion, big endian byte order. * long[] to byte[] conversion, big endian byte order.
*/ */
static void l2bBig(long[] in, int inOfs, byte[] out, int outOfs, int len) { static void l2bBig(long[] in, int inOfs, byte[] out, int outOfs, int len) {
if ((inOfs < 0) || ((in.length - inOfs) < len/8) ||
(outOfs < 0) || ((out.length - outOfs) < len)) {
throw new ArrayIndexOutOfBoundsException();
}
len += outOfs; len += outOfs;
while (outOfs < len) { while (outOfs < len) {
long i = in[inOfs++]; long i = in[inOfs++];
...@@ -419,5 +459,4 @@ final class ByteArrayAccess { ...@@ -419,5 +459,4 @@ final class ByteArrayAccess {
out[outOfs++] = (byte)(i ); out[outOfs++] = (byte)(i );
} }
} }
} }
/* /*
* Copyright (c) 2003, 2013 Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -318,33 +318,53 @@ public final class RSAPadding { ...@@ -318,33 +318,53 @@ public final class RSAPadding {
/** /**
* PKCS#1 v1.5 unpadding (blocktype 1 and 2). * PKCS#1 v1.5 unpadding (blocktype 1 and 2).
*
* Note that we want to make it a constant-time operation
*/ */
private byte[] unpadV15(byte[] padded) throws BadPaddingException { private byte[] unpadV15(byte[] padded) throws BadPaddingException {
int k = 0; int k = 0;
BadPaddingException bpe = null;
if (padded[k++] != 0) { if (padded[k++] != 0) {
throw new BadPaddingException("Data must start with zero"); bpe = new BadPaddingException("Data must start with zero");
} }
if (padded[k++] != type) { if (padded[k++] != type && bpe == null) {
throw new BadPaddingException("Blocktype mismatch: " + padded[1]); bpe = new BadPaddingException("Blocktype mismatch: " + padded[1]);
} }
while (true) { int p = 0;
while (k < padded.length) {
int b = padded[k++] & 0xff; int b = padded[k++] & 0xff;
if (b == 0) { if (b == 0 && p == 0) {
break; p = k;
} }
if (k == padded.length) { if (k == padded.length && p == 0 && bpe == null) {
throw new BadPaddingException("Padding string not terminated"); bpe = new BadPaddingException("Padding string not terminated");
} }
if ((type == PAD_BLOCKTYPE_1) && (b != 0xff)) { if ((type == PAD_BLOCKTYPE_1) && (b != 0xff) &&
throw new BadPaddingException("Padding byte not 0xff: " + b); p == 0 && bpe == null) {
bpe = new BadPaddingException("Padding byte not 0xff: " + b);
} }
} }
int n = padded.length - k; int n = padded.length - p;
if (n > maxDataSize) { if (n > maxDataSize && bpe == null) {
throw new BadPaddingException("Padding string too short"); bpe = new BadPaddingException("Padding string too short");
} }
// copy useless padding array for a constant-time method
//
// Is it necessary?
byte[] padding = new byte[p];
System.arraycopy(padded, 0, padding, 0, p);
byte[] data = new byte[n]; byte[] data = new byte[n];
System.arraycopy(padded, padded.length - n, data, 0, n); System.arraycopy(padded, p, data, 0, n);
if (bpe == null) {
bpe = new BadPaddingException("Unused exception");
} else {
throw bpe;
}
return data; return data;
} }
......
...@@ -1104,94 +1104,23 @@ abstract class Handshaker { ...@@ -1104,94 +1104,23 @@ abstract class Handshaker {
clnt_random.random_bytes, svr_random.random_bytes, clnt_random.random_bytes, svr_random.random_bytes,
prfHashAlg, prfHashLength, prfBlockSize); prfHashAlg, prfHashLength, prfBlockSize);
SecretKey masterSecret;
try { try {
KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg); KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
kg.init(spec); kg.init(spec);
masterSecret = kg.generateKey(); return kg.generateKey();
} catch (GeneralSecurityException e) { } catch (InvalidAlgorithmParameterException |
NoSuchAlgorithmException iae) {
// unlikely to happen, otherwise, must be a provider exception
//
// For RSA premaster secrets, do not signal a protocol error // For RSA premaster secrets, do not signal a protocol error
// due to the Bleichenbacher attack. See comments further down. // due to the Bleichenbacher attack. See comments further down.
if (!preMasterSecret.getAlgorithm().equals(
"TlsRsaPremasterSecret")) {
throw new ProviderException(e);
}
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
System.out.println("RSA master secret generation error:"); System.out.println("RSA master secret generation error:");
e.printStackTrace(System.out); iae.printStackTrace(System.out);
}
if (requestedVersion != null) {
preMasterSecret =
RSAClientKeyExchange.generateDummySecret(requestedVersion);
} else {
preMasterSecret =
RSAClientKeyExchange.generateDummySecret(protocolVersion);
} }
throw new ProviderException(iae);
// recursive call with new premaster secret
return calculateMasterSecret(preMasterSecret, null);
} }
// if no version check requested (client side handshake), or version
// information is not available (not an RSA premaster secret),
// return master secret immediately.
if ((requestedVersion == null) ||
!(masterSecret instanceof TlsMasterSecret)) {
return masterSecret;
}
// we have checked the ClientKeyExchange message when reading TLS
// record, the following check is necessary to ensure that
// JCE provider does not ignore the checking, or the previous
// checking process bypassed the premaster secret version checking.
TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
int major = tlsKey.getMajorVersion();
int minor = tlsKey.getMinorVersion();
if ((major < 0) || (minor < 0)) {
return masterSecret;
}
// check if the premaster secret version is ok
// the specification says that it must be the maximum version supported
// by the client from its ClientHello message. However, many
// implementations send the negotiated version, so accept both
// for SSL v3.0 and TLS v1.0.
// NOTE that we may be comparing two unsupported version numbers, which
// is why we cannot use object reference equality in this special case.
ProtocolVersion premasterVersion =
ProtocolVersion.valueOf(major, minor);
boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
/*
* we never checked the client_version in server side
* for TLS v1.0 and SSL v3.0. For compatibility, we
* maintain this behavior.
*/
if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
versionMismatch = (premasterVersion.v != protocolVersion.v);
}
if (versionMismatch == false) {
// check passed, return key
return masterSecret;
}
// Due to the Bleichenbacher attack, do not signal a protocol error.
// Generate a random premaster secret and continue with the handshake,
// which will fail when verifying the finished messages.
// For more information, see comments in PreMasterSecret.
if (debug != null && Debug.isOn("handshake")) {
System.out.println("RSA PreMasterSecret version error: expected"
+ protocolVersion + " or " + requestedVersion + ", decrypted: "
+ premasterVersion);
}
preMasterSecret =
RSAClientKeyExchange.generateDummySecret(requestedVersion);
// recursive call with new premaster secret
return calculateMasterSecret(preMasterSecret, null);
} }
/* /*
......
/* /*
* Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -133,26 +133,37 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -133,26 +133,37 @@ final class RSAClientKeyExchange extends HandshakeMessage {
} else { } else {
encrypted = new byte [messageSize]; encrypted = new byte [messageSize];
if (input.read(encrypted) != messageSize) { if (input.read(encrypted) != messageSize) {
throw new SSLProtocolException throw new SSLProtocolException(
("SSL: read PreMasterSecret: short read"); "SSL: read PreMasterSecret: short read");
} }
} }
Exception failover = null;
byte[] encoded = null;
try { try {
Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);
cipher.init(Cipher.UNWRAP_MODE, privateKey); // Cannot generate key here, please don't use Cipher.UNWRAP_MODE!
preMaster = (SecretKey)cipher.unwrap(encrypted, cipher.init(Cipher.DECRYPT_MODE, privateKey);
"TlsRsaPremasterSecret", Cipher.SECRET_KEY); encoded = cipher.doFinal(encrypted);
} catch (BadPaddingException bpe) {
// polish the premaster secret failover = bpe;
preMaster = polishPreMasterSecretKey(currentVersion, maxVersion, encoded = null;
generator, preMaster, null); } catch (IllegalBlockSizeException ibse) {
// the message it too big to process with RSA
throw new SSLProtocolException(
"Unable to process PreMasterSecret, may be too big");
} catch (Exception e) { } catch (Exception e) {
// polish the premaster secret // unlikely to happen, otherwise, must be a provider exception
preMaster = if (debug != null && Debug.isOn("handshake")) {
polishPreMasterSecretKey(currentVersion, maxVersion, System.out.println("RSA premaster secret decryption error:");
generator, null, e); e.printStackTrace(System.out);
}
throw new RuntimeException("Could not generate dummy secret", e);
} }
// polish the premaster secret
preMaster = polishPreMasterSecretKey(
currentVersion, maxVersion, generator, encoded, failover);
} }
/** /**
...@@ -163,85 +174,74 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -163,85 +174,74 @@ final class RSAClientKeyExchange extends HandshakeMessage {
* *
* RFC 5246 describes the approach as : * RFC 5246 describes the approach as :
* *
* 1. Generate a string R of 46 random bytes * 1. Generate a string R of 48 random bytes
* *
* 2. Decrypt the message to recover the plaintext M * 2. Decrypt the message to recover the plaintext M
* *
* 3. If the PKCS#1 padding is not correct, or the length of message * 3. If the PKCS#1 padding is not correct, or the length of message
* M is not exactly 48 bytes: * M is not exactly 48 bytes:
* pre_master_secret = ClientHello.client_version || R * pre_master_secret = R
* else If ClientHello.client_version <= TLS 1.0, and version * else If ClientHello.client_version <= TLS 1.0, and version
* number check is explicitly disabled: * number check is explicitly disabled:
* pre_master_secret = M * premaster secret = M
* else If M[0..1] != ClientHello.client_version:
* premaster secret = R
* else: * else:
* pre_master_secret = ClientHello.client_version || M[2..47] * premaster secret = M
*
* Note that #2 has completed before the call of this method.
*/ */
private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion, private SecretKey polishPreMasterSecretKey(ProtocolVersion currentVersion,
ProtocolVersion clientHelloVersion, SecureRandom generator, ProtocolVersion clientHelloVersion, SecureRandom generator,
SecretKey secretKey, Exception failoverException) { byte[] encoded, Exception failoverException) {
this.protocolVersion = clientHelloVersion; this.protocolVersion = clientHelloVersion;
if (generator == null) {
generator = new SecureRandom();
}
byte[] random = new byte[48];
generator.nextBytes(random);
if (failoverException == null && secretKey != null) { if (failoverException == null && encoded != null) {
// check the length // check the length
byte[] encoded = secretKey.getEncoded(); if (encoded.length != 48) {
if (encoded == null) { // unable to get the encoded key
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
System.out.println( System.out.println(
"unable to get the plaintext of the premaster secret"); "incorrect length of premaster secret: " +
encoded.length);
} }
int keySize = KeyUtil.getKeySize(secretKey); return generatePreMasterSecret(
if (keySize > 0 && keySize != 384) { // 384 = 48 * 8 clientHelloVersion, random, generator);
if (debug != null && Debug.isOn("handshake")) { }
System.out.println(
"incorrect length of premaster secret: " +
(keySize/8));
}
return generateDummySecret(clientHelloVersion); if (clientHelloVersion.major != encoded[0] ||
} clientHelloVersion.minor != encoded[1]) {
// The key size is exactly 48 bytes or not accessible. if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
// currentVersion.major == encoded[0] &&
// Conservatively, pass the checking to master secret currentVersion.minor == encoded[1]) {
// calculation.
return secretKey;
} else if (encoded.length == 48) {
// check the version
if (clientHelloVersion.major == encoded[0] &&
clientHelloVersion.minor == encoded[1]) {
return secretKey;
} else if (clientHelloVersion.v <= ProtocolVersion.TLS10.v &&
currentVersion.major == encoded[0] &&
currentVersion.minor == encoded[1]) {
/* /*
* For compatibility, we maintain the behavior that the * For compatibility, we maintain the behavior that the
* version in pre_master_secret can be the negotiated * version in pre_master_secret can be the negotiated
* version for TLS v1.0 and SSL v3.0. * version for TLS v1.0 and SSL v3.0.
*/ */
this.protocolVersion = currentVersion; this.protocolVersion = currentVersion;
return secretKey; } else {
} if (debug != null && Debug.isOn("handshake")) {
System.out.println("Mismatching Protocol Versions, " +
if (debug != null && Debug.isOn("handshake")) { "ClientHello.client_version is " +
System.out.println("Mismatching Protocol Versions, " + clientHelloVersion +
"ClientHello.client_version is " + clientHelloVersion + ", while PreMasterSecret.client_version is " +
", while PreMasterSecret.client_version is " + ProtocolVersion.valueOf(encoded[0], encoded[1]));
ProtocolVersion.valueOf(encoded[0], encoded[1])); }
}
return generateDummySecret(clientHelloVersion); encoded = random;
} else {
if (debug != null && Debug.isOn("handshake")) {
System.out.println(
"incorrect length of premaster secret: " +
encoded.length);
} }
return generateDummySecret(clientHelloVersion);
} }
return generatePreMasterSecret(
clientHelloVersion, encoded, generator);
} }
if (debug != null && Debug.isOn("handshake") && if (debug != null && Debug.isOn("handshake") &&
...@@ -250,11 +250,14 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -250,11 +250,14 @@ final class RSAClientKeyExchange extends HandshakeMessage {
failoverException.printStackTrace(System.out); failoverException.printStackTrace(System.out);
} }
return generateDummySecret(clientHelloVersion); return generatePreMasterSecret(clientHelloVersion, random, generator);
} }
// generate a premaster secret with the specified version number // generate a premaster secret with the specified version number
static SecretKey generateDummySecret(ProtocolVersion version) { private static SecretKey generatePreMasterSecret(
ProtocolVersion version, byte[] encodedSecret,
SecureRandom generator) {
if (debug != null && Debug.isOn("handshake")) { if (debug != null && Debug.isOn("handshake")) {
System.out.println("Generating a random fake premaster secret"); System.out.println("Generating a random fake premaster secret");
} }
...@@ -263,11 +266,17 @@ final class RSAClientKeyExchange extends HandshakeMessage { ...@@ -263,11 +266,17 @@ final class RSAClientKeyExchange extends HandshakeMessage {
String s = ((version.v >= ProtocolVersion.TLS12.v) ? String s = ((version.v >= ProtocolVersion.TLS12.v) ?
"SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret"); "SunTls12RsaPremasterSecret" : "SunTlsRsaPremasterSecret");
KeyGenerator kg = JsseJce.getKeyGenerator(s); KeyGenerator kg = JsseJce.getKeyGenerator(s);
kg.init(new TlsRsaPremasterSecretParameterSpec kg.init(new TlsRsaPremasterSecretParameterSpec(
(version.major, version.minor)); version.major, version.minor, encodedSecret), generator);
return kg.generateKey(); return kg.generateKey();
} catch (GeneralSecurityException e) { } catch (InvalidAlgorithmParameterException |
throw new RuntimeException("Could not generate dummy secret", e); NoSuchAlgorithmException iae) {
// unlikely to happen, otherwise, must be a provider exception
if (debug != null && Debug.isOn("handshake")) {
System.out.println("RSA premaster secret generation error:");
iae.printStackTrace(System.out);
}
throw new RuntimeException("Could not generate dummy secret", iae);
} }
} }
......
...@@ -158,8 +158,13 @@ public class Main { ...@@ -158,8 +158,13 @@ public class Main {
private String altSignerClasspath = null; private String altSignerClasspath = null;
private ZipFile zipFile = null; private ZipFile zipFile = null;
private boolean hasExpiredCert = false; // Informational warnings
private boolean hasExpiringCert = false; private boolean hasExpiringCert = false;
private boolean noTimestamp = false;
private Date expireDate = new Date(0L); // used in noTimestamp warning
// Severe warnings
private boolean hasExpiredCert = false;
private boolean notYetValidCert = false; private boolean notYetValidCert = false;
private boolean chainNotValidated = false; private boolean chainNotValidated = false;
private boolean notSignedByAlias = false; private boolean notSignedByAlias = false;
...@@ -258,9 +263,6 @@ public class Main { ...@@ -258,9 +263,6 @@ public class Main {
if (strict) { if (strict) {
int exitCode = 0; int exitCode = 0;
if (hasExpiringCert) {
exitCode |= 2;
}
if (chainNotValidated || hasExpiredCert || notYetValidCert) { if (chainNotValidated || hasExpiredCert || notYetValidCert) {
exitCode |= 4; exitCode |= 4;
} }
...@@ -754,14 +756,25 @@ public class Main { ...@@ -754,14 +756,25 @@ public class Main {
System.out.println(rb.getString( System.out.println(rb.getString(
"jar.is.unsigned.signatures.missing.or.not.parsable.")); "jar.is.unsigned.signatures.missing.or.not.parsable."));
} else { } else {
System.out.println(rb.getString("jar.verified.")); boolean warningAppeared = false;
if (hasUnsignedEntry || hasExpiredCert || hasExpiringCert || boolean errorAppeared = false;
badKeyUsage || badExtendedKeyUsage || badNetscapeCertType || if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
notYetValidCert || chainNotValidated || notYetValidCert || chainNotValidated || hasExpiredCert ||
aliasNotInStore || notSignedByAlias) { hasUnsignedEntry ||
aliasNotInStore || notSignedByAlias) {
if (strict) {
System.out.println(rb.getString("jar.verified.with.signer.errors."));
System.out.println();
System.out.println(rb.getString("Error."));
errorAppeared = true;
} else {
System.out.println(rb.getString("jar.verified."));
System.out.println();
System.out.println(rb.getString("Warning."));
warningAppeared = true;
}
System.out.println();
System.out.println(rb.getString("Warning."));
if (badKeyUsage) { if (badKeyUsage) {
System.out.println( System.out.println(
rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); rb.getString("This.jar.contains.entries.whose.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
...@@ -785,10 +798,6 @@ public class Main { ...@@ -785,10 +798,6 @@ public class Main {
System.out.println(rb.getString( System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.has.expired.")); "This.jar.contains.entries.whose.signer.certificate.has.expired."));
} }
if (hasExpiringCert) {
System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
}
if (notYetValidCert) { if (notYetValidCert) {
System.out.println(rb.getString( System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.")); "This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid."));
...@@ -807,10 +816,29 @@ public class Main { ...@@ -807,10 +816,29 @@ public class Main {
if (aliasNotInStore) { if (aliasNotInStore) {
System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.")); System.out.println(rb.getString("This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore."));
} }
} else {
System.out.println(rb.getString("jar.verified."));
}
if (hasExpiringCert || noTimestamp) {
if (!warningAppeared) {
System.out.println();
System.out.println(rb.getString("Warning."));
warningAppeared = true;
}
if (hasExpiringCert) {
System.out.println(rb.getString(
"This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months."));
}
if (noTimestamp) {
System.out.println(
String.format(rb.getString("no.timestamp.verifying"), expireDate));
}
}
if (warningAppeared || errorAppeared) {
if (! (verbose != null && showcerts)) { if (! (verbose != null && showcerts)) {
System.out.println(); System.out.println();
System.out.println(rb.getString( System.out.println(rb.getString(
"Re.run.with.the.verbose.and.certs.options.for.more.details.")); "Re.run.with.the.verbose.and.certs.options.for.more.details."));
} }
} }
} }
...@@ -870,6 +898,9 @@ public class Main { ...@@ -870,6 +898,9 @@ public class Main {
try { try {
boolean printValidity = true; boolean printValidity = true;
if (timestamp == null) { if (timestamp == null) {
if (expireDate.getTime() == 0 || expireDate.after(notAfter)) {
expireDate = notAfter;
}
x509Cert.checkValidity(); x509Cert.checkValidity();
// test if cert will expire within six months // test if cert will expire within six months
if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) { if (notAfter.getTime() < System.currentTimeMillis() + SIX_MONTHS) {
...@@ -1233,6 +1264,10 @@ public class Main { ...@@ -1233,6 +1264,10 @@ public class Main {
tsaCert = getTsaCert(tsaAlias); tsaCert = getTsaCert(tsaAlias);
} }
if (tsaUrl == null && tsaCert == null) {
noTimestamp = true;
}
SignatureFile.Block block = null; SignatureFile.Block block = null;
try { try {
...@@ -1380,12 +1415,20 @@ public class Main { ...@@ -1380,12 +1415,20 @@ public class Main {
} }
} }
if (hasExpiredCert || hasExpiringCert || notYetValidCert boolean warningAppeared = false;
|| badKeyUsage || badExtendedKeyUsage if (badKeyUsage || badExtendedKeyUsage || badNetscapeCertType ||
|| badNetscapeCertType || chainNotValidated) { notYetValidCert || chainNotValidated || hasExpiredCert) {
System.out.println(); if (strict) {
System.out.println(rb.getString("jar.signed.with.signer.errors."));
System.out.println();
System.out.println(rb.getString("Error."));
} else {
System.out.println(rb.getString("jar.signed."));
System.out.println();
System.out.println(rb.getString("Warning."));
warningAppeared = true;
}
System.out.println(rb.getString("Warning."));
if (badKeyUsage) { if (badKeyUsage) {
System.out.println( System.out.println(
rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing.")); rb.getString("The.signer.certificate.s.KeyUsage.extension.doesn.t.allow.code.signing."));
...@@ -1404,9 +1447,6 @@ public class Main { ...@@ -1404,9 +1447,6 @@ public class Main {
if (hasExpiredCert) { if (hasExpiredCert) {
System.out.println( System.out.println(
rb.getString("The.signer.certificate.has.expired.")); rb.getString("The.signer.certificate.has.expired."));
} else if (hasExpiringCert) {
System.out.println(
rb.getString("The.signer.certificate.will.expire.within.six.months."));
} else if (notYetValidCert) { } else if (notYetValidCert) {
System.out.println( System.out.println(
rb.getString("The.signer.certificate.is.not.yet.valid.")); rb.getString("The.signer.certificate.is.not.yet.valid."));
...@@ -1416,6 +1456,24 @@ public class Main { ...@@ -1416,6 +1456,24 @@ public class Main {
System.out.println( System.out.println(
rb.getString("The.signer.s.certificate.chain.is.not.validated.")); rb.getString("The.signer.s.certificate.chain.is.not.validated."));
} }
} else {
System.out.println(rb.getString("jar.signed."));
}
if (hasExpiringCert || noTimestamp) {
if (!warningAppeared) {
System.out.println();
System.out.println(rb.getString("Warning."));
}
if (hasExpiringCert) {
System.out.println(
rb.getString("The.signer.certificate.will.expire.within.six.months."));
}
if (noTimestamp) {
System.out.println(
String.format(rb.getString("no.timestamp.signing"), expireDate));
}
} }
// no IOException thrown in the above try clause, so disable // no IOException thrown in the above try clause, so disable
...@@ -1502,6 +1560,7 @@ public class Main { ...@@ -1502,6 +1560,7 @@ public class Main {
timestamp = ts.getTimestamp(); timestamp = ts.getTimestamp();
} else { } else {
timestamp = null; timestamp = null;
noTimestamp = true;
} }
// display the certificate(s). The first one is end-entity cert and // display the certificate(s). The first one is end-entity cert and
// its KeyUsage should be checked. // its KeyUsage should be checked.
......
...@@ -112,9 +112,9 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -112,9 +112,9 @@ public class Resources extends java.util.ListResourceBundle {
{"Please.specify.alias.name", "Please specify alias name"}, {"Please.specify.alias.name", "Please specify alias name"},
{"Only.one.alias.can.be.specified", "Only one alias can be specified"}, {"Only.one.alias.can.be.specified", "Only one alias can be specified"},
{"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.", {"This.jar.contains.signed.entries.which.is.not.signed.by.the.specified.alias.es.",
"This jar contains signed entries which is not signed by the specified alias(es)."}, "This jar contains signed entries which are not signed by the specified alias(es)."},
{"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.", {"This.jar.contains.signed.entries.that.s.not.signed.by.alias.in.this.keystore.",
"This jar contains signed entries that's not signed by alias in this keystore."}, "This jar contains signed entries that are not signed by alias in this keystore."},
{"s", "s"}, {"s", "s"},
{"m", "m"}, {"m", "m"},
{"k", "k"}, {"k", "k"},
...@@ -135,7 +135,10 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -135,7 +135,10 @@ public class Resources extends java.util.ListResourceBundle {
{".Unsigned.entries.", "(Unsigned entries)"}, {".Unsigned.entries.", "(Unsigned entries)"},
{"jar.is.unsigned.signatures.missing.or.not.parsable.", {"jar.is.unsigned.signatures.missing.or.not.parsable.",
"jar is unsigned. (signatures missing or not parsable)"}, "jar is unsigned. (signatures missing or not parsable)"},
{"jar.signed.", "jar signed."},
{"jar.signed.with.signer.errors.", "jar signed, with signer errors."},
{"jar.verified.", "jar verified."}, {"jar.verified.", "jar verified."},
{"jar.verified.with.signer.errors.", "jar verified, with signer errors."},
{"jarsigner.", "jarsigner: "}, {"jarsigner.", "jarsigner: "},
{"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.", {"signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.",
"signature filename must consist of the following characters: A-Z, 0-9, _ or -"}, "signature filename must consist of the following characters: A-Z, 0-9, _ or -"},
...@@ -193,6 +196,7 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -193,6 +196,7 @@ public class Resources extends java.util.ListResourceBundle {
"using an alternative signing mechanism"}, "using an alternative signing mechanism"},
{"entry.was.signed.on", "entry was signed on {0}"}, {"entry.was.signed.on", "entry was signed on {0}"},
{"Warning.", "Warning: "}, {"Warning.", "Warning: "},
{"Error.", "Error: "},
{"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.", {"This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.",
"This jar contains unsigned entries which have not been integrity-checked. "}, "This jar contains unsigned entries which have not been integrity-checked. "},
{"This.jar.contains.entries.whose.signer.certificate.has.expired.", {"This.jar.contains.entries.whose.signer.certificate.has.expired.",
...@@ -229,6 +233,10 @@ public class Resources extends java.util.ListResourceBundle { ...@@ -229,6 +233,10 @@ public class Resources extends java.util.ListResourceBundle {
"The signer's certificate chain is not validated."}, "The signer's certificate chain is not validated."},
{"This.jar.contains.entries.whose.certificate.chain.is.not.validated.", {"This.jar.contains.entries.whose.certificate.chain.is.not.validated.",
"This jar contains entries whose certificate chain is not validated."}, "This jar contains entries whose certificate chain is not validated."},
{"no.timestamp.signing",
"No -tsa or -tsacert is provided and this jar is not timestamped. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
{"no.timestamp.verifying",
"This jar contains signatures that does not include a timestamp. Without a timestamp, users may not be able to validate this jar after the signer certificate's expiration date (%1$tY-%1$tm-%1$td) or after any future revocation date."},
{"Unknown.password.type.", "Unknown password type: "}, {"Unknown.password.type.", "Unknown password type: "},
{"Cannot.find.environment.variable.", {"Cannot.find.environment.variable.",
"Cannot find environment variable: "}, "Cannot find environment variable: "},
......
...@@ -182,6 +182,7 @@ package.access=sun.,\ ...@@ -182,6 +182,7 @@ package.access=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -205,7 +206,7 @@ package.access=sun.,\ ...@@ -205,7 +206,7 @@ package.access=sun.,\
com.sun.org.glassfish.,\ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\ oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\ org.jcp.xml.dsig.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
...@@ -228,6 +229,7 @@ package.definition=sun.,\ ...@@ -228,6 +229,7 @@ package.definition=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -251,7 +253,7 @@ package.definition=sun.,\ ...@@ -251,7 +253,7 @@ package.definition=sun.,\
com.sun.org.glassfish.,\ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\ oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\ org.jcp.xml.dsig.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
......
...@@ -183,6 +183,7 @@ package.access=sun.,\ ...@@ -183,6 +183,7 @@ package.access=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -229,6 +230,7 @@ package.definition=sun.,\ ...@@ -229,6 +230,7 @@ package.definition=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
......
...@@ -184,6 +184,7 @@ package.access=sun.,\ ...@@ -184,6 +184,7 @@ package.access=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -207,7 +208,7 @@ package.access=sun.,\ ...@@ -207,7 +208,7 @@ package.access=sun.,\
com.sun.org.glassfish.,\ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\ oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\ org.jcp.xml.dsig.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
...@@ -229,6 +230,7 @@ package.definition=sun.,\ ...@@ -229,6 +230,7 @@ package.definition=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -252,7 +254,7 @@ package.definition=sun.,\ ...@@ -252,7 +254,7 @@ package.definition=sun.,\
com.sun.org.glassfish.,\ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\ oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\ org.jcp.xml.dsig.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
......
...@@ -183,6 +183,7 @@ package.access=sun.,\ ...@@ -183,6 +183,7 @@ package.access=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -206,7 +207,7 @@ package.access=sun.,\ ...@@ -206,7 +207,7 @@ package.access=sun.,\
com.sun.org.glassfish.,\ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\ oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\ org.jcp.xml.dsig.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
...@@ -229,6 +230,7 @@ package.definition=sun.,\ ...@@ -229,6 +230,7 @@ package.definition=sun.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.media.sound.,\ com.sun.media.sound.,\
com.sun.naming.internal.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.corba.se.,\ com.sun.corba.se.,\
com.sun.org.apache.bcel.internal.,\ com.sun.org.apache.bcel.internal.,\
...@@ -252,7 +254,7 @@ package.definition=sun.,\ ...@@ -252,7 +254,7 @@ package.definition=sun.,\
com.sun.org.glassfish.,\ com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
oracle.jrockit.jfr.,\ oracle.jrockit.jfr.,\
org.jcp.xml.dsig.internal.,\ org.jcp.xml.dsig.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
......
...@@ -111,8 +111,9 @@ SplashDone(Splash * splash) ...@@ -111,8 +111,9 @@ SplashDone(Splash * splash)
int int
SplashIsStillLooping(Splash * splash) SplashIsStillLooping(Splash * splash)
{ {
if (splash->currentFrame < 0) if (splash->currentFrame < 0) {
return 0; return 0;
}
return splash->loopCount != 1 || return splash->loopCount != 1 ||
splash->currentFrame + 1 < splash->frameCount; splash->currentFrame + 1 < splash->frameCount;
} }
...@@ -121,17 +122,22 @@ void ...@@ -121,17 +122,22 @@ void
SplashUpdateScreenData(Splash * splash) SplashUpdateScreenData(Splash * splash)
{ {
ImageRect srcRect, dstRect; ImageRect srcRect, dstRect;
if (splash->currentFrame < 0) {
return;
}
initRect(&srcRect, 0, 0, splash->width, splash->height, 1, initRect(&srcRect, 0, 0, splash->width, splash->height, 1,
splash->width * sizeof(rgbquad_t), splash->width * sizeof(rgbquad_t),
splash->frames[splash->currentFrame].bitmapBits, &splash->imageFormat); splash->frames[splash->currentFrame].bitmapBits, &splash->imageFormat);
if (splash->screenData) if (splash->screenData) {
free(splash->screenData); free(splash->screenData);
}
splash->screenStride = splash->width * splash->screenFormat.depthBytes; splash->screenStride = splash->width * splash->screenFormat.depthBytes;
if (splash->byteAlignment > 1) if (splash->byteAlignment > 1) {
splash->screenStride = splash->screenStride =
(splash->screenStride + splash->byteAlignment - 1) & (splash->screenStride + splash->byteAlignment - 1) &
~(splash->byteAlignment - 1); ~(splash->byteAlignment - 1);
}
splash->screenData = malloc(splash->height * splash->screenStride); splash->screenData = malloc(splash->height * splash->screenStride);
initRect(&dstRect, 0, 0, splash->width, splash->height, 1, initRect(&dstRect, 0, 0, splash->width, splash->height, 1,
splash->screenStride, splash->screenData, &splash->screenFormat); splash->screenStride, splash->screenData, &splash->screenFormat);
...@@ -146,16 +152,19 @@ SplashUpdateScreenData(Splash * splash) ...@@ -146,16 +152,19 @@ SplashUpdateScreenData(Splash * splash)
void void
SplashNextFrame(Splash * splash) SplashNextFrame(Splash * splash)
{ {
if (splash->currentFrame < 0) if (splash->currentFrame < 0) {
return; return;
}
do { do {
if (!SplashIsStillLooping(splash)) if (!SplashIsStillLooping(splash)) {
return; return;
}
splash->time += splash->frames[splash->currentFrame].delay; splash->time += splash->frames[splash->currentFrame].delay;
if (++splash->currentFrame >= splash->frameCount) { if (++splash->currentFrame >= splash->frameCount) {
splash->currentFrame = 0; splash->currentFrame = 0;
if (splash->loopCount > 0) if (splash->loopCount > 0) {
splash->loopCount--; splash->loopCount--;
}
} }
} while (splash->time + splash->frames[splash->currentFrame].delay - } while (splash->time + splash->frames[splash->currentFrame].delay -
SplashTime() <= 0); SplashTime() <= 0);
...@@ -183,8 +192,9 @@ BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out) ...@@ -183,8 +192,9 @@ BitmapToYXBandedRectangles(ImageRect * pSrcRect, RECT_T * out)
pSrc += pSrcRect->depthBytes; pSrc += pSrcRect->depthBytes;
++i; ++i;
} }
if (i >= pSrcRect->numSamples) if (i >= pSrcRect->numSamples) {
break; break;
}
i0 = i; i0 = i;
while (i < pSrcRect->numSamples && while (i < pSrcRect->numSamples &&
getRGBA(pSrc, pSrcRect->format) >= ALPHA_THRESHOLD) { getRGBA(pSrc, pSrcRect->format) >= ALPHA_THRESHOLD) {
......
...@@ -55,7 +55,7 @@ le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSu ...@@ -55,7 +55,7 @@ le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSu
(const AlternateSetTable *) ((char *) this + alternateSetTableOffset)); (const AlternateSetTable *) ((char *) this + alternateSetTableOffset));
TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[0]); TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[0]);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate))) { if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate), success)) {
glyphIterator->setCurrGlyphID(SWAPW(alternateSetTable->alternateArray[0])); glyphIterator->setCurrGlyphID(SWAPW(alternateSetTable->alternateArray[0]));
} }
......
...@@ -37,55 +37,54 @@ ...@@ -37,55 +37,54 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
void AnchorTable::getAnchor(LEGlyphID glyphID, const LEFontInstance *fontInstance, void AnchorTable::getAnchor(const LETableReference &base, LEGlyphID glyphID, const LEFontInstance *fontInstance,
LEPoint &anchor) const LEPoint &anchor, LEErrorCode &success) const
{ {
switch(SWAPW(anchorFormat)) { switch(SWAPW(anchorFormat)) {
case 1: case 1:
{ {
const Format1AnchorTable *f1 = (const Format1AnchorTable *) this; LEReferenceTo<Format1AnchorTable> f1(base, success);
f1->getAnchor(f1, fontInstance, anchor, success);
f1->getAnchor(fontInstance, anchor);
break; break;
} }
case 2: case 2:
{ {
const Format2AnchorTable *f2 = (const Format2AnchorTable *) this; LEReferenceTo<Format2AnchorTable> f2(base, success);
f2->getAnchor(f2, glyphID, fontInstance, anchor, success);
f2->getAnchor(glyphID, fontInstance, anchor);
break; break;
} }
case 3: case 3:
{ {
const Format3AnchorTable *f3 = (const Format3AnchorTable *) this; LEReferenceTo<Format3AnchorTable> f3(base, success);
f3->getAnchor(f3, fontInstance, anchor, success);
f3->getAnchor(fontInstance, anchor);
break; break;
} }
default: default:
{
// unknown format: just use x, y coordinate, like format 1... // unknown format: just use x, y coordinate, like format 1...
const Format1AnchorTable *f1 = (const Format1AnchorTable *) this; LEReferenceTo<Format1AnchorTable> f1(base, success);
f1->getAnchor(f1, fontInstance, anchor, success);
f1->getAnchor(fontInstance, anchor);
break; break;
} }
}
} }
void Format1AnchorTable::getAnchor(const LEFontInstance *fontInstance, LEPoint &anchor) const void Format1AnchorTable::getAnchor(const LEReferenceTo<Format1AnchorTable>& base, const LEFontInstance *fontInstance, LEPoint &anchor, LEErrorCode &success) const
{ {
le_int16 x = SWAPW(xCoordinate); le_int16 x = SWAPW(xCoordinate);
le_int16 y = SWAPW(yCoordinate); le_int16 y = SWAPW(yCoordinate);
LEPoint pixels; LEPoint pixels;
fontInstance->transformFunits(x, y, pixels); fontInstance->transformFunits(x, y, pixels);
fontInstance->pixelsToUnits(pixels, anchor); fontInstance->pixelsToUnits(pixels, anchor);
} }
void Format2AnchorTable::getAnchor(LEGlyphID glyphID, const LEFontInstance *fontInstance, LEPoint &anchor) const void Format2AnchorTable::getAnchor(const LEReferenceTo<Format2AnchorTable>& base,
LEGlyphID glyphID, const LEFontInstance *fontInstance, LEPoint &anchor
, LEErrorCode &success) const
{ {
LEPoint point; LEPoint point;
...@@ -100,7 +99,8 @@ void Format2AnchorTable::getAnchor(LEGlyphID glyphID, const LEFontInstance *font ...@@ -100,7 +99,8 @@ void Format2AnchorTable::getAnchor(LEGlyphID glyphID, const LEFontInstance *font
fontInstance->pixelsToUnits(point, anchor); fontInstance->pixelsToUnits(point, anchor);
} }
void Format3AnchorTable::getAnchor(const LEFontInstance *fontInstance, LEPoint &anchor) const void Format3AnchorTable::getAnchor(const LEReferenceTo<Format3AnchorTable> &base, const LEFontInstance *fontInstance,
LEPoint &anchor, LEErrorCode &success) const
{ {
le_int16 x = SWAPW(xCoordinate); le_int16 x = SWAPW(xCoordinate);
le_int16 y = SWAPW(yCoordinate); le_int16 y = SWAPW(yCoordinate);
...@@ -111,15 +111,15 @@ void Format3AnchorTable::getAnchor(const LEFontInstance *fontInstance, LEPoint & ...@@ -111,15 +111,15 @@ void Format3AnchorTable::getAnchor(const LEFontInstance *fontInstance, LEPoint &
fontInstance->transformFunits(x, y, pixels); fontInstance->transformFunits(x, y, pixels);
if (dtxOffset != 0) { if (dtxOffset != 0) {
const DeviceTable *dtx = (const DeviceTable *) ((char *) this + dtxOffset); LEReferenceTo<DeviceTable> dt(base, success, dtxOffset);
le_int16 adjx = dtx->getAdjustment((le_int16) fontInstance->getXPixelsPerEm()); le_int16 adjx = dt->getAdjustment(dt, (le_int16) fontInstance->getXPixelsPerEm(), success);
pixels.fX += adjx; pixels.fX += adjx;
} }
if (dtyOffset != 0) { if (dtyOffset != 0) {
const DeviceTable *dty = (const DeviceTable *) ((char *) this + dtyOffset); LEReferenceTo<DeviceTable> dt(base, success, dtyOffset);
le_int16 adjy = dty->getAdjustment((le_int16) fontInstance->getYPixelsPerEm()); le_int16 adjy = dt->getAdjustment(dt, (le_int16) fontInstance->getYPixelsPerEm(), success);
pixels.fY += adjy; pixels.fY += adjy;
} }
......
...@@ -49,20 +49,23 @@ struct AnchorTable ...@@ -49,20 +49,23 @@ struct AnchorTable
le_int16 xCoordinate; le_int16 xCoordinate;
le_int16 yCoordinate; le_int16 yCoordinate;
void getAnchor(LEGlyphID glyphID, const LEFontInstance *fontInstance, void getAnchor(const LETableReference &base, LEGlyphID glyphID, const LEFontInstance *fontInstance,
LEPoint &anchor) const; LEPoint &anchor, LEErrorCode &success) const;
}; };
struct Format1AnchorTable : AnchorTable struct Format1AnchorTable : AnchorTable
{ {
void getAnchor(const LEFontInstance *fontInstance, LEPoint &anchor) const; void getAnchor(const LEReferenceTo<Format1AnchorTable>& base,
const LEFontInstance *fontInstance, LEPoint &anchor, LEErrorCode &success) const;
}; };
struct Format2AnchorTable : AnchorTable struct Format2AnchorTable : AnchorTable
{ {
le_uint16 anchorPoint; le_uint16 anchorPoint;
void getAnchor(LEGlyphID glyphID, const LEFontInstance *fontInstance, LEPoint &anchor) const; void getAnchor(const LEReferenceTo<Format2AnchorTable>& base,
LEGlyphID glyphID, const LEFontInstance *fontInstance,
LEPoint &anchor, LEErrorCode &success) const;
}; };
struct Format3AnchorTable : AnchorTable struct Format3AnchorTable : AnchorTable
...@@ -70,7 +73,9 @@ struct Format3AnchorTable : AnchorTable ...@@ -70,7 +73,9 @@ struct Format3AnchorTable : AnchorTable
Offset xDeviceTableOffset; Offset xDeviceTableOffset;
Offset yDeviceTableOffset; Offset yDeviceTableOffset;
void getAnchor(const LEFontInstance *fontInstance, LEPoint &anchor) const; void getAnchor(const LEReferenceTo<Format3AnchorTable>& base,
const LEFontInstance *fontInstance, LEPoint &anchor,
LEErrorCode &success) const;
}; };
U_NAMESPACE_END U_NAMESPACE_END
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const le_bool CharSubstitutionFilter::accept(LEGlyphID glyph, LEErrorCode &/*success*/) const
{ {
return fFontInstance->canDisplay((LEUnicode) glyph); return fFontInstance->canDisplay((LEUnicode) glyph);
} }
...@@ -147,7 +147,9 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l ...@@ -147,7 +147,9 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l
GDEFMarkFilter filter(fGDEFTable, success); GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(glyphStorage, &filter, success); adjustMarkGlyphs(glyphStorage, &filter, success);
} else { } else {
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen); LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(LETableReference::kStaticData,
CanonShaping::glyphDefinitionTable,
CanonShaping::glyphDefinitionTableLen);
GDEFMarkFilter filter(gdefTable, success); GDEFMarkFilter filter(gdefTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success); adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
...@@ -157,9 +159,9 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l ...@@ -157,9 +159,9 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l
UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success) UnicodeArabicOpenTypeLayoutEngine::UnicodeArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
: ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success) : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success)
{ {
fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable; fGSUBTable.setTo(LETableReference::kStaticData, (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable, CanonShaping::glyphSubstitutionTableLen);
fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable; fGDEFTable.setTo(LETableReference::kStaticData, (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
/* OpenTypeLayoutEngine will allocate a substitution filter */ /* OpenTypeLayoutEngine will allocate a substitution filter */
} }
UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine() UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
......
...@@ -59,7 +59,8 @@ const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] = ...@@ -59,7 +59,8 @@ const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c) ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
{ {
LEErrorCode success = LE_NO_ERROR; LEErrorCode success = LE_NO_ERROR;
const LEReferenceTo<ClassDefinitionTable> joiningTypes((const ClassDefinitionTable *) ArabicShaping::shapingTypeTable, const LEReferenceTo<ClassDefinitionTable> joiningTypes(LETableReference::kStaticData,
(const ClassDefinitionTable *) ArabicShaping::shapingTypeTable,
ArabicShaping::shapingTypeTableLen); ArabicShaping::shapingTypeTableLen);
le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success); le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success);
......
...@@ -60,7 +60,7 @@ void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le ...@@ -60,7 +60,7 @@ void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le
LEUnicode *outChars, LEGlyphStorage &glyphStorage) LEUnicode *outChars, LEGlyphStorage &glyphStorage)
{ {
LEErrorCode success = LE_NO_ERROR; LEErrorCode success = LE_NO_ERROR;
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen); LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(LETableReference::kStaticData, CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
LEReferenceTo<ClassDefinitionTable> classTable = gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success); LEReferenceTo<ClassDefinitionTable> classTable = gdefTable->getMarkAttachClassDefinitionTable(gdefTable, success);
le_int32 *combiningClasses = LE_NEW_ARRAY(le_int32, charCount); le_int32 *combiningClasses = LE_NEW_ARRAY(le_int32, charCount);
le_int32 *indices = LE_NEW_ARRAY(le_int32, charCount); le_int32 *indices = LE_NEW_ARRAY(le_int32, charCount);
......
...@@ -43,6 +43,8 @@ class LEFontInstance; ...@@ -43,6 +43,8 @@ class LEFontInstance;
* This filter is used by character-based GSUB processors. It * This filter is used by character-based GSUB processors. It
* accepts only those characters which the given font can display. * accepts only those characters which the given font can display.
* *
* Note: Implementation is in ArabicLayoutEngine.cpp
*
* @internal * @internal
*/ */
class CharSubstitutionFilter : public UMemory, public LEGlyphFilter class CharSubstitutionFilter : public UMemory, public LEGlyphFilter
...@@ -97,7 +99,7 @@ public: ...@@ -97,7 +99,7 @@ public:
* *
* @internal * @internal
*/ */
le_bool accept(LEGlyphID glyph) const; le_bool accept(LEGlyphID glyph, LEErrorCode &success) const;
}; };
U_NAMESPACE_END U_NAMESPACE_END
......
...@@ -49,6 +49,7 @@ struct ClassDefinitionTable ...@@ -49,6 +49,7 @@ struct ClassDefinitionTable
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const; le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const; le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
#if LE_ENABLE_RAW
le_int32 getGlyphClass(LEGlyphID glyphID) const { le_int32 getGlyphClass(LEGlyphID glyphID) const {
LETableReference base((const le_uint8*)this); LETableReference base((const le_uint8*)this);
LEErrorCode ignored = LE_NO_ERROR; LEErrorCode ignored = LE_NO_ERROR;
...@@ -60,6 +61,7 @@ struct ClassDefinitionTable ...@@ -60,6 +61,7 @@ struct ClassDefinitionTable
LEErrorCode ignored = LE_NO_ERROR; LEErrorCode ignored = LE_NO_ERROR;
return hasGlyphClass(base,glyphClass,ignored); return hasGlyphClass(base,glyphClass,ignored);
} }
#endif
}; };
struct ClassDefFormat1Table : ClassDefinitionTable struct ClassDefFormat1Table : ClassDefinitionTable
......
...@@ -48,7 +48,7 @@ U_NAMESPACE_BEGIN ...@@ -48,7 +48,7 @@ U_NAMESPACE_BEGIN
*/ */
void ContextualSubstitutionBase::applySubstitutionLookups( void ContextualSubstitutionBase::applySubstitutionLookups(
const LookupProcessor *lookupProcessor, const LookupProcessor *lookupProcessor,
const SubstitutionLookupRecord *substLookupRecordArray, const LEReferenceToArrayOf<SubstitutionLookupRecord>& substLookupRecordArray,
le_uint16 substCount, le_uint16 substCount,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
...@@ -60,10 +60,11 @@ void ContextualSubstitutionBase::applySubstitutionLookups( ...@@ -60,10 +60,11 @@ void ContextualSubstitutionBase::applySubstitutionLookups(
} }
GlyphIterator tempIterator(*glyphIterator); GlyphIterator tempIterator(*glyphIterator);
const SubstitutionLookupRecord *substLookupRecordArrayPtr = substLookupRecordArray.getAlias(); // OK to dereference, range checked against substCount below.
for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) { for (le_int16 subst = 0; subst < substCount && LE_SUCCESS(success); subst += 1) {
le_uint16 sequenceIndex = SWAPW(substLookupRecordArray[subst].sequenceIndex); le_uint16 sequenceIndex = SWAPW(substLookupRecordArrayPtr[subst].sequenceIndex);
le_uint16 lookupListIndex = SWAPW(substLookupRecordArray[subst].lookupListIndex); le_uint16 lookupListIndex = SWAPW(substLookupRecordArrayPtr[subst].lookupListIndex);
tempIterator.setCurrStreamPosition(position); tempIterator.setCurrStreamPosition(position);
tempIterator.next(sequenceIndex); tempIterator.next(sequenceIndex);
...@@ -72,7 +73,7 @@ void ContextualSubstitutionBase::applySubstitutionLookups( ...@@ -72,7 +73,7 @@ void ContextualSubstitutionBase::applySubstitutionLookups(
} }
} }
le_bool ContextualSubstitutionBase::matchGlyphIDs(const TTGlyphID *glyphArray, le_uint16 glyphCount, le_bool ContextualSubstitutionBase::matchGlyphIDs(const LEReferenceToArrayOf<TTGlyphID>& glyphArray, le_uint16 glyphCount,
GlyphIterator *glyphIterator, le_bool backtrack) GlyphIterator *glyphIterator, le_bool backtrack)
{ {
le_int32 direction = 1; le_int32 direction = 1;
...@@ -101,10 +102,13 @@ le_bool ContextualSubstitutionBase::matchGlyphIDs(const TTGlyphID *glyphArray, l ...@@ -101,10 +102,13 @@ le_bool ContextualSubstitutionBase::matchGlyphIDs(const TTGlyphID *glyphArray, l
return TRUE; return TRUE;
} }
le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArray, le_uint16 glyphCount, le_bool ContextualSubstitutionBase::matchGlyphClasses(
GlyphIterator *glyphIterator, const LEReferenceToArrayOf<le_uint16> &classArray,
const ClassDefinitionTable *classDefinitionTable, le_uint16 glyphCount,
le_bool backtrack) GlyphIterator *glyphIterator,
const LEReferenceTo<ClassDefinitionTable> &classDefinitionTable,
LEErrorCode &success,
le_bool backtrack)
{ {
le_int32 direction = 1; le_int32 direction = 1;
le_int32 match = 0; le_int32 match = 0;
...@@ -120,7 +124,7 @@ le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArra ...@@ -120,7 +124,7 @@ le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArra
} }
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 glyphClass = classDefinitionTable->getGlyphClass(glyph); le_int32 glyphClass = classDefinitionTable->getGlyphClass(classDefinitionTable, glyph, success);
le_int32 matchClass = SWAPW(classArray[match]); le_int32 matchClass = SWAPW(classArray[match]);
if (glyphClass != matchClass) { if (glyphClass != matchClass) {
...@@ -128,7 +132,7 @@ le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArra ...@@ -128,7 +132,7 @@ le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArra
// in the class array which aren't in the class definition // in the class array which aren't in the class definition
// table. If we're looking for such a class, pretend that // table. If we're looking for such a class, pretend that
// we found it. // we found it.
if (classDefinitionTable->hasGlyphClass(matchClass)) { if (classDefinitionTable->hasGlyphClass(classDefinitionTable, matchClass, success)) {
return FALSE; return FALSE;
} }
} }
...@@ -140,8 +144,8 @@ le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArra ...@@ -140,8 +144,8 @@ le_bool ContextualSubstitutionBase::matchGlyphClasses(const le_uint16 *classArra
return TRUE; return TRUE;
} }
le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTableOffsetArray, le_uint16 glyphCount, le_bool ContextualSubstitutionBase::matchGlyphCoverages(const LEReferenceToArrayOf<Offset> &coverageTableOffsetArray, le_uint16 glyphCount,
GlyphIterator *glyphIterator, const char *offsetBase, le_bool backtrack) GlyphIterator *glyphIterator, const LETableReference &offsetBase, LEErrorCode &success, le_bool backtrack)
{ {
le_int32 direction = 1; le_int32 direction = 1;
le_int32 glyph = 0; le_int32 glyph = 0;
...@@ -153,13 +157,15 @@ le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTa ...@@ -153,13 +157,15 @@ le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTa
while (glyphCount > 0) { while (glyphCount > 0) {
Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]); Offset coverageTableOffset = SWAPW(coverageTableOffsetArray[glyph]);
const CoverageTable *coverageTable = (const CoverageTable *) (offsetBase + coverageTableOffset); LEReferenceTo<CoverageTable> coverageTable(offsetBase, success, coverageTableOffset);
if (! glyphIterator->next()) { if (LE_FAILURE(success) || ! glyphIterator->next()) {
return FALSE; return FALSE;
} }
if (coverageTable->getGlyphCoverage((LEGlyphID) glyphIterator->getCurrGlyphID()) < 0) { if (coverageTable->getGlyphCoverage(coverageTable,
(LEGlyphID) glyphIterator->getCurrGlyphID(),
success) < 0) {
return FALSE; return FALSE;
} }
...@@ -170,7 +176,7 @@ le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTa ...@@ -170,7 +176,7 @@ le_bool ContextualSubstitutionBase::matchGlyphCoverages(const Offset *coverageTa
return TRUE; return TRUE;
} }
le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor, le_uint32 ContextualSubstitutionSubtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode& success) const LEErrorCode& success) const
...@@ -186,20 +192,29 @@ le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupP ...@@ -186,20 +192,29 @@ le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupP
case 1: case 1:
{ {
const ContextualSubstitutionFormat1Subtable *subtable = (const ContextualSubstitutionFormat1Subtable *) this; LEReferenceTo<ContextualSubstitutionFormat1Subtable> subtable(base, success, (const ContextualSubstitutionFormat1Subtable *) this);
return subtable->process(lookupProcessor, glyphIterator, fontInstance, success); if( LE_FAILURE(success) ) {
return 0;
}
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
} }
case 2: case 2:
{ {
const ContextualSubstitutionFormat2Subtable *subtable = (const ContextualSubstitutionFormat2Subtable *) this; LEReferenceTo<ContextualSubstitutionFormat2Subtable> subtable(base, success, (const ContextualSubstitutionFormat2Subtable *) this);
return subtable->process(lookupProcessor, glyphIterator, fontInstance, success); if( LE_FAILURE(success) ) {
return 0;
}
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
} }
case 3: case 3:
{ {
const ContextualSubstitutionFormat3Subtable *subtable = (const ContextualSubstitutionFormat3Subtable *) this; LEReferenceTo<ContextualSubstitutionFormat3Subtable> subtable(base, success, (const ContextualSubstitutionFormat3Subtable *) this);
return subtable->process(lookupProcessor, glyphIterator, fontInstance, success); if( LE_FAILURE(success) ) {
return 0;
}
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
} }
default: default:
...@@ -207,7 +222,7 @@ le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupP ...@@ -207,7 +222,7 @@ le_uint32 ContextualSubstitutionSubtable::process(const LookupProcessor *lookupP
} }
} }
le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, le_uint32 ContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode& success) const LEErrorCode& success) const
...@@ -227,22 +242,22 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor * ...@@ -227,22 +242,22 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *
if (coverageIndex < srSetCount) { if (coverageIndex < srSetCount) {
Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]); Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]);
const SubRuleSetTable *subRuleSetTable = LEReferenceTo<SubRuleSetTable>
(const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset); subRuleSetTable(base, success, (const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset));
le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount); le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount);
le_int32 position = glyphIterator->getCurrStreamPosition(); le_int32 position = glyphIterator->getCurrStreamPosition();
for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) { for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) {
Offset subRuleTableOffset = Offset subRuleTableOffset =
SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]); SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]);
const SubRuleTable *subRuleTable = LEReferenceTo<SubRuleTable>
(const SubRuleTable *) ((char *) subRuleSetTable + subRuleTableOffset); subRuleTable(subRuleSetTable, success, subRuleTableOffset);
le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1; le_uint16 matchCount = SWAPW(subRuleTable->glyphCount) - 1;
le_uint16 substCount = SWAPW(subRuleTable->substCount); le_uint16 substCount = SWAPW(subRuleTable->substCount);
LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, subRuleTable->inputGlyphArray, matchCount+2);
if (matchGlyphIDs(subRuleTable->inputGlyphArray, matchCount, glyphIterator)) { if (matchGlyphIDs(inputGlyphArray, matchCount, glyphIterator)) {
const SubstitutionLookupRecord *substLookupRecordArray = LEReferenceToArrayOf<SubstitutionLookupRecord>
(const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount]; substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subRuleTable->inputGlyphArray[matchCount], substCount);
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
...@@ -259,10 +274,11 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor * ...@@ -259,10 +274,11 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *
return 0; return 0;
} }
le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, le_uint32 ContextualSubstitutionFormat2Subtable::process(const LETableReference &base,
GlyphIterator *glyphIterator, const LookupProcessor *lookupProcessor,
const LEFontInstance *fontInstance, GlyphIterator *glyphIterator,
LEErrorCode& success) const const LEFontInstance *fontInstance,
LEErrorCode& success) const
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return 0; return 0;
...@@ -275,29 +291,33 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor * ...@@ -275,29 +291,33 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *
} }
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
const ClassDefinitionTable *classDefinitionTable = LEReferenceTo<ClassDefinitionTable> classDefinitionTable(base, success,
(const ClassDefinitionTable *) ((char *) this + SWAPW(classDefTableOffset)); (const ClassDefinitionTable *) ((char *) this + SWAPW(classDefTableOffset)));
le_uint16 scSetCount = SWAPW(subClassSetCount); le_uint16 scSetCount = SWAPW(subClassSetCount);
le_int32 setClass = classDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID()); le_int32 setClass = classDefinitionTable->getGlyphClass(classDefinitionTable,
glyphIterator->getCurrGlyphID(),
success);
if (setClass < scSetCount && subClassSetTableOffsetArray[setClass] != 0) { if (setClass < scSetCount && subClassSetTableOffsetArray[setClass] != 0) {
Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]); Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]);
const SubClassSetTable *subClassSetTable = LEReferenceTo<SubClassSetTable>
(const SubClassSetTable *) ((char *) this + subClassSetTableOffset); subClassSetTable(base, success, (const SubClassSetTable *) ((char *) this + subClassSetTableOffset));
le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount); le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount);
le_int32 position = glyphIterator->getCurrStreamPosition(); le_int32 position = glyphIterator->getCurrStreamPosition();
for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) { for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) {
Offset subClassRuleTableOffset = Offset subClassRuleTableOffset =
SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]); SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]);
const SubClassRuleTable *subClassRuleTable = LEReferenceTo<SubClassRuleTable>
(const SubClassRuleTable *) ((char *) subClassSetTable + subClassRuleTableOffset); subClassRuleTable(subClassSetTable, success, subClassRuleTableOffset);
le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1; le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1;
le_uint16 substCount = SWAPW(subClassRuleTable->substCount); le_uint16 substCount = SWAPW(subClassRuleTable->substCount);
if (matchGlyphClasses(subClassRuleTable->classArray, matchCount, glyphIterator, classDefinitionTable)) { LEReferenceToArrayOf<le_uint16> classArray(base, success, subClassRuleTable->classArray, matchCount+1);
const SubstitutionLookupRecord *substLookupRecordArray =
(const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount]; if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) {
LEReferenceToArrayOf<SubstitutionLookupRecord>
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount);
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
...@@ -314,7 +334,8 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor * ...@@ -314,7 +334,8 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *
return 0; return 0;
} }
le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, le_uint32 ContextualSubstitutionFormat3Subtable::process(const LETableReference &base,
const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode& success)const LEErrorCode& success)const
...@@ -333,9 +354,13 @@ le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor * ...@@ -333,9 +354,13 @@ le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor *
// that matched when we're done. // that matched when we're done.
glyphIterator->prev(); glyphIterator->prev();
if (ContextualSubstitutionBase::matchGlyphCoverages(coverageTableOffsetArray, gCount, glyphIterator, (const char *) this)) { LEReferenceToArrayOf<Offset> covTableOffsetArray(base, success, coverageTableOffsetArray, gCount);
const SubstitutionLookupRecord *substLookupRecordArray =
(const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount]; if( LE_FAILURE(success) ) { return 0; }
if (ContextualSubstitutionBase::matchGlyphCoverages(covTableOffsetArray, gCount, glyphIterator, base, success)) {
LEReferenceToArrayOf<SubstitutionLookupRecord>
substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &coverageTableOffsetArray[gCount], subCount);
ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position, success); ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, subCount, glyphIterator, fontInstance, position, success);
...@@ -347,7 +372,8 @@ le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor * ...@@ -347,7 +372,8 @@ le_uint32 ContextualSubstitutionFormat3Subtable::process(const LookupProcessor *
return 0; return 0;
} }
le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor *lookupProcessor, le_uint32 ChainingContextualSubstitutionSubtable::process(const LEReferenceTo<ChainingContextualSubstitutionSubtable> &base,
const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode& success) const LEErrorCode& success) const
...@@ -363,20 +389,23 @@ le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor ...@@ -363,20 +389,23 @@ le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor
case 1: case 1:
{ {
const ChainingContextualSubstitutionFormat1Subtable *subtable = (const ChainingContextualSubstitutionFormat1Subtable *) this; LEReferenceTo<ChainingContextualSubstitutionFormat1Subtable> subtable(base, success, (ChainingContextualSubstitutionFormat1Subtable *) this);
return subtable->process(lookupProcessor, glyphIterator, fontInstance, success); if(LE_FAILURE(success)) return 0;
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
} }
case 2: case 2:
{ {
const ChainingContextualSubstitutionFormat2Subtable *subtable = (const ChainingContextualSubstitutionFormat2Subtable *) this; LEReferenceTo<ChainingContextualSubstitutionFormat2Subtable> subtable(base, success, (const ChainingContextualSubstitutionFormat2Subtable *) this);
return subtable->process(lookupProcessor, glyphIterator, fontInstance, success); if( LE_FAILURE(success) ) { return 0; }
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
} }
case 3: case 3:
{ {
const ChainingContextualSubstitutionFormat3Subtable *subtable = (const ChainingContextualSubstitutionFormat3Subtable *) this; LEReferenceTo<ChainingContextualSubstitutionFormat3Subtable> subtable(base, success, (const ChainingContextualSubstitutionFormat3Subtable *) this);
return subtable->process(lookupProcessor, glyphIterator, fontInstance, success); if( LE_FAILURE(success) ) { return 0; }
return subtable->process(subtable, lookupProcessor, glyphIterator, fontInstance, success);
} }
default: default:
...@@ -390,7 +419,7 @@ le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor ...@@ -390,7 +419,7 @@ le_uint32 ChainingContextualSubstitutionSubtable::process(const LookupProcessor
// emptyFeatureList matches an le_uint32 or an le_uint16... // emptyFeatureList matches an le_uint32 or an le_uint16...
static const FeatureMask emptyFeatureList = 0x00000000UL; static const FeatureMask emptyFeatureList = 0x00000000UL;
le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupProcessor *lookupProcessor, le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode& success) const LEErrorCode& success) const
...@@ -410,8 +439,8 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro ...@@ -410,8 +439,8 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
if (coverageIndex < srSetCount) { if (coverageIndex < srSetCount) {
Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]); Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]);
const ChainSubRuleSetTable *chainSubRuleSetTable = LEReferenceTo<ChainSubRuleSetTable>
(const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset); chainSubRuleSetTable(base, success, (const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset));
le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount); le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount);
le_int32 position = glyphIterator->getCurrStreamPosition(); le_int32 position = glyphIterator->getCurrStreamPosition();
GlyphIterator tempIterator(*glyphIterator, emptyFeatureList); GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
...@@ -419,13 +448,19 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro ...@@ -419,13 +448,19 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) { for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) {
Offset chainSubRuleTableOffset = Offset chainSubRuleTableOffset =
SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]); SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]);
const ChainSubRuleTable *chainSubRuleTable = LEReferenceTo<ChainSubRuleTable>
(const ChainSubRuleTable *) ((char *) chainSubRuleSetTable + chainSubRuleTableOffset); chainSubRuleTable = LEReferenceTo<ChainSubRuleTable>(chainSubRuleSetTable, success, chainSubRuleTableOffset);
if( LE_FAILURE(success) ) { return 0; }
le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount); le_uint16 backtrackGlyphCount = SWAPW(chainSubRuleTable->backtrackGlyphCount);
LEReferenceToArrayOf<TTGlyphID> backtrackGlyphArray(base, success, chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount);
if( LE_FAILURE(success) ) { return 0; }
le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1; le_uint16 inputGlyphCount = (le_uint16) SWAPW(chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount]) - 1;
const TTGlyphID *inputGlyphArray = &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1]; LEReferenceToArrayOf<TTGlyphID> inputGlyphArray(base, success, &chainSubRuleTable->backtrackGlyphArray[backtrackGlyphCount + 1], inputGlyphCount+2);
if( LE_FAILURE(success) ) { return 0; }
le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]); le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputGlyphArray[inputGlyphCount]);
const TTGlyphID *lookaheadGlyphArray = &inputGlyphArray[inputGlyphCount + 1]; LEReferenceToArrayOf<TTGlyphID> lookaheadGlyphArray(base, success, inputGlyphArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2);
if( LE_FAILURE(success) ) { return 0; }
le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]); le_uint16 substCount = (le_uint16) SWAPW(lookaheadGlyphArray[lookaheadGlyphCount]);
tempIterator.setCurrStreamPosition(position); tempIterator.setCurrStreamPosition(position);
...@@ -435,7 +470,8 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro ...@@ -435,7 +470,8 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
} }
tempIterator.prev(); tempIterator.prev();
if (! matchGlyphIDs(chainSubRuleTable->backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
if (! matchGlyphIDs(backtrackGlyphArray, backtrackGlyphCount, &tempIterator, TRUE)) {
continue; continue;
} }
...@@ -446,8 +482,8 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro ...@@ -446,8 +482,8 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
} }
if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) { if (matchGlyphIDs(inputGlyphArray, inputGlyphCount, glyphIterator)) {
const SubstitutionLookupRecord *substLookupRecordArray = LEReferenceToArrayOf<SubstitutionLookupRecord>
(const SubstitutionLookupRecord *) &lookaheadGlyphArray[lookaheadGlyphCount + 1]; substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadGlyphArray.getAlias(lookaheadGlyphCount + 1,success), substCount);
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
...@@ -464,7 +500,7 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro ...@@ -464,7 +500,7 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
return 0; return 0;
} }
le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupProcessor *lookupProcessor, le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode& success) const LEErrorCode& success) const
...@@ -480,19 +516,21 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro ...@@ -480,19 +516,21 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
} }
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
const ClassDefinitionTable *backtrackClassDefinitionTable = LEReferenceTo<ClassDefinitionTable>
(const ClassDefinitionTable *) ((char *) this + SWAPW(backtrackClassDefTableOffset)); backtrackClassDefinitionTable(base, success, (const ClassDefinitionTable *) ((char *) this + SWAPW(backtrackClassDefTableOffset)));
const ClassDefinitionTable *inputClassDefinitionTable = LEReferenceTo<ClassDefinitionTable>
(const ClassDefinitionTable *) ((char *) this + SWAPW(inputClassDefTableOffset)); inputClassDefinitionTable(base, success, (const ClassDefinitionTable *) ((char *) this + SWAPW(inputClassDefTableOffset)));
const ClassDefinitionTable *lookaheadClassDefinitionTable = LEReferenceTo<ClassDefinitionTable>
(const ClassDefinitionTable *) ((char *) this + SWAPW(lookaheadClassDefTableOffset)); lookaheadClassDefinitionTable(base, success, (const ClassDefinitionTable *) ((char *) this + SWAPW(lookaheadClassDefTableOffset)));
le_uint16 scSetCount = SWAPW(chainSubClassSetCount); le_uint16 scSetCount = SWAPW(chainSubClassSetCount);
le_int32 setClass = inputClassDefinitionTable->getGlyphClass(glyphIterator->getCurrGlyphID()); le_int32 setClass = inputClassDefinitionTable->getGlyphClass(inputClassDefinitionTable,
glyphIterator->getCurrGlyphID(),
success);
if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) { if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) {
Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]); Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]);
const ChainSubClassSetTable *chainSubClassSetTable = LEReferenceTo<ChainSubClassSetTable>
(const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset); chainSubClassSetTable(base, success, (const ChainSubClassSetTable *) ((char *) this + chainSubClassSetTableOffset));
le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount); le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount);
le_int32 position = glyphIterator->getCurrStreamPosition(); le_int32 position = glyphIterator->getCurrStreamPosition();
GlyphIterator tempIterator(*glyphIterator, emptyFeatureList); GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
...@@ -500,13 +538,15 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro ...@@ -500,13 +538,15 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) { for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) {
Offset chainSubClassRuleTableOffset = Offset chainSubClassRuleTableOffset =
SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]); SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]);
const ChainSubClassRuleTable *chainSubClassRuleTable = LEReferenceTo<ChainSubClassRuleTable>
(const ChainSubClassRuleTable *) ((char *) chainSubClassSetTable + chainSubClassRuleTableOffset); chainSubClassRuleTable(chainSubClassSetTable, success, chainSubClassRuleTableOffset);
le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount); le_uint16 backtrackGlyphCount = SWAPW(chainSubClassRuleTable->backtrackGlyphCount);
le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1; le_uint16 inputGlyphCount = SWAPW(chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount]) - 1;
const le_uint16 *inputClassArray = &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1]; LEReferenceToArrayOf<le_uint16> inputClassArray(base, success, &chainSubClassRuleTable->backtrackClassArray[backtrackGlyphCount + 1],inputGlyphCount+2); // +2 for the lookaheadGlyphCount count
le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray[inputGlyphCount]); le_uint16 lookaheadGlyphCount = SWAPW(inputClassArray.getObject(inputGlyphCount, success));
const le_uint16 *lookaheadClassArray = &inputClassArray[inputGlyphCount + 1]; LEReferenceToArrayOf<le_uint16> lookaheadClassArray(base, success, inputClassArray.getAlias(inputGlyphCount + 1,success), lookaheadGlyphCount+2); // +2 for the substCount
if( LE_FAILURE(success) ) { return 0; }
le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]); le_uint16 substCount = SWAPW(lookaheadClassArray[lookaheadGlyphCount]);
...@@ -517,20 +557,22 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro ...@@ -517,20 +557,22 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
} }
tempIterator.prev(); tempIterator.prev();
if (! matchGlyphClasses(chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount, LEReferenceToArrayOf<le_uint16> backtrackClassArray(base, success, chainSubClassRuleTable->backtrackClassArray, backtrackGlyphCount);
&tempIterator, backtrackClassDefinitionTable, TRUE)) { if( LE_FAILURE(success) ) { return 0; }
if (! matchGlyphClasses(backtrackClassArray, backtrackGlyphCount,
&tempIterator, backtrackClassDefinitionTable, success, TRUE)) {
continue; continue;
} }
tempIterator.setCurrStreamPosition(position); tempIterator.setCurrStreamPosition(position);
tempIterator.next(inputGlyphCount); tempIterator.next(inputGlyphCount);
if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable)) { if (! matchGlyphClasses(lookaheadClassArray, lookaheadGlyphCount, &tempIterator, lookaheadClassDefinitionTable, success)) {
continue; continue;
} }
if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable)) { if (matchGlyphClasses(inputClassArray, inputGlyphCount, glyphIterator, inputClassDefinitionTable, success)) {
const SubstitutionLookupRecord *substLookupRecordArray = LEReferenceToArrayOf<SubstitutionLookupRecord>
(const SubstitutionLookupRecord *) &lookaheadClassArray[lookaheadGlyphCount + 1]; substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) lookaheadClassArray.getAlias(lookaheadGlyphCount + 1, success), substCount);
applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
...@@ -547,7 +589,7 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro ...@@ -547,7 +589,7 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
return 0; return 0;
} }
le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupProcessor *lookupProcessor, le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
LEErrorCode & success) const LEErrorCode & success) const
...@@ -558,9 +600,13 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupPro ...@@ -558,9 +600,13 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupPro
le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount); le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount);
le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]); le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]);
const Offset *inputCoverageTableOffsetArray = &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1]; LEReferenceToArrayOf<Offset> inputCoverageTableOffsetArray(base, success, &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1], inputGlyphCount+2); // offset
const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]); const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]);
const Offset *lookaheadCoverageTableOffsetArray = &inputCoverageTableOffsetArray[inputGlyphCount + 1];
if( LE_FAILURE(success) ) { return 0; }
LEReferenceToArrayOf<Offset> lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2);
if( LE_FAILURE(success) ) { return 0; }
le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]); le_uint16 substCount = (le_uint16) SWAPW(lookaheadCoverageTableOffsetArray[lookaheadGlyphCount]);
le_int32 position = glyphIterator->getCurrStreamPosition(); le_int32 position = glyphIterator->getCurrStreamPosition();
GlyphIterator tempIterator(*glyphIterator, emptyFeatureList); GlyphIterator tempIterator(*glyphIterator, emptyFeatureList);
...@@ -571,14 +617,14 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupPro ...@@ -571,14 +617,14 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupPro
tempIterator.prev(); tempIterator.prev();
if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray, if (! ContextualSubstitutionBase::matchGlyphCoverages(backtrackCoverageTableOffsetArray,
backtrkGlyphCount, &tempIterator, (const char *) this, TRUE)) { backtrkGlyphCount, &tempIterator, base, success, TRUE)) {
return 0; return 0;
} }
tempIterator.setCurrStreamPosition(position); tempIterator.setCurrStreamPosition(position);
tempIterator.next(inputGlyphCount - 1); tempIterator.next(inputGlyphCount - 1);
if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray, if (! ContextualSubstitutionBase::matchGlyphCoverages(lookaheadCoverageTableOffsetArray,
lookaheadGlyphCount, &tempIterator, (const char *) this)) { lookaheadGlyphCount, &tempIterator, base, success)) {
return 0; return 0;
} }
...@@ -589,9 +635,10 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupPro ...@@ -589,9 +635,10 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LookupPro
glyphIterator->prev(); glyphIterator->prev();
if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray, if (ContextualSubstitutionBase::matchGlyphCoverages(inputCoverageTableOffsetArray,
inputGlyphCount, glyphIterator, (const char *) this)) { inputGlyphCount, glyphIterator, base, success)) {
const SubstitutionLookupRecord *substLookupRecordArray = LEReferenceToArrayOf<SubstitutionLookupRecord>
(const SubstitutionLookupRecord *) &lookaheadCoverageTableOffsetArray[lookaheadGlyphCount + 1]; substLookupRecordArray(base, success,
(const SubstitutionLookupRecord *) lookaheadCoverageTableOffsetArray.getAlias(lookaheadGlyphCount + 1,success), substCount);
ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); ContextualSubstitutionBase::applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success);
......
...@@ -56,20 +56,32 @@ struct SubstitutionLookupRecord ...@@ -56,20 +56,32 @@ struct SubstitutionLookupRecord
struct ContextualSubstitutionBase : GlyphSubstitutionSubtable struct ContextualSubstitutionBase : GlyphSubstitutionSubtable
{ {
static le_bool matchGlyphIDs( static le_bool matchGlyphIDs(
const TTGlyphID *glyphArray, le_uint16 glyphCount, GlyphIterator *glyphIterator, const LEReferenceToArrayOf<TTGlyphID> &glyphArray, le_uint16 glyphCount, GlyphIterator *glyphIterator,
le_bool backtrack = FALSE); le_bool backtrack = FALSE);
static le_bool matchGlyphClasses( static le_bool matchGlyphClasses(
const le_uint16 *classArray, le_uint16 glyphCount, GlyphIterator *glyphIterator, const LEReferenceToArrayOf<le_uint16> &classArray, le_uint16 glyphCount, GlyphIterator *glyphIterator,
const ClassDefinitionTable *classDefinitionTable, le_bool backtrack = FALSE); const LEReferenceTo<ClassDefinitionTable> &classDefinitionTable, LEErrorCode &success, le_bool backtrack = FALSE);
static le_bool matchGlyphCoverages( static le_bool matchGlyphCoverages(
const Offset *coverageTableOffsetArray, le_uint16 glyphCount, const LEReferenceToArrayOf<Offset> &coverageTableOffsetArray, le_uint16 glyphCount,
GlyphIterator *glyphIterator, const char *offsetBase, le_bool backtrack = FALSE); GlyphIterator *glyphIterator, const LETableReference& offsetBase, LEErrorCode &success, le_bool backtrack = FALSE);
/**
* little shim to wrap the Offset array in range checking
* @private
*/
static le_bool matchGlyphCoverages(
const Offset *coverageTableOffsetArray, le_uint16 glyphCount,
GlyphIterator *glyphIterator, const LETableReference& offsetBase, LEErrorCode &success, le_bool backtrack = FALSE) {
LEReferenceToArrayOf<Offset> ref(offsetBase, success, coverageTableOffsetArray, glyphCount);
if( LE_FAILURE(success) ) { return FALSE; }
return matchGlyphCoverages(ref, glyphCount, glyphIterator, offsetBase, success, backtrack);
}
static void applySubstitutionLookups( static void applySubstitutionLookups(
const LookupProcessor *lookupProcessor, const LookupProcessor *lookupProcessor,
const SubstitutionLookupRecord *substLookupRecordArray, const LEReferenceToArrayOf<SubstitutionLookupRecord>& substLookupRecordArray,
le_uint16 substCount, le_uint16 substCount,
GlyphIterator *glyphIterator, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, const LEFontInstance *fontInstance,
...@@ -79,7 +91,8 @@ struct ContextualSubstitutionBase : GlyphSubstitutionSubtable ...@@ -79,7 +91,8 @@ struct ContextualSubstitutionBase : GlyphSubstitutionSubtable
struct ContextualSubstitutionSubtable : ContextualSubstitutionBase struct ContextualSubstitutionSubtable : ContextualSubstitutionBase
{ {
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
struct ContextualSubstitutionFormat1Subtable : ContextualSubstitutionSubtable struct ContextualSubstitutionFormat1Subtable : ContextualSubstitutionSubtable
...@@ -87,7 +100,8 @@ struct ContextualSubstitutionFormat1Subtable : ContextualSubstitutionSubtable ...@@ -87,7 +100,8 @@ struct ContextualSubstitutionFormat1Subtable : ContextualSubstitutionSubtable
le_uint16 subRuleSetCount; le_uint16 subRuleSetCount;
Offset subRuleSetTableOffsetArray[ANY_NUMBER]; Offset subRuleSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
LE_VAR_ARRAY(ContextualSubstitutionFormat1Subtable, subRuleSetTableOffsetArray) LE_VAR_ARRAY(ContextualSubstitutionFormat1Subtable, subRuleSetTableOffsetArray)
...@@ -116,7 +130,7 @@ struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable ...@@ -116,7 +130,7 @@ struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable
le_uint16 subClassSetCount; le_uint16 subClassSetCount;
Offset subClassSetTableOffsetArray[ANY_NUMBER]; Offset subClassSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
LE_VAR_ARRAY(ContextualSubstitutionFormat2Subtable, subClassSetTableOffsetArray) LE_VAR_ARRAY(ContextualSubstitutionFormat2Subtable, subClassSetTableOffsetArray)
...@@ -152,13 +166,15 @@ struct ContextualSubstitutionFormat3Subtable ...@@ -152,13 +166,15 @@ struct ContextualSubstitutionFormat3Subtable
Offset coverageTableOffsetArray[ANY_NUMBER]; Offset coverageTableOffsetArray[ANY_NUMBER];
//SubstitutionLookupRecord substLookupRecord[ANY_NUMBER]; //SubstitutionLookupRecord substLookupRecord[ANY_NUMBER];
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
LE_VAR_ARRAY(ContextualSubstitutionFormat3Subtable, coverageTableOffsetArray) LE_VAR_ARRAY(ContextualSubstitutionFormat3Subtable, coverageTableOffsetArray)
struct ChainingContextualSubstitutionSubtable : ContextualSubstitutionBase struct ChainingContextualSubstitutionSubtable : ContextualSubstitutionBase
{ {
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LEReferenceTo<ChainingContextualSubstitutionSubtable> &base, const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
struct ChainingContextualSubstitutionFormat1Subtable : ChainingContextualSubstitutionSubtable struct ChainingContextualSubstitutionFormat1Subtable : ChainingContextualSubstitutionSubtable
...@@ -166,7 +182,8 @@ struct ChainingContextualSubstitutionFormat1Subtable : ChainingContextualSubstit ...@@ -166,7 +182,8 @@ struct ChainingContextualSubstitutionFormat1Subtable : ChainingContextualSubstit
le_uint16 chainSubRuleSetCount; le_uint16 chainSubRuleSetCount;
Offset chainSubRuleSetTableOffsetArray[ANY_NUMBER]; Offset chainSubRuleSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat1Subtable, chainSubRuleSetTableOffsetArray) LE_VAR_ARRAY(ChainingContextualSubstitutionFormat1Subtable, chainSubRuleSetTableOffsetArray)
...@@ -201,7 +218,8 @@ struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstit ...@@ -201,7 +218,8 @@ struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstit
le_uint16 chainSubClassSetCount; le_uint16 chainSubClassSetCount;
Offset chainSubClassSetTableOffsetArray[ANY_NUMBER]; Offset chainSubClassSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator,
const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat2Subtable, chainSubClassSetTableOffsetArray) LE_VAR_ARRAY(ChainingContextualSubstitutionFormat2Subtable, chainSubClassSetTableOffsetArray)
...@@ -243,7 +261,8 @@ struct ChainingContextualSubstitutionFormat3Subtable ...@@ -243,7 +261,8 @@ struct ChainingContextualSubstitutionFormat3Subtable
//le_uint16 substCount; //le_uint16 substCount;
//SubstitutionLookupRecord substLookupRecord[ANY_NUMBER]; //SubstitutionLookupRecord substLookupRecord[ANY_NUMBER];
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; le_uint32 process(const LETableReference &base, const LookupProcessor *lookupProcessor,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat3Subtable, backtrackCoverageTableOffsetArray) LE_VAR_ARRAY(ChainingContextualSubstitutionFormat3Subtable, backtrackCoverageTableOffsetArray)
......
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
le_int32 CoverageTable::getGlyphCoverage(LEGlyphID glyphID) const le_int32 CoverageTable::getGlyphCoverage(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const
{ {
if(LE_FAILURE(success)) return -1;
switch(SWAPW(coverageFormat)) switch(SWAPW(coverageFormat))
{ {
case 0: case 0:
...@@ -46,16 +48,16 @@ le_int32 CoverageTable::getGlyphCoverage(LEGlyphID glyphID) const ...@@ -46,16 +48,16 @@ le_int32 CoverageTable::getGlyphCoverage(LEGlyphID glyphID) const
case 1: case 1:
{ {
const CoverageFormat1Table *f1Table = (const CoverageFormat1Table *) this; LEReferenceTo<CoverageFormat1Table> f1Table(base, success);
return f1Table->getGlyphCoverage(glyphID); return f1Table->getGlyphCoverage(f1Table, glyphID, success);
} }
case 2: case 2:
{ {
const CoverageFormat2Table *f2Table = (const CoverageFormat2Table *) this; LEReferenceTo<CoverageFormat2Table> f2Table(base, success);
return f2Table->getGlyphCoverage(glyphID); return f2Table->getGlyphCoverage(f2Table, glyphID, success);
} }
default: default:
...@@ -63,8 +65,10 @@ le_int32 CoverageTable::getGlyphCoverage(LEGlyphID glyphID) const ...@@ -63,8 +65,10 @@ le_int32 CoverageTable::getGlyphCoverage(LEGlyphID glyphID) const
} }
} }
le_int32 CoverageFormat1Table::getGlyphCoverage(LEGlyphID glyphID) const le_int32 CoverageFormat1Table::getGlyphCoverage(LEReferenceTo<CoverageFormat1Table> &base, LEGlyphID glyphID, LEErrorCode &success) const
{ {
if(LE_FAILURE(success)) return -1;
TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID); TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID);
le_uint16 count = SWAPW(glyphCount); le_uint16 count = SWAPW(glyphCount);
le_uint8 bit = OpenTypeUtilities::highBit(count); le_uint8 bit = OpenTypeUtilities::highBit(count);
...@@ -73,37 +77,45 @@ le_int32 CoverageFormat1Table::getGlyphCoverage(LEGlyphID glyphID) const ...@@ -73,37 +77,45 @@ le_int32 CoverageFormat1Table::getGlyphCoverage(LEGlyphID glyphID) const
le_uint16 probe = power; le_uint16 probe = power;
le_uint16 index = 0; le_uint16 index = 0;
if (count == 0) { if (count == 0) {
return -1; return -1;
} }
LEReferenceToArrayOf<TTGlyphID>(base, success, glyphArray, count);
if(LE_FAILURE(success)) return -1; // range checks array
if (SWAPW(glyphArray[extra]) <= ttGlyphID) { if (SWAPW(glyphArray[extra]) <= ttGlyphID) {
index = extra; index = extra;
} }
while (probe > (1 << 0)) { while (probe > (1 << 0)) {
probe >>= 1; probe >>= 1;
if (SWAPW(glyphArray[index + probe]) <= ttGlyphID) { if (SWAPW(glyphArray[index + probe]) <= ttGlyphID) {
index += probe; index += probe;
} }
} }
if (SWAPW(glyphArray[index]) == ttGlyphID) { if (SWAPW(glyphArray[index]) == ttGlyphID) {
return index; return index;
} }
return -1; return -1;
} }
le_int32 CoverageFormat2Table::getGlyphCoverage(LEGlyphID glyphID) const le_int32 CoverageFormat2Table::getGlyphCoverage(LEReferenceTo<CoverageFormat2Table> &base, LEGlyphID glyphID, LEErrorCode &success) const
{ {
if(LE_FAILURE(success)) return -1;
TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID); TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID);
le_uint16 count = SWAPW(rangeCount); le_uint16 count = SWAPW(rangeCount);
LEReferenceToArrayOf<GlyphRangeRecord> rangeRecordArrayRef(base, success, rangeRecordArray, count);
le_int32 rangeIndex = le_int32 rangeIndex =
OpenTypeUtilities::getGlyphRangeIndex(ttGlyphID, rangeRecordArray, count); OpenTypeUtilities::getGlyphRangeIndex(ttGlyphID, rangeRecordArrayRef, success);
if (rangeIndex < 0) { if (rangeIndex < 0 || LE_FAILURE(success)) { // could fail if array out of bounds
return -1; return -1;
} }
......
...@@ -46,7 +46,7 @@ struct CoverageTable ...@@ -46,7 +46,7 @@ struct CoverageTable
{ {
le_uint16 coverageFormat; le_uint16 coverageFormat;
le_int32 getGlyphCoverage(LEGlyphID glyphID) const; le_int32 getGlyphCoverage(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
}; };
struct CoverageFormat1Table : CoverageTable struct CoverageFormat1Table : CoverageTable
...@@ -54,7 +54,7 @@ struct CoverageFormat1Table : CoverageTable ...@@ -54,7 +54,7 @@ struct CoverageFormat1Table : CoverageTable
le_uint16 glyphCount; le_uint16 glyphCount;
TTGlyphID glyphArray[ANY_NUMBER]; TTGlyphID glyphArray[ANY_NUMBER];
le_int32 getGlyphCoverage(LEGlyphID glyphID) const; le_int32 getGlyphCoverage(LEReferenceTo<CoverageFormat1Table> &base, LEGlyphID glyphID, LEErrorCode &success) const;
}; };
LE_VAR_ARRAY(CoverageFormat1Table, glyphArray) LE_VAR_ARRAY(CoverageFormat1Table, glyphArray)
...@@ -64,7 +64,7 @@ struct CoverageFormat2Table : CoverageTable ...@@ -64,7 +64,7 @@ struct CoverageFormat2Table : CoverageTable
le_uint16 rangeCount; le_uint16 rangeCount;
GlyphRangeRecord rangeRecordArray[ANY_NUMBER]; GlyphRangeRecord rangeRecordArray[ANY_NUMBER];
le_int32 getGlyphCoverage(LEGlyphID glyphID) const; le_int32 getGlyphCoverage(LEReferenceTo<CoverageFormat2Table> &base, LEGlyphID glyphID, LEErrorCode &success) const;
}; };
LE_VAR_ARRAY(CoverageFormat2Table, rangeRecordArray) LE_VAR_ARRAY(CoverageFormat2Table, rangeRecordArray)
......
...@@ -51,23 +51,27 @@ le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachme ...@@ -51,23 +51,27 @@ le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachme
} }
LEPoint entryAnchor, exitAnchor; LEPoint entryAnchor, exitAnchor;
Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor); // TODO Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor);
Offset exitOffset = SWAPW(entryExitRecords[coverageIndex].exitAnchor); Offset exitOffset = SWAPW(entryExitRecords[coverageIndex].exitAnchor);
if (entryOffset != 0) { if (entryOffset != 0) {
const AnchorTable *entryAnchorTable = (const AnchorTable *) ((char *) this + entryOffset); LEReferenceTo<AnchorTable> entryAnchorTable(base, success, entryOffset);
entryAnchorTable->getAnchor(glyphID, fontInstance, entryAnchor); if( LE_SUCCESS(success) ) {
glyphIterator->setCursiveEntryPoint(entryAnchor); entryAnchorTable->getAnchor(entryAnchorTable, glyphID, fontInstance, entryAnchor, success);
glyphIterator->setCursiveEntryPoint(entryAnchor);
}
} else { } else {
//glyphIterator->clearCursiveEntryPoint(); //glyphIterator->clearCursiveEntryPoint();
} }
if (exitOffset != 0) { if (exitOffset != 0) {
const AnchorTable *exitAnchorTable = (const AnchorTable *) ((char *) this + exitOffset); LEReferenceTo<AnchorTable> exitAnchorTable(base, success, exitOffset);
exitAnchorTable->getAnchor(glyphID, fontInstance, exitAnchor); if( LE_SUCCESS(success) ) {
glyphIterator->setCursiveExitPoint(exitAnchor); exitAnchorTable->getAnchor(exitAnchorTable, glyphID, fontInstance, exitAnchor, success);
glyphIterator->setCursiveExitPoint(exitAnchor);
}
} else { } else {
//glyphIterator->clearCursiveExitPoint(); //glyphIterator->clearCursiveExitPoint();
} }
......
...@@ -43,7 +43,7 @@ const le_uint16 DeviceTable::fieldBits[] = { 2, 4, 8}; ...@@ -43,7 +43,7 @@ const le_uint16 DeviceTable::fieldBits[] = { 2, 4, 8};
#define FORMAT_COUNT LE_ARRAY_SIZE(fieldBits) #define FORMAT_COUNT LE_ARRAY_SIZE(fieldBits)
le_int16 DeviceTable::getAdjustment(le_uint16 ppem) const le_int16 DeviceTable::getAdjustment(const LEReferenceTo<DeviceTable>&base, le_uint16 ppem, LEErrorCode &success) const
{ {
le_uint16 start = SWAPW(startSize); le_uint16 start = SWAPW(startSize);
le_uint16 format = SWAPW(deltaFormat) - 1; le_uint16 format = SWAPW(deltaFormat) - 1;
...@@ -53,6 +53,13 @@ le_int16 DeviceTable::getAdjustment(le_uint16 ppem) const ...@@ -53,6 +53,13 @@ le_int16 DeviceTable::getAdjustment(le_uint16 ppem) const
le_uint16 sizeIndex = ppem - start; le_uint16 sizeIndex = ppem - start;
le_uint16 bits = fieldBits[format]; le_uint16 bits = fieldBits[format];
le_uint16 count = 16 / bits; le_uint16 count = 16 / bits;
LEReferenceToArrayOf<le_uint16> deltaValuesRef(base, success, deltaValues, (sizeIndex / count));
if(LE_FAILURE(success)) {
return result;
}
le_uint16 word = SWAPW(deltaValues[sizeIndex / count]); le_uint16 word = SWAPW(deltaValues[sizeIndex / count]);
le_uint16 fieldIndex = sizeIndex % count; le_uint16 fieldIndex = sizeIndex % count;
le_uint16 shift = 16 - (bits * (fieldIndex + 1)); le_uint16 shift = 16 - (bits * (fieldIndex + 1));
......
...@@ -50,7 +50,7 @@ struct DeviceTable ...@@ -50,7 +50,7 @@ struct DeviceTable
le_uint16 deltaFormat; le_uint16 deltaFormat;
le_uint16 deltaValues[ANY_NUMBER]; le_uint16 deltaValues[ANY_NUMBER];
le_int16 getAdjustment(le_uint16 ppem) const; le_int16 getAdjustment(const LEReferenceTo<DeviceTable> &base, le_uint16 ppem, LEErrorCode &success) const;
private: private:
static const le_uint16 fieldMasks[]; static const le_uint16 fieldMasks[];
......
...@@ -48,7 +48,6 @@ le_uint32 ExtensionSubtable::process(const LEReferenceTo<ExtensionSubtable> &thi ...@@ -48,7 +48,6 @@ le_uint32 ExtensionSubtable::process(const LEReferenceTo<ExtensionSubtable> &thi
const LookupProcessor *lookupProcessor, le_uint16 lookupType, const LookupProcessor *lookupProcessor, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return 0; return 0;
} }
......
...@@ -52,8 +52,7 @@ struct ExtensionSubtable //: GlyphSubstitutionSubtable ...@@ -52,8 +52,7 @@ struct ExtensionSubtable //: GlyphSubstitutionSubtable
le_uint16 extensionLookupType; le_uint16 extensionLookupType;
le_uint32 extensionOffset; le_uint32 extensionOffset;
le_uint32 process(const LEReferenceTo<ExtensionSubtable> &extRef, le_uint32 process(const LEReferenceTo<ExtensionSubtable> &base, const LookupProcessor *lookupProcessor, le_uint16 lookupType,
const LookupProcessor *lookupProcessor, le_uint16 lookupType,
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const; GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
}; };
......
...@@ -49,11 +49,11 @@ GDEFMarkFilter::~GDEFMarkFilter() ...@@ -49,11 +49,11 @@ GDEFMarkFilter::~GDEFMarkFilter()
// nothing to do? // nothing to do?
} }
le_bool GDEFMarkFilter::accept(LEGlyphID glyph) const le_bool GDEFMarkFilter::accept(LEGlyphID glyph, LEErrorCode &success) const
{ {
le_int32 glyphClass = classDefTable->getGlyphClass(glyph); le_int32 glyphClass = classDefTable->getGlyphClass(classDefTable, glyph, success);
return glyphClass == gcdMarkGlyph; return glyphClass == gcdMarkGlyph;
} }
U_NAMESPACE_END U_NAMESPACE_END
...@@ -55,7 +55,7 @@ public: ...@@ -55,7 +55,7 @@ public:
GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success); GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
virtual ~GDEFMarkFilter(); virtual ~GDEFMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const; virtual le_bool accept(LEGlyphID glyph, LEErrorCode &success) const;
}; };
U_NAMESPACE_END U_NAMESPACE_END
......
...@@ -41,14 +41,13 @@ ...@@ -41,14 +41,13 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags, GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader) FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader, LEErrorCode &success)
: direction(1), position(-1), nextLimit(-1), prevLimit(-1), : direction(1), position(-1), nextLimit(-1), prevLimit(-1),
glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments), glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0), srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
glyphClassDefinitionTable(), markAttachClassDefinitionTable() glyphClassDefinitionTable(), markAttachClassDefinitionTable()
{ {
LEErrorCode success = LE_NO_ERROR; // TODO
le_int32 glyphCount = glyphStorage.getGlyphCount(); le_int32 glyphCount = glyphStorage.getGlyphCount();
if (theGlyphDefinitionTableHeader.isValid()) { if (theGlyphDefinitionTableHeader.isValid()) {
...@@ -388,7 +387,7 @@ void GlyphIterator::setCursiveGlyph() ...@@ -388,7 +387,7 @@ void GlyphIterator::setCursiveGlyph()
void GlyphIterator::filterResetCache(void) { void GlyphIterator::filterResetCache(void) {
filterCacheValid = FALSE; filterCacheValid = FALSE;
} }
le_bool GlyphIterator::filterGlyph(le_uint32 index) le_bool GlyphIterator::filterGlyph(le_uint32 index)
{ {
...@@ -399,53 +398,53 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index) ...@@ -399,53 +398,53 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index)
le_bool &filterResult = filterCache.result; // NB: Making this a reference to accept the updated value, in case le_bool &filterResult = filterCache.result; // NB: Making this a reference to accept the updated value, in case
// we want more fancy cacheing in the future. // we want more fancy cacheing in the future.
if (LE_GET_GLYPH(glyphID) >= 0xFFFE) { if (LE_GET_GLYPH(glyphID) >= 0xFFFE) {
filterResult = TRUE; filterResult = TRUE;
} else { } else {
LEErrorCode success = LE_NO_ERROR; LEErrorCode success = LE_NO_ERROR;
le_int32 glyphClass = gcdNoGlyphClass; le_int32 glyphClass = gcdNoGlyphClass;
if (glyphClassDefinitionTable.isValid()) { if (glyphClassDefinitionTable.isValid()) {
glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success); glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);
} }
switch (glyphClass) { switch (glyphClass) {
case gcdNoGlyphClass: case gcdNoGlyphClass:
filterResult = FALSE; filterResult = FALSE;
break; break;
case gcdSimpleGlyph: case gcdSimpleGlyph:
filterResult = (lookupFlags & lfIgnoreBaseGlyphs) != 0; filterResult = (lookupFlags & lfIgnoreBaseGlyphs) != 0;
break; break;
case gcdLigatureGlyph: case gcdLigatureGlyph:
filterResult = (lookupFlags & lfIgnoreLigatures) != 0; filterResult = (lookupFlags & lfIgnoreLigatures) != 0;
break; break;
case gcdMarkGlyph: case gcdMarkGlyph:
if ((lookupFlags & lfIgnoreMarks) != 0) { if ((lookupFlags & lfIgnoreMarks) != 0) {
filterResult = TRUE; filterResult = TRUE;
} else { } else {
le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift; le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) { if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {
filterResult = (markAttachClassDefinitionTable filterResult = (markAttachClassDefinitionTable
-> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType); -> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType);
} else { } else {
filterResult = FALSE; filterResult = FALSE;
} }
} }
break; break;
case gcdComponentGlyph: case gcdComponentGlyph:
filterResult = ((lookupFlags & lfIgnoreBaseGlyphs) != 0); filterResult = ((lookupFlags & lfIgnoreBaseGlyphs) != 0);
break; break;
default: default:
filterResult = FALSE; filterResult = FALSE;
break; break;
} }
} }
filterCacheValid = TRUE; filterCacheValid = TRUE;
} }
return filterCache.result; return filterCache.result;
} }
......
...@@ -49,7 +49,7 @@ class GlyphPositionAdjustments; ...@@ -49,7 +49,7 @@ class GlyphPositionAdjustments;
class GlyphIterator : public UMemory { class GlyphIterator : public UMemory {
public: public:
GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags, GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader); FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader, LEErrorCode &success);
GlyphIterator(GlyphIterator &that); GlyphIterator(GlyphIterator &that);
......
...@@ -95,6 +95,8 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo ...@@ -95,6 +95,8 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo
le_uint32 delta = 0; le_uint32 delta = 0;
//_LETRACE("attempting lookupType #%d", lookupType);
switch(lookupType) switch(lookupType)
{ {
case 0: case 0:
...@@ -152,21 +154,21 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo ...@@ -152,21 +154,21 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo
{ {
LEReferenceTo<ContextualPositioningSubtable> subtable(lookupSubtable, success); LEReferenceTo<ContextualPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this , glyphIterator, fontInstance, success);
break; break;
} }
case gpstChainedContext: case gpstChainedContext:
{ {
LEReferenceTo<ChainingContextualPositioningSubtable> subtable(lookupSubtable, success); const LEReferenceTo<ChainingContextualPositioningSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this, glyphIterator, fontInstance, success);
break; break;
} }
case gpstExtension: case gpstExtension:
{ {
LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success); const LEReferenceTo<ExtensionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(subtable, this, lookupType, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this, lookupType, glyphIterator, fontInstance, success);
break; break;
...@@ -176,6 +178,12 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo ...@@ -176,6 +178,12 @@ le_uint32 GlyphPositioningLookupProcessor::applySubtable(const LEReferenceTo<Loo
break; break;
} }
#if LE_TRACE
if(delta != 0) {
_LETRACE("GlyphPositioningLookupProcessor applied #%d -> delta %d @ %d", lookupType, delta, glyphIterator->getCurrStreamPosition());
}
#endif
return delta; return delta;
} }
......
...@@ -123,7 +123,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<Lo ...@@ -123,7 +123,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<Lo
{ {
const LEReferenceTo<ContextualSubstitutionSubtable> subtable(lookupSubtable, success); const LEReferenceTo<ContextualSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this, glyphIterator, fontInstance, success);
break; break;
} }
...@@ -131,7 +131,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<Lo ...@@ -131,7 +131,7 @@ le_uint32 GlyphSubstitutionLookupProcessor::applySubtable(const LEReferenceTo<Lo
{ {
const LEReferenceTo<ChainingContextualSubstitutionSubtable> subtable(lookupSubtable, success); const LEReferenceTo<ChainingContextualSubstitutionSubtable> subtable(lookupSubtable, success);
delta = subtable->process(this, glyphIterator, fontInstance, success); delta = subtable->process(subtable, this, glyphIterator, fontInstance, success);
break; break;
} }
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include "LEGlyphStorage.h" #include "LEGlyphStorage.h"
#include "IndicReordering.h" #include "IndicReordering.h"
#include <stdio.h>
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicOpenTypeLayoutEngine) UOBJECT_DEFINE_RTTI_IMPLEMENTATION(IndicOpenTypeLayoutEngine)
...@@ -53,14 +53,14 @@ IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontI ...@@ -53,14 +53,14 @@ IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontI
le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success) le_int32 typoFlags, le_bool version2, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success), fMPreFixups(NULL) : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success), fMPreFixups(NULL)
{ {
if ( version2 ) { if ( version2 ) {
fFeatureMap = IndicReordering::getv2FeatureMap(fFeatureMapCount); fFeatureMap = IndicReordering::getv2FeatureMap(fFeatureMapCount);
} else { } else {
fFeatureMap = IndicReordering::getFeatureMap(fFeatureMapCount); fFeatureMap = IndicReordering::getFeatureMap(fFeatureMapCount);
} }
fFeatureOrder = TRUE; fFeatureOrder = TRUE;
fVersion2 = version2; fVersion2 = version2;
fFilterZeroWidth = IndicReordering::getFilterZeroWidth(fScriptCode); fFilterZeroWidth = IndicReordering::getFilterZeroWidth(fScriptCode);
} }
IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success) IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, le_int32 typoFlags, LEErrorCode &success)
...@@ -68,7 +68,7 @@ IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontI ...@@ -68,7 +68,7 @@ IndicOpenTypeLayoutEngine::IndicOpenTypeLayoutEngine(const LEFontInstance *fontI
{ {
fFeatureMap = IndicReordering::getFeatureMap(fFeatureMapCount); fFeatureMap = IndicReordering::getFeatureMap(fFeatureMapCount);
fFeatureOrder = TRUE; fFeatureOrder = TRUE;
fVersion2 = FALSE; fVersion2 = FALSE;
} }
IndicOpenTypeLayoutEngine::~IndicOpenTypeLayoutEngine() IndicOpenTypeLayoutEngine::~IndicOpenTypeLayoutEngine()
...@@ -90,6 +90,7 @@ le_int32 IndicOpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_ ...@@ -90,6 +90,7 @@ le_int32 IndicOpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_
return 0; return 0;
} }
_LETRACE("IOTLE::gp, calling parent");
le_int32 retCount = OpenTypeLayoutEngine::glyphProcessing(chars, offset, count, max, rightToLeft, glyphStorage, success); le_int32 retCount = OpenTypeLayoutEngine::glyphProcessing(chars, offset, count, max, rightToLeft, glyphStorage, success);
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
...@@ -97,11 +98,15 @@ le_int32 IndicOpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_ ...@@ -97,11 +98,15 @@ le_int32 IndicOpenTypeLayoutEngine::glyphProcessing(const LEUnicode chars[], le_
} }
if (fVersion2) { if (fVersion2) {
IndicReordering::finalReordering(glyphStorage,retCount); _LETRACE("IOTLE::gp, v2 final,");
IndicReordering::applyPresentationForms(glyphStorage,retCount); IndicReordering::finalReordering(glyphStorage,retCount);
OpenTypeLayoutEngine::glyphSubstitution(count,max, rightToLeft, glyphStorage, success); _LETRACE("IOTLE::gp, v2 pres");
IndicReordering::applyPresentationForms(glyphStorage,retCount);
_LETRACE("IOTLE::gp, parent gsub");
OpenTypeLayoutEngine::glyphSubstitution(count,max, rightToLeft, glyphStorage, success);
} else { } else {
IndicReordering::adjustMPres(fMPreFixups, glyphStorage, success); _LETRACE("IOTLE::gp, adjust mpres");
IndicReordering::adjustMPres(fMPreFixups, glyphStorage, success);
} }
return retCount; return retCount;
} }
...@@ -116,6 +121,8 @@ le_int32 IndicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], ...@@ -116,6 +121,8 @@ le_int32 IndicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[],
return 0; return 0;
} }
_LETRACE("IOTLE: charProc");
if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) { if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
success = LE_ILLEGAL_ARGUMENT_ERROR; success = LE_ILLEGAL_ARGUMENT_ERROR;
return 0; return 0;
...@@ -143,8 +150,10 @@ le_int32 IndicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], ...@@ -143,8 +150,10 @@ le_int32 IndicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[],
le_int32 outCharCount; le_int32 outCharCount;
if (fVersion2) { if (fVersion2) {
_LETRACE("v2process");
outCharCount = IndicReordering::v2process(&chars[offset], count, fScriptCode, outChars, glyphStorage); outCharCount = IndicReordering::v2process(&chars[offset], count, fScriptCode, outChars, glyphStorage);
} else { } else {
_LETRACE("reorder");
outCharCount = IndicReordering::reorder(&chars[offset], count, fScriptCode, outChars, glyphStorage, &fMPreFixups, success); outCharCount = IndicReordering::reorder(&chars[offset], count, fScriptCode, outChars, glyphStorage, &fMPreFixups, success);
} }
......
...@@ -254,8 +254,8 @@ public: ...@@ -254,8 +254,8 @@ public:
return fGlyphStorage.getAuxData(charIndex,success); return fGlyphStorage.getAuxData(charIndex,success);
} }
void decomposeReorderMatras ( const IndicClassTable *classTable, le_int32 beginSyllable, le_int32 nextSyllable, le_int32 inv_count ) { void decomposeReorderMatras ( const IndicClassTable *classTable, le_int32 beginSyllable, le_int32 nextSyllable, le_int32 inv_count ) {
le_int32 i; le_int32 i;
LEErrorCode success = LE_NO_ERROR; LEErrorCode success = LE_NO_ERROR;
for ( i = beginSyllable ; i < nextSyllable ; i++ ) { for ( i = beginSyllable ; i < nextSyllable ; i++ ) {
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include <stdio.h> #include <stdio.h>
#define DEBUG 0 #define DEBUG_KERN_TABLE 0
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
...@@ -99,14 +99,14 @@ KernTable::KernTable(const LETableReference& base, LEErrorCode &success) ...@@ -99,14 +99,14 @@ KernTable::KernTable(const LETableReference& base, LEErrorCode &success)
: pairsSwapped(NULL), fTable(base) : pairsSwapped(NULL), fTable(base)
{ {
if(LE_FAILURE(success) || (fTable.isEmpty())) { if(LE_FAILURE(success) || (fTable.isEmpty())) {
#if DEBUG #if DEBUG_KERN_TABLE
fprintf(stderr, "no kern data\n"); fprintf(stderr, "no kern data\n");
#endif #endif
return; return;
} }
LEReferenceTo<KernTableHeader> header(fTable, success); LEReferenceTo<KernTableHeader> header(fTable, success);
#if DEBUG #if DEBUG_KERN_TABLE
// dump first 32 bytes of header // dump first 32 bytes of header
for (int i = 0; i < 64; ++i) { for (int i = 0; i < 64; ++i) {
fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff); fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff);
...@@ -171,13 +171,13 @@ KernTable::KernTable(const LETableReference& base, LEErrorCode &success) ...@@ -171,13 +171,13 @@ KernTable::KernTable(const LETableReference& base, LEErrorCode &success)
fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift); fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift);
fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift)); fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift));
#endif #endif
#if DEBUG #if DEBUG_KERN_TABLE
fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairsSwapped); fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairsSwapped);
fprintf(stderr, fprintf(stderr,
" searchRange(pairs): %d entrySelector: %d rangeShift(pairs): %d\n", " searchRange(pairs): %d entrySelector: %d rangeShift(pairs): %d\n",
searchRange, entrySelector, rangeShift); searchRange, entrySelector, rangeShift);
{ if (LE_SUCCESS(success)) {
// dump part of the pair list // dump part of the pair list
char ids[256]; char ids[256];
for (int i = 256; --i >= 0;) { for (int i = 256; --i >= 0;) {
...@@ -242,7 +242,7 @@ void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success) ...@@ -242,7 +242,7 @@ void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success)
p = tp; p = tp;
} }
#if DEBUG #if DEBUG_KERN_TABLE
fprintf(stderr, "binary search for %0.8x\n", key); fprintf(stderr, "binary search for %0.8x\n", key);
#endif #endif
...@@ -251,13 +251,13 @@ void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success) ...@@ -251,13 +251,13 @@ void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success)
probe >>= 1; probe >>= 1;
tp = (const PairInfo*)(p + (probe/KERN_PAIRINFO_SIZE)); tp = (const PairInfo*)(p + (probe/KERN_PAIRINFO_SIZE));
le_uint32 tkey = tp->key; le_uint32 tkey = tp->key;
#if DEBUG #if DEBUG_KERN_TABLE
fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairsSwapped), tkey); fprintf(stdout, " %.3d (%0.8x)\n", (tp - pairsSwapped), tkey);
#endif #endif
if (tkey <= key) { if (tkey <= key) {
if (tkey == key) { if (tkey == key) {
le_int16 value = SWAPW(tp->value); le_int16 value = SWAPW(tp->value);
#if DEBUG #if DEBUG_KERN_TABLE
fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n", fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n",
storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value)); storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value));
fflush(stdout); fflush(stdout);
......
...@@ -181,6 +181,10 @@ public: ...@@ -181,6 +181,10 @@ public:
* *
* Subclasses which represent composite fonts should always return <code>NULL</code>. * Subclasses which represent composite fonts should always return <code>NULL</code>.
* *
* Note that implementing this function does not allow for range checking.
* Subclasses that desire the safety of range checking must implement the
* variation which has a length parameter.
*
* @param tableTag - the four byte table tag. (e.g. 'cmap') * @param tableTag - the four byte table tag. (e.g. 'cmap')
* *
* @return the address of the table in memory, or <code>NULL</code> * @return the address of the table in memory, or <code>NULL</code>
...@@ -200,6 +204,8 @@ public: ...@@ -200,6 +204,8 @@ public:
* Subclasses which represent composite fonts should always return <code>NULL</code>. * Subclasses which represent composite fonts should always return <code>NULL</code>.
* *
* This version sets a length, for range checking. * This version sets a length, for range checking.
* Note that range checking can only be accomplished if this function is
* implemented in subclasses.
* *
* @param tableTag - the four byte table tag. (e.g. 'cmap') * @param tableTag - the four byte table tag. (e.g. 'cmap')
* @param length - ignored on entry, on exit will be the length of the table if known, or -1 if unknown. * @param length - ignored on entry, on exit will be the length of the table if known, or -1 if unknown.
...@@ -572,5 +578,3 @@ inline le_int32 LEFontInstance::floatToFixed(float theFloat) ...@@ -572,5 +578,3 @@ inline le_int32 LEFontInstance::floatToFixed(float theFloat)
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
...@@ -62,7 +62,7 @@ public: ...@@ -62,7 +62,7 @@ public:
* *
* @internal * @internal
*/ */
virtual le_bool accept(LEGlyphID glyph) const = 0; virtual le_bool accept(LEGlyphID glyph, LEErrorCode &success) const = 0;
}; };
#endif /* U_HIDE_INTERNAL_API */ #endif /* U_HIDE_INTERNAL_API */
......
...@@ -458,7 +458,7 @@ void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorC ...@@ -458,7 +458,7 @@ void LEGlyphStorage::setPosition(le_int32 glyphIndex, float x, float y, LEErrorC
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
return; return;
} }
_LETRACE("set%-4d\t(%.2f, %.2f)", glyphIndex, x, y);
fPositions[glyphIndex * 2] = x; fPositions[glyphIndex * 2] = x;
fPositions[glyphIndex * 2 + 1] = y; fPositions[glyphIndex * 2 + 1] = y;
} }
...@@ -688,10 +688,9 @@ le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGl ...@@ -688,10 +688,9 @@ le_bool LEGlyphStorage::applyInsertion(le_int32 atPosition, le_int32 count, LEGl
// the source glyph we're pointing at // the source glyph we're pointing at
// just got replaced by the insertion // just got replaced by the insertion
fSrcIndex -= 1; fSrcIndex -= 1;
return FALSE; return FALSE;
} }
U_NAMESPACE_END U_NAMESPACE_END
...@@ -568,4 +568,3 @@ inline LEGlyphID &LEGlyphStorage::operator[](le_int32 glyphIndex) const ...@@ -568,4 +568,3 @@ inline LEGlyphID &LEGlyphStorage::operator[](le_int32 glyphIndex) const
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
* WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT UNLESS * WARNING: THIS FILE IS MACHINE GENERATED. DO NOT HAND EDIT IT UNLESS
* YOU REALLY KNOW WHAT YOU'RE DOING. * YOU REALLY KNOW WHAT YOU'RE DOING.
* *
* Generated on: 10/26/2010 02:53:33 PM PDT * Generated on: 11/01/2011 04:08:09 PM PDT
*/ */
#ifndef __LESCRIPTS_H #ifndef __LESCRIPTS_H
...@@ -262,7 +262,16 @@ enum ScriptCodes { ...@@ -262,7 +262,16 @@ enum ScriptCodes {
khojScriptCode = 157, khojScriptCode = 157,
tirhScriptCode = 158, tirhScriptCode = 158,
scriptCodeCount = 159 /**
* @stable ICU 52
*/
aghbScriptCode = 159,
mahjScriptCode = 160,
/**
* @stable ICU 2.2
*/
scriptCodeCount
}; };
U_NAMESPACE_END U_NAMESPACE_END
......
...@@ -132,6 +132,9 @@ enum LEErrorCode { ...@@ -132,6 +132,9 @@ enum LEErrorCode {
#define uprv_memcpy memcpy #define uprv_memcpy memcpy
#define uprv_realloc realloc #define uprv_realloc realloc
#define U_EXPORT2
#define U_CAPI extern "C"
#if !defined(U_IS_BIG_ENDIAN) #if !defined(U_IS_BIG_ENDIAN)
#ifdef _LITTLE_ENDIAN #ifdef _LITTLE_ENDIAN
#define U_IS_BIG_ENDIAN 0 #define U_IS_BIG_ENDIAN 0
......
...@@ -37,34 +37,47 @@ ...@@ -37,34 +37,47 @@
#include "LETypes.h" #include "LETypes.h"
#include "LEFontInstance.h" #include "LEFontInstance.h"
/**
* \def LE_ENABLE_RAW
* If this is 1, enables old non-safe raw access
*/
#ifndef LE_ENABLE_RAW
#define LE_ENABLE_RAW 0
#endif
#define kQuestionmarkTableTag 0x3F3F3F3FUL #define kQuestionmarkTableTag 0x3F3F3F3FUL /* ???? */
#define kTildeTableTag 0x7e7e7e7eUL #define kStaticTableTag 0x30303030UL /* 0000 */
#define kTildeTableTag 0x7e7e7e7eUL /* ~~~~ */
#ifdef __cplusplus #ifdef __cplusplus
// internal - interface for range checking // internal - interface for range checking
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
#if LE_ASSERT_BAD_FONT #if LE_ASSERT_BAD_FONT
#ifndef LE_TRACE_TR
#define LE_TRACE_TR 0
#endif
class LETableReference; // fwd class LETableReference; // fwd
/** /**
* defined in OpenTypeUtilities.cpp * defined in OpenTypeUtilities.cpp
* @internal * @internal
*/ */
extern void _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len); U_CAPI void U_EXPORT2 _debug_LETableReference(const char *f, int l, const char *msg, const LETableReference *what, const void *ptr, size_t len);
#define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0); #define LE_DEBUG_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
#define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z); #define LE_DEBUG_TR3(x,y,z) _debug_LETableReference(__FILE__, __LINE__, x, this, (const void*)y, (size_t)z);
#if 0 #if LE_TRACE_TR
#define LE_TRACE_TR(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0); #define _TRTRACE(x) _debug_LETableReference(__FILE__, __LINE__, x, this, NULL, 0);
#else #else
#define LE_TRACE_TR(x) #define _TRTRACE(x)
#endif #endif
#else #else
#define LE_DEBUG_TR(x) #define LE_DEBUG_TR(x)
#define LE_DEBUG_TR3(x,y,z) #define LE_DEBUG_TR3(x,y,z)
#define LE_TRACE_TR(x) #define _TRTRACE(x)
#endif #endif
/** /**
...@@ -72,6 +85,13 @@ extern void _debug_LETableReference(const char *f, int l, const char *msg, const ...@@ -72,6 +85,13 @@ extern void _debug_LETableReference(const char *f, int l, const char *msg, const
*/ */
class LETableReference { class LETableReference {
public: public:
/**
* Dummy enum asserting that a value is actually static data
* and does not need to be range checked
*/
enum EStaticData { kStaticData = 0 };
/** /**
* @internal * @internal
* Construct from a specific tag * Construct from a specific tag
...@@ -79,28 +99,42 @@ public: ...@@ -79,28 +99,42 @@ public:
LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) : LETableReference(const LEFontInstance* font, LETag tableTag, LEErrorCode &success) :
fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) { fFont(font), fTag(tableTag), fParent(NULL), fStart(NULL),fLength(LE_UINTPTR_MAX) {
loadTable(success); loadTable(success);
LE_TRACE_TR("INFO: new table load") _TRTRACE("INFO: new table load")
} }
LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) { LETableReference(const LETableReference &parent, LEErrorCode &success) : fFont(parent.fFont), fTag(parent.fTag), fParent(&parent), fStart(parent.fStart), fLength(parent.fLength) {
if(LE_FAILURE(success)) { if(LE_FAILURE(success)) {
clear(); clear();
} }
LE_TRACE_TR("INFO: new clone") _TRTRACE("INFO: new clone")
} }
#if LE_ENABLE_RAW
/**
* Construct without a parent LETR.
*/
LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) : LETableReference(const le_uint8* data, size_t length = LE_UINTPTR_MAX) :
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) { fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {
LE_TRACE_TR("INFO: new raw") _TRTRACE("INFO: new raw")
}
#endif
/**
* Construct without a parent LETR.
*/
LETableReference(EStaticData /* NOTUSED */, const le_uint8* data, size_t length) :
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(data), fLength(length) {
_TRTRACE("INFO: new EStaticData")
} }
LETableReference() : LETableReference() :
fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) { fFont(NULL), fTag(kQuestionmarkTableTag), fParent(NULL), fStart(NULL), fLength(0) {
LE_TRACE_TR("INFO: new empty") _TRTRACE("INFO: new empty")
} }
~LETableReference() { ~LETableReference() {
fTag=kTildeTableTag; fTag= (LETag)kTildeTableTag;
LE_TRACE_TR("INFO: new dtor") _TRTRACE("INFO: new dtor")
} }
/** /**
...@@ -126,7 +160,7 @@ public: ...@@ -126,7 +160,7 @@ public:
fLength = (fParent->fLength) - offset; // decrement length as base address is incremented fLength = (fParent->fLength) - offset; // decrement length as base address is incremented
} }
if(fLength != LE_UINTPTR_MAX) { // if we have bounds: if(fLength != LE_UINTPTR_MAX) { // if we have bounds:
if(offset+fLength > fParent->fLength) { if((offset+fLength < offset) || (offset+fLength > fParent->fLength)) {
LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength); LE_DEBUG_TR3("offset+fLength out of range: (%p) +%d", NULL, offset+fLength);
err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded err = LE_INDEX_OUT_OF_BOUNDS_ERROR; // exceeded
clear(); clear();
...@@ -136,11 +170,13 @@ public: ...@@ -136,11 +170,13 @@ public:
} else { } else {
clear(); clear();
} }
LE_TRACE_TR("INFO: new subset") _TRTRACE("INFO: new subset")
} }
const void* getAlias() const { return (const void*)fStart; } const void* getAlias() const { return (const void*)fStart; }
const void* getAliasTODO() const { LE_DEBUG_TR("getAliasTODO()"); return (const void*)fStart; } #ifndef LE_ENABLE_RAW
const void* getAliasRAW() const { LE_DEBUG_TR("getAliasRAW()"); return (const void*)fStart; }
#endif
le_bool isEmpty() const { return fStart==NULL || fLength==0; } le_bool isEmpty() const { return fStart==NULL || fLength==0; }
le_bool isValid() const { return !isEmpty(); } le_bool isValid() const { return !isEmpty(); }
le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; } le_bool hasBounds() const { return fLength!=LE_UINTPTR_MAX; }
...@@ -233,7 +269,18 @@ protected: ...@@ -233,7 +269,18 @@ protected:
void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) { void setRaw(const void *data, size_t length = LE_UINTPTR_MAX) {
fFont = NULL; fFont = NULL;
fTag = kQuestionmarkTableTag; fTag = (LETag)kQuestionmarkTableTag;
fParent = NULL;
fStart = (const le_uint8*)data;
fLength = length;
}
/**
* set this object pointing to static data
*/
void setTo(EStaticData /*notused*/, const void *data, size_t length) {
fFont = NULL;
fTag = (LETag)kStaticTableTag;
fParent = NULL; fParent = NULL;
fStart = (const le_uint8*)data; fStart = (const le_uint8*)data;
fLength = length; fLength = length;
...@@ -276,6 +323,90 @@ size_t LETableVarSizer<T>::getSize() { ...@@ -276,6 +323,90 @@ size_t LETableVarSizer<T>::getSize() {
* Open a new entry based on an existing table * Open a new entry based on an existing table
*/ */
template<class T>
class LEReferenceTo : public LETableReference {
public:
/**
* open a sub reference.
* @param parent parent reference
* @param success error status
* @param atPtr location of reference - if NULL, will be at offset zero (i.e. downcast of parent). Otherwise must be a pointer within parent's bounds.
*/
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)
: LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
/**
* ptr plus offset
*/
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)
: LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)
: LETableReference(parent, offset, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success)
: LETableReference(parent, 0, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)
: LETableReference(font, tableTag, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
#if LE_ENABLE_RAW
inline LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}
inline LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}
#endif
inline LEReferenceTo(EStaticData staticData, const le_uint8 *data, size_t length) : LETableReference(staticData, data, length) {}
inline LEReferenceTo(EStaticData staticData, const T *data, size_t length) : LETableReference(staticData, (const le_uint8*)data, length) {}
inline LEReferenceTo() : LETableReference() {}
#if LE_ENABLE_RAW
inline LEReferenceTo<T>& operator=(const T* other) {
setRaw(other);
return *this;
}
#endif
LEReferenceTo<T>& setTo(LETableReference::EStaticData staticData, const T* other, size_t length) {
LETableReference::setTo(staticData, other, length);
return *this;
}
LEReferenceTo<T> &reparent(const LETableReference &base) {
fParent = &base;
return *this;
}
/**
* roll forward by one <T> size.
* same as addOffset(LETableVarSizer<T>::getSize(),success)
*/
void addObject(LEErrorCode &success) {
addOffset(LETableVarSizer<T>::getSize(), success);
}
void addObject(size_t count, LEErrorCode &success) {
addOffset(LETableVarSizer<T>::getSize()*count, success);
}
const T *operator->() const { return getAlias(); }
const T *operator*() const { return getAlias(); }
const T *getAlias() const { return (const T*)fStart; }
#if LE_ENABLE_RAW
const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }
#endif
};
/** /**
* \def LE_UNBOUNDED_ARRAY * \def LE_UNBOUNDED_ARRAY
* define an array with no *known* bound. Will trim to available size. * define an array with no *known* bound. Will trim to available size.
...@@ -288,12 +419,12 @@ class LEReferenceToArrayOf : public LETableReference { ...@@ -288,12 +419,12 @@ class LEReferenceToArrayOf : public LETableReference {
public: public:
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count) LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, size_t offset, le_uint32 count)
: LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) { : LETableReference(parent, offset, LE_UINTPTR_MAX, success), fCount(count) {
LE_TRACE_TR("INFO: new RTAO by offset") _TRTRACE("INFO: new RTAO by offset")
if(LE_SUCCESS(success)) { if(LE_SUCCESS(success)) {
if(count == LE_UNBOUNDED_ARRAY) { // not a known length if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
} }
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success); LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*fCount, success);
} }
if(LE_FAILURE(success)) { if(LE_FAILURE(success)) {
fCount=0; fCount=0;
...@@ -303,23 +434,23 @@ public: ...@@ -303,23 +434,23 @@ public:
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count) LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, le_uint32 count)
: LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) { : LETableReference(parent, parent.ptrToOffset(array, success), LE_UINTPTR_MAX, success), fCount(count) {
LE_TRACE_TR("INFO: new RTAO") _TRTRACE("INFO: new RTAO")
if(LE_SUCCESS(success)) { if(LE_SUCCESS(success)) {
if(count == LE_UNBOUNDED_ARRAY) { // not a known length if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
} }
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success); LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*fCount, success);
} }
if(LE_FAILURE(success)) clear(); if(LE_FAILURE(success)) clear();
} }
LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count) LEReferenceToArrayOf(const LETableReference &parent, LEErrorCode &success, const T* array, size_t offset, le_uint32 count)
: LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) { : LETableReference(parent, parent.ptrToOffset(array, success)+offset, LE_UINTPTR_MAX, success), fCount(count) {
LE_TRACE_TR("INFO: new RTAO") _TRTRACE("INFO: new RTAO")
if(LE_SUCCESS(success)) { if(LE_SUCCESS(success)) {
if(count == LE_UNBOUNDED_ARRAY) { // not a known length if(fCount == LE_UNBOUNDED_ARRAY) { // not a known length
count = getLength()/LETableVarSizer<T>::getSize(); // fit to max size fCount = getLength()/LETableVarSizer<T>::getSize(); // fit to max size
} }
LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*count, success); LETableReference::verifyLength(0, LETableVarSizer<T>::getSize()*fCount, success);
} }
if(LE_FAILURE(success)) clear(); if(LE_FAILURE(success)) clear();
} }
...@@ -328,18 +459,40 @@ LE_TRACE_TR("INFO: new RTAO") ...@@ -328,18 +459,40 @@ LE_TRACE_TR("INFO: new RTAO")
le_uint32 getCount() const { return fCount; } le_uint32 getCount() const { return fCount; }
using LETableReference::getAlias; const T *getAlias() const { return (const T*)fStart; }
const T *getAlias(le_uint32 i, LEErrorCode &success) const { const T *getAlias(le_uint32 i, LEErrorCode &success) const {
return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success))); return ((const T*)(((const char*)getAlias())+getOffsetFor(i, success)));
} }
const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); return (const T*)fStart; } #ifndef LE_ENABLE_RAW
const T *getAliasRAW() const { LE_DEBUG_TR("getAliasRAW<>"); return (const T*)fStart; }
#endif
const T& getObject(le_uint32 i, LEErrorCode &success) const { const T& getObject(le_uint32 i, LEErrorCode &success) const {
return *getAlias(i,success); return *getAlias(i,success);
} }
/**
* by-value array accessor for integral types.
*/
const T operator[](le_uint32 i) const {
LEErrorCode success = LE_NO_ERROR;
const T *ret = getAlias(i, success);
if(LE_FAILURE(success) || ret==NULL) {
#if LE_ASSERT_BAD_FONT
LE_DEBUG_TR3("Range error, out of bounds? (%p) #%d", NULL, i);
#endif
return T(0); // will not work for all types.
}
return *ret;
}
const LEReferenceTo<T> getReference(le_uint32 i, LEErrorCode &success) const {
if(LE_FAILURE(success)) return LEReferenceTo<T>();
return LEReferenceTo<T>(*this, success, getAlias(i,success));
}
const T& operator()(le_uint32 i, LEErrorCode &success) const { const T& operator()(le_uint32 i, LEErrorCode &success) const {
return *getAlias(i,success); return *getAlias(i,success);
} }
...@@ -348,6 +501,7 @@ LE_TRACE_TR("INFO: new RTAO") ...@@ -348,6 +501,7 @@ LE_TRACE_TR("INFO: new RTAO")
if(LE_SUCCESS(success)&&i<getCount()) { if(LE_SUCCESS(success)&&i<getCount()) {
return LETableVarSizer<T>::getSize()*i; return LETableVarSizer<T>::getSize()*i;
} else { } else {
LE_DEBUG_TR3("getOffsetFor failed (%p) index=%d",NULL, i);
success = LE_INDEX_OUT_OF_BOUNDS_ERROR; success = LE_INDEX_OUT_OF_BOUNDS_ERROR;
} }
return 0; return 0;
...@@ -359,7 +513,7 @@ LE_TRACE_TR("INFO: new RTAO") ...@@ -359,7 +513,7 @@ LE_TRACE_TR("INFO: new RTAO")
} }
LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) { LEReferenceToArrayOf(const LETableReference& parent, LEErrorCode & success) : LETableReference(parent,0, LE_UINTPTR_MAX, success), fCount(0) {
LE_TRACE_TR("INFO: null RTAO") _TRTRACE("INFO: null RTAO")
} }
private: private:
...@@ -367,73 +521,11 @@ private: ...@@ -367,73 +521,11 @@ private:
}; };
template<class T>
class LEReferenceTo : public LETableReference {
public:
/**
* open a sub reference.
* @param parent parent reference
* @param success error status
* @param atPtr location of reference - if NULL, will be at offset zero (i.e. downcast of parent). Otherwise must be a pointer within parent's bounds.
*/
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr)
: LETableReference(parent, parent.ptrToOffset(atPtr, success), LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
/**
* ptr plus offset
*/
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, const void* atPtr, size_t offset)
: LETableReference(parent, parent.ptrToOffset(atPtr, success)+offset, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success, size_t offset)
: LETableReference(parent, offset, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const LETableReference &parent, LEErrorCode &success)
: LETableReference(parent, 0, LE_UINTPTR_MAX, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const LEFontInstance *font, LETag tableTag, LEErrorCode &success)
: LETableReference(font, tableTag, success) {
verifyLength(0, LETableVarSizer<T>::getSize(), success);
if(LE_FAILURE(success)) clear();
}
inline LEReferenceTo(const le_uint8 *data, size_t length = LE_UINTPTR_MAX) : LETableReference(data, length) {}
inline LEReferenceTo(const T *data, size_t length = LE_UINTPTR_MAX) : LETableReference((const le_uint8*)data, length) {}
inline LEReferenceTo() : LETableReference(NULL) {}
inline LEReferenceTo<T>& operator=(const T* other) {
setRaw(other);
return *this;
}
LEReferenceTo<T> &reparent(const LETableReference &base) {
fParent = &base;
return *this;
}
/**
* roll forward by one <T> size.
* same as addOffset(LETableVarSizer<T>::getSize(),success)
*/
void addObject(LEErrorCode &success) {
addOffset(LETableVarSizer<T>::getSize(), success);
}
void addObject(size_t count, LEErrorCode &success) {
addOffset(LETableVarSizer<T>::getSize()*count, success);
}
const T *operator->() const { return getAlias(); }
const T *getAlias() const { return (const T*)fStart; }
const T *getAliasTODO() const { LE_DEBUG_TR("getAliasTODO<>"); return (const T*)fStart; }
};
#ifdef _TRTRACE
#undef _TRTRACE
#endif
U_NAMESPACE_END U_NAMESPACE_END
......
...@@ -337,6 +337,20 @@ struct LEPoint ...@@ -337,6 +337,20 @@ struct LEPoint
typedef struct LEPoint LEPoint; typedef struct LEPoint LEPoint;
#endif #endif
/**
* \def LE_TRACE
* @internal
*/
#ifndef LE_TRACE
# define LE_TRACE 0
#endif
#if LE_TRACE
# include <stdio.h>
# define _LETRACE printf("\n%s:%d: LE: ", __FILE__, __LINE__),printf
#else
# define _LETRACE 0&&
#endif
#ifndef U_HIDE_INTERNAL_API #ifndef U_HIDE_INTERNAL_API
...@@ -553,7 +567,7 @@ enum LEFeatureTags { ...@@ -553,7 +567,7 @@ enum LEFeatureTags {
LE_CALT_FEATURE_TAG = 0x63616C74UL, /**< 'calt' */ LE_CALT_FEATURE_TAG = 0x63616C74UL, /**< 'calt' */
LE_CASE_FEATURE_TAG = 0x63617365UL, /**< 'case' */ LE_CASE_FEATURE_TAG = 0x63617365UL, /**< 'case' */
LE_CCMP_FEATURE_TAG = 0x63636D70UL, /**< 'ccmp' */ LE_CCMP_FEATURE_TAG = 0x63636D70UL, /**< 'ccmp' */
LE_CJCT_FEATURE_TAG = 0x636A6374UL, /**< 'cjct' */ LE_CJCT_FEATURE_TAG = 0x636A6374UL, /**< 'cjct' */
LE_CLIG_FEATURE_TAG = 0x636C6967UL, /**< 'clig' */ LE_CLIG_FEATURE_TAG = 0x636C6967UL, /**< 'clig' */
LE_CPSP_FEATURE_TAG = 0x63707370UL, /**< 'cpsp' */ LE_CPSP_FEATURE_TAG = 0x63707370UL, /**< 'cpsp' */
LE_CSWH_FEATURE_TAG = 0x63737768UL, /**< 'cswh' */ LE_CSWH_FEATURE_TAG = 0x63737768UL, /**< 'cswh' */
...@@ -701,6 +715,12 @@ enum LEFeatureENUMs { ...@@ -701,6 +715,12 @@ enum LEFeatureENUMs {
LE_FEATURE_ENUM_MAX = LE_CHAR_FILTER_FEATURE_ENUM LE_FEATURE_ENUM_MAX = LE_CHAR_FILTER_FEATURE_ENUM
}; };
/**
* Flags for typographic features.
* @internal
* @{
*/
#define LE_Kerning_FEATURE_FLAG (1 << LE_Kerning_FEATURE_ENUM) #define LE_Kerning_FEATURE_FLAG (1 << LE_Kerning_FEATURE_ENUM)
#define LE_Ligatures_FEATURE_FLAG (1 << LE_Ligatures_FEATURE_ENUM) #define LE_Ligatures_FEATURE_FLAG (1 << LE_Ligatures_FEATURE_ENUM)
#define LE_NoCanon_FEATURE_FLAG (1 << LE_NoCanon_FEATURE_ENUM) #define LE_NoCanon_FEATURE_FLAG (1 << LE_NoCanon_FEATURE_ENUM)
...@@ -727,6 +747,9 @@ enum LEFeatureENUMs { ...@@ -727,6 +747,9 @@ enum LEFeatureENUMs {
#define LE_SS07_FEATURE_FLAG (1 << LE_SS07_FEATURE_ENUM) #define LE_SS07_FEATURE_FLAG (1 << LE_SS07_FEATURE_ENUM)
#define LE_CHAR_FILTER_FEATURE_FLAG (1 << LE_CHAR_FILTER_FEATURE_ENUM) #define LE_CHAR_FILTER_FEATURE_FLAG (1 << LE_CHAR_FILTER_FEATURE_ENUM)
/**
* @}
*/
#define LE_DEFAULT_FEATURE_FLAG (LE_Kerning_FEATURE_FLAG | LE_Ligatures_FEATURE_FLAG) /**< default features */ #define LE_DEFAULT_FEATURE_FLAG (LE_Kerning_FEATURE_FLAG | LE_Ligatures_FEATURE_FLAG) /**< default features */
...@@ -768,7 +791,7 @@ typedef enum LEErrorCode LEErrorCode; ...@@ -768,7 +791,7 @@ typedef enum LEErrorCode LEErrorCode;
* *
* @stable ICU 2.4 * @stable ICU 2.4
*/ */
#ifndef LE_FAILURE #ifndef LE_SUCCESS
#define LE_SUCCESS(code) (U_SUCCESS((UErrorCode)code)) #define LE_SUCCESS(code) (U_SUCCESS((UErrorCode)code))
#endif #endif
...@@ -781,4 +804,4 @@ typedef enum LEErrorCode LEErrorCode; ...@@ -781,4 +804,4 @@ typedef enum LEErrorCode LEErrorCode;
#define LE_FAILURE(code) (U_FAILURE((UErrorCode)code)) #define LE_FAILURE(code) (U_FAILURE((UErrorCode)code))
#endif #endif
#endif /* __LETYPES_H */ #endif
...@@ -156,7 +156,7 @@ public: ...@@ -156,7 +156,7 @@ public:
CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success); CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
virtual ~CanonMarkFilter(); virtual ~CanonMarkFilter();
virtual le_bool accept(LEGlyphID glyph) const; virtual le_bool accept(LEGlyphID glyph, LEErrorCode &success) const;
}; };
CanonMarkFilter::CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success) CanonMarkFilter::CanonMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
...@@ -169,9 +169,8 @@ CanonMarkFilter::~CanonMarkFilter() ...@@ -169,9 +169,8 @@ CanonMarkFilter::~CanonMarkFilter()
// nothing to do? // nothing to do?
} }
le_bool CanonMarkFilter::accept(LEGlyphID glyph) const le_bool CanonMarkFilter::accept(LEGlyphID glyph, LEErrorCode &success) const
{ {
LEErrorCode success = LE_NO_ERROR;
le_int32 glyphClass = classDefTable->getGlyphClass(classDefTable, glyph, success); le_int32 glyphClass = classDefTable->getGlyphClass(classDefTable, glyph, success);
if(LE_FAILURE(success)) return false; if(LE_FAILURE(success)) return false;
return glyphClass != 0; return glyphClass != 0;
...@@ -207,7 +206,7 @@ LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance, ...@@ -207,7 +206,7 @@ LayoutEngine::LayoutEngine(const LEFontInstance *fontInstance,
fGlyphStorage = new LEGlyphStorage(); fGlyphStorage = new LEGlyphStorage();
if (fGlyphStorage == NULL) { if (fGlyphStorage == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
} }
} }
le_int32 LayoutEngine::getGlyphCount() const le_int32 LayoutEngine::getGlyphCount() const
...@@ -263,7 +262,9 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off ...@@ -263,7 +262,9 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
return count; return count;
} }
LEReferenceTo<GlyphSubstitutionTableHeader> canonGSUBTable((GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable); LEReferenceTo<GlyphSubstitutionTableHeader> canonGSUBTable(LETableReference::kStaticData,
(GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable,
CanonShaping::glyphSubstitutionTableLen);
LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode); LETag scriptTag = OpenTypeLayoutEngine::getScriptTag(fScriptCode);
LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode); LETag langSysTag = OpenTypeLayoutEngine::getLangSysTag(fLanguageCode);
le_int32 i, dir = 1, out = 0, outCharCount = count; le_int32 i, dir = 1, out = 0, outCharCount = count;
...@@ -300,7 +301,7 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off ...@@ -300,7 +301,7 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, fakeGlyphStorage); CanonShaping::reorderMarks(&chars[offset], count, rightToLeft, reordered, fakeGlyphStorage);
inChars = reordered; inChars = reordered;
} }
fakeGlyphStorage.allocateAuxData(success); fakeGlyphStorage.allocateAuxData(success);
...@@ -323,7 +324,8 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off ...@@ -323,7 +324,8 @@ le_int32 LayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 off
LE_DELETE_ARRAY(reordered); LE_DELETE_ARRAY(reordered);
} }
outCharCount = canonGSUBTable->process(canonGSUBTable, fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, (const GlyphDefinitionTableHeader*)NULL, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success); const LEReferenceTo<GlyphDefinitionTableHeader> noGDEF; // empty gdef header
outCharCount = canonGSUBTable->process(canonGSUBTable, fakeGlyphStorage, rightToLeft, scriptTag, langSysTag, noGDEF, substitutionFilter, canonFeatureMap, canonFeatureMapCount, FALSE, success);
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
delete substitutionFilter; delete substitutionFilter;
...@@ -403,10 +405,13 @@ void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y ...@@ -403,10 +405,13 @@ void LayoutEngine::positionGlyphs(LEGlyphStorage &glyphStorage, float x, float y
LEPoint advance; LEPoint advance;
glyphStorage.setPosition(i, x, y, success); glyphStorage.setPosition(i, x, y, success);
_LETRACE("g#%-4d (%.2f, %.2f)", i, x, y);
fFontInstance->getGlyphAdvance(glyphStorage[i], advance); fFontInstance->getGlyphAdvance(glyphStorage[i], advance);
x += advance.fX; x += advance.fX;
y += advance.fY; y += advance.fY;
} }
glyphStorage.setPosition(glyphCount, x, y, success); glyphStorage.setPosition(glyphCount, x, y, success);
...@@ -424,7 +429,7 @@ void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset ...@@ -424,7 +429,7 @@ void LayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset
return; return;
} }
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable((GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable, LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(LETableReference::kStaticData, (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable,
CanonShaping::glyphDefinitionTableLen); CanonShaping::glyphDefinitionTableLen);
CanonMarkFilter filter(gdefTable, success); CanonMarkFilter filter(gdefTable, success);
...@@ -464,9 +469,10 @@ void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter ...@@ -464,9 +469,10 @@ void LayoutEngine::adjustMarkGlyphs(LEGlyphStorage &glyphStorage, LEGlyphFilter
glyphStorage.getGlyphPosition(p + 1, next, ignore, success); glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
xAdvance = next - prev; xAdvance = next - prev;
_LETRACE("p#%d (%.2f,%.2f)", p, xAdvance, 0);
glyphStorage.adjustPosition(p, xAdjust, 0, success); glyphStorage.adjustPosition(p, xAdjust, 0, success);
if (markFilter->accept(glyphStorage[p])) { if (markFilter->accept(glyphStorage[p], success)) {
xAdjust -= xAdvance; xAdjust -= xAdvance;
} }
...@@ -506,9 +512,13 @@ void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount, ...@@ -506,9 +512,13 @@ void LayoutEngine::adjustMarkGlyphs(const LEUnicode chars[], le_int32 charCount,
glyphStorage.getGlyphPosition(p + 1, next, ignore, success); glyphStorage.getGlyphPosition(p + 1, next, ignore, success);
xAdvance = next - prev; xAdvance = next - prev;
_LETRACE("p#%d (%.2f,%.2f)", p, xAdvance, 0);
glyphStorage.adjustPosition(p, xAdjust, 0, success); glyphStorage.adjustPosition(p, xAdjust, 0, success);
if (markFilter->accept(chars[c])) { if (markFilter->accept(chars[c], success)) {
xAdjust -= xAdvance; xAdjust -= xAdvance;
} }
...@@ -662,8 +672,10 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan ...@@ -662,8 +672,10 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
break; break;
} }
} else { } else {
MorphTableHeader2 *morxTable = (MorphTableHeader2 *)fontInstance->getFontTable(morxTableTag); LEReferenceTo<MorphTableHeader2> morxTable(fontInstance, morxTableTag, success);
if (morxTable != NULL && SWAPL(morxTable->version)==0x00020000) { if (LE_SUCCESS(success) &&
morxTable.isValid() &&
SWAPL(morxTable->version)==0x00020000) {
result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success); result = new GXLayoutEngine2(fontInstance, scriptCode, languageCode, morxTable, typoFlags, success);
} else { } else {
LEReferenceTo<MorphTableHeader> mortTable(fontInstance, mortTableTag, success); LEReferenceTo<MorphTableHeader> mortTable(fontInstance, mortTableTag, success);
...@@ -686,21 +698,20 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan ...@@ -686,21 +698,20 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
break; break;
} }
case arabScriptCode: case arabScriptCode:
//case hebrScriptCode: result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
result = new UnicodeArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success); break;
break;
//case hebrScriptCode: //case hebrScriptCode:
// return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags); // return new HebrewOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags);
case thaiScriptCode: case thaiScriptCode:
result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success); result = new ThaiLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break; break;
case hangScriptCode: case hangScriptCode:
result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success); result = new HangulOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
break; break;
default: default:
result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success); result = new LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success);
...@@ -711,9 +722,9 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan ...@@ -711,9 +722,9 @@ LayoutEngine *LayoutEngine::layoutEngineFactory(const LEFontInstance *fontInstan
} }
if (result && LE_FAILURE(success)) { if (result && LE_FAILURE(success)) {
delete result; delete result;
result = NULL; result = NULL;
} }
if (result == NULL) { if (result == NULL) {
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
......
...@@ -156,8 +156,8 @@ protected: ...@@ -156,8 +156,8 @@ protected:
* @param fontInstance - the font for the text * @param fontInstance - the font for the text
* @param scriptCode - the script for the text * @param scriptCode - the script for the text
* @param languageCode - the language for the text * @param languageCode - the language for the text
* @param typoFlags - the typographic control flags for the text. Set bit 1 if kerning * @param typoFlags - the typographic control flags for the text (a bitfield). Use kTypoFlagKern
* is desired, set bit 2 if ligature formation is desired. Others are reserved. * if kerning is desired, kTypoFlagLiga if ligature formation is desired. Others are reserved.
* @param success - set to an error code if the operation fails * @param success - set to an error code if the operation fails
* *
* @see LEFontInstance * @see LEFontInstance
......
...@@ -105,7 +105,7 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp ...@@ -105,7 +105,7 @@ le_uint16 LigatureSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyp
LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY); LEReferenceToArrayOf<le_uint16> componentTable(stHeader, success, componentOffset, LE_UNBOUNDED_ARRAY);
if(LE_FAILURE(success)) { if(LE_FAILURE(success)) {
currGlyph+= dir; currGlyph+= dir;
return nextStateIndex; // get out! bad font return nextStateIndex; // get out! bad font
} }
do { do {
......
...@@ -49,14 +49,20 @@ le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -49,14 +49,20 @@ le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, Gl
return 0; return 0;
} }
if (coverageIndex >= 0) { LEReferenceToArrayOf<Offset> ligSetTableOffsetArrayRef(base, success, ligSetTableOffsetArray, SWAPW(ligSetCount));
if (coverageIndex >= 0 && LE_SUCCESS(success) && (le_uint32)coverageIndex < ligSetTableOffsetArrayRef.getCount()) {
Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]); Offset ligSetTableOffset = SWAPW(ligSetTableOffsetArray[coverageIndex]);
const LigatureSetTable *ligSetTable = (const LigatureSetTable *) ((char *) this + ligSetTableOffset); LEReferenceTo<LigatureSetTable> ligSetTable(base, success, ligSetTableOffset);
if( LE_FAILURE(success) ) { return 0; }
le_uint16 ligCount = SWAPW(ligSetTable->ligatureCount); le_uint16 ligCount = SWAPW(ligSetTable->ligatureCount);
for (le_uint16 lig = 0; lig < ligCount; lig += 1) { LEReferenceTo<Offset> ligatureTableOffsetArray(base, success, ligSetTable->ligatureTableOffsetArray, ligCount);
for (le_uint16 lig = 0; LE_SUCCESS(success) && lig < ligCount; lig += 1) {
Offset ligTableOffset = SWAPW(ligSetTable->ligatureTableOffsetArray[lig]); Offset ligTableOffset = SWAPW(ligSetTable->ligatureTableOffsetArray[lig]);
const LigatureTable *ligTable = (const LigatureTable *) ((char *)ligSetTable + ligTableOffset); LEReferenceTo<LigatureTable> ligTable(ligSetTable, success, ligTableOffset);
if(LE_FAILURE(success)) { return 0; }
le_uint16 compCount = SWAPW(ligTable->compCount) - 1; le_uint16 compCount = SWAPW(ligTable->compCount) - 1;
le_int32 startPosition = glyphIterator->getCurrStreamPosition(); le_int32 startPosition = glyphIterator->getCurrStreamPosition();
TTGlyphID ligGlyph = SWAPW(ligTable->ligGlyph); TTGlyphID ligGlyph = SWAPW(ligTable->ligGlyph);
...@@ -72,7 +78,7 @@ le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -72,7 +78,7 @@ le_uint32 LigatureSubstitutionSubtable::process(const LETableReference &base, Gl
} }
} }
if (comp == compCount && (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, ligGlyph)))) { if (comp == compCount && (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, ligGlyph), success))) {
GlyphIterator tempIterator(*glyphIterator); GlyphIterator tempIterator(*glyphIterator);
TTGlyphID deletedGlyph = tempIterator.ignoresMarks()? 0xFFFE : 0xFFFF; TTGlyphID deletedGlyph = tempIterator.ignoresMarks()? 0xFFFE : 0xFFFF;
......
...@@ -60,9 +60,11 @@ le_uint32 LookupProcessor::applyLookupTable(const LEReferenceTo<LookupTable> &lo ...@@ -60,9 +60,11 @@ le_uint32 LookupProcessor::applyLookupTable(const LEReferenceTo<LookupTable> &lo
LEReferenceTo<LookupSubtable> lookupSubtable = lookupTable->getLookupSubtable(lookupTable, subtable, success); LEReferenceTo<LookupSubtable> lookupSubtable = lookupTable->getLookupSubtable(lookupTable, subtable, success);
delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success); delta = applySubtable(lookupSubtable, lookupType, glyphIterator, fontInstance, success);
if (delta > 0 && LE_FAILURE(success)) {
if (delta > 0 || LE_FAILURE(success)) { #if LE_TRACE
return 1; _LETRACE("Posn #%d, type %X, applied subtable #%d/%d - %s\n", startPosition, lookupType, subtable, subtableCount, u_errorName((UErrorCode)success));
#endif
return 1;
} }
glyphIterator->setCurrStreamPosition(startPosition); glyphIterator->setCurrStreamPosition(startPosition);
...@@ -86,7 +88,7 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj ...@@ -86,7 +88,7 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj
} }
GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments, GlyphIterator glyphIterator(glyphStorage, glyphPositionAdjustments,
rightToLeft, 0, 0, glyphDefinitionTableHeader); rightToLeft, 0, 0, glyphDefinitionTableHeader, success);
le_int32 newGlyphCount = glyphCount; le_int32 newGlyphCount = glyphCount;
for (le_uint16 order = 0; order < lookupOrderCount && LE_SUCCESS(success); order += 1) { for (le_uint16 order = 0; order < lookupOrderCount && LE_SUCCESS(success); order += 1) {
...@@ -94,6 +96,7 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj ...@@ -94,6 +96,7 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj
FeatureMask selectMask = lookupSelectArray[lookup]; FeatureMask selectMask = lookupSelectArray[lookup];
if (selectMask != 0) { if (selectMask != 0) {
_LETRACE("Processing order#%d/%d", order, lookupOrderCount);
const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookup, success); const LEReferenceTo<LookupTable> lookupTable = lookupListTable->getLookupTable(lookupListTable, lookup, success);
if (!lookupTable.isValid() ||LE_FAILURE(success) ) { if (!lookupTable.isValid() ||LE_FAILURE(success) ) {
continue; continue;
...@@ -103,8 +106,11 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj ...@@ -103,8 +106,11 @@ le_int32 LookupProcessor::process(LEGlyphStorage &glyphStorage, GlyphPositionAdj
glyphIterator.reset(lookupFlags, selectMask); glyphIterator.reset(lookupFlags, selectMask);
while (glyphIterator.findFeatureTag()) { while (glyphIterator.findFeatureTag()) {
applyLookupTable(lookupTable, &glyphIterator, fontInstance, success); // TODO applyLookupTable(lookupTable, &glyphIterator, fontInstance, success);
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
#if LE_TRACE
_LETRACE("Failure for lookup 0x%x - %s\n", lookup, u_errorName((UErrorCode)success));
#endif
return 0; return 0;
} }
} }
...@@ -138,7 +144,7 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt ...@@ -138,7 +144,7 @@ le_uint32 LookupProcessor::applySingleLookup(le_uint16 lookupTableIndex, GlyphIt
le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success) le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featureTable, FeatureMask featureMask, le_int32 order, LEErrorCode &success)
{ {
le_uint16 lookupCount = featureTable.isValid()? SWAPW(featureTable->lookupCount) : 0; le_uint16 lookupCount = featureTable.isValid()? SWAPW(featureTable->lookupCount) : 0;
le_int32 store = order; le_uint32 store = (le_uint32)order;
LEReferenceToArrayOf<le_uint16> lookupListIndexArray(featureTable, success, featureTable->lookupListIndexArray, lookupCount); LEReferenceToArrayOf<le_uint16> lookupListIndexArray(featureTable, success, featureTable->lookupListIndexArray, lookupCount);
...@@ -147,6 +153,9 @@ le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featu ...@@ -147,6 +153,9 @@ le_int32 LookupProcessor::selectLookups(const LEReferenceTo<FeatureTable> &featu
if (lookupListIndex >= lookupSelectCount) { if (lookupListIndex >= lookupSelectCount) {
continue; continue;
} }
if (store >= lookupOrderCount) {
continue;
}
lookupSelectArray[lookupListIndex] |= featureMask; lookupSelectArray[lookupListIndex] |= featureMask;
lookupOrderArray[store++] = lookupListIndex; lookupOrderArray[store++] = lookupListIndex;
...@@ -246,7 +255,7 @@ LookupProcessor::LookupProcessor(const LETableReference &baseAddress, ...@@ -246,7 +255,7 @@ LookupProcessor::LookupProcessor(const LETableReference &baseAddress,
if (requiredFeatureIndex != 0xFFFF) { if (requiredFeatureIndex != 0xFFFF) {
requiredFeatureTable = featureListTable->getFeatureTable(featureListTable, requiredFeatureIndex, &requiredFeatureTag, success); requiredFeatureTable = featureListTable->getFeatureTable(featureListTable, requiredFeatureIndex, &requiredFeatureTag, success);
featureReferences += SWAPW(featureTable->lookupCount); featureReferences += SWAPW(requiredFeatureTable->lookupCount);
} }
lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences); lookupOrderArray = LE_NEW_ARRAY(le_uint16, featureReferences);
...@@ -254,6 +263,7 @@ LookupProcessor::LookupProcessor(const LETableReference &baseAddress, ...@@ -254,6 +263,7 @@ LookupProcessor::LookupProcessor(const LETableReference &baseAddress,
success = LE_MEMORY_ALLOCATION_ERROR; success = LE_MEMORY_ALLOCATION_ERROR;
return; return;
} }
lookupOrderCount = featureReferences;
for (le_int32 f = 0; f < featureMapCount; f += 1) { for (le_int32 f = 0; f < featureMapCount; f += 1) {
FeatureMap fm = featureMap[f]; FeatureMap fm = featureMap[f];
......
...@@ -65,7 +65,7 @@ le_int32 LookupSubtable::getGlyphCoverage(const LEReferenceTo<LookupSubtable> &b ...@@ -65,7 +65,7 @@ le_int32 LookupSubtable::getGlyphCoverage(const LEReferenceTo<LookupSubtable> &b
if(LE_FAILURE(success)) return 0; if(LE_FAILURE(success)) return 0;
return coverageTable->getGlyphCoverage(glyphID); return coverageTable->getGlyphCoverage(coverageTable, glyphID, success);
} }
U_NAMESPACE_END U_NAMESPACE_END
...@@ -38,20 +38,28 @@ ...@@ -38,20 +38,28 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
le_int32 MarkArray::getMarkClass(LEGlyphID glyphID, le_int32 coverageIndex, const LEFontInstance *fontInstance, le_int32 MarkArray::getMarkClass(const LETableReference &base, LEGlyphID glyphID,
LEPoint &anchor) const le_int32 coverageIndex, const LEFontInstance *fontInstance,
LEPoint &anchor, LEErrorCode &success) const
{ {
le_int32 markClass = -1; le_int32 markClass = -1;
if (coverageIndex >= 0) { if ( coverageIndex >= 0 && LE_SUCCESS(success) ) {
le_uint16 mCount = SWAPW(markCount); le_uint16 mCount = SWAPW(markCount);
if (coverageIndex < mCount) { if (coverageIndex < mCount) {
LEReferenceToArrayOf<MarkRecord> markRecordArrayRef(base, success, markRecordArray, mCount);
if(LE_FAILURE(success)) {
return markClass;
}
const MarkRecord *markRecord = &markRecordArray[coverageIndex]; const MarkRecord *markRecord = &markRecordArray[coverageIndex];
Offset anchorTableOffset = SWAPW(markRecord->markAnchorTableOffset); Offset anchorTableOffset = SWAPW(markRecord->markAnchorTableOffset);
const AnchorTable *anchorTable = (AnchorTable *) ((char *) this + anchorTableOffset); LEReferenceTo<AnchorTable> anchorTable(base, success, anchorTableOffset);
if(LE_FAILURE(success)) {
return markClass;
}
anchorTable->getAnchor(glyphID, fontInstance, anchor); anchorTable->getAnchor(anchorTable, glyphID, fontInstance, anchor, success);
markClass = SWAPW(markRecord->markClass); markClass = SWAPW(markRecord->markClass);
} }
......
...@@ -54,8 +54,9 @@ struct MarkArray ...@@ -54,8 +54,9 @@ struct MarkArray
le_uint16 markCount; le_uint16 markCount;
MarkRecord markRecordArray[ANY_NUMBER]; MarkRecord markRecordArray[ANY_NUMBER];
le_int32 getMarkClass(LEGlyphID glyphID, le_int32 coverageIndex, const LEFontInstance *fontInstance, le_int32 getMarkClass(const LETableReference &base, LEGlyphID glyphID,
LEPoint &anchor) const; le_int32 coverageIndex, const LEFontInstance *fontInstance,
LEPoint &anchor, LEErrorCode &success) const;
}; };
LE_VAR_ARRAY(MarkArray, markRecordArray) LE_VAR_ARRAY(MarkArray, markRecordArray)
......
...@@ -66,11 +66,11 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl ...@@ -66,11 +66,11 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
} }
LEPoint markAnchor; LEPoint markAnchor;
const MarkArray *markArray = (const MarkArray *) ((char *) this + SWAPW(markArrayOffset)); LEReferenceTo<MarkArray> markArray(base, success, (const MarkArray *) ((char *) this + SWAPW(markArrayOffset)));
le_int32 markClass = markArray->getMarkClass(markGlyph, markCoverage, fontInstance, markAnchor); le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success);
le_uint16 mcCount = SWAPW(classCount); le_uint16 mcCount = SWAPW(classCount);
if (markClass < 0 || markClass >= mcCount) { if (markClass < 0 || markClass >= mcCount || LE_FAILURE(success)) {
// markGlyph isn't in the mark array or its // markGlyph isn't in the mark array or its
// mark class is too big. The table is mal-formed! // mark class is too big. The table is mal-formed!
return 0; return 0;
...@@ -80,7 +80,8 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl ...@@ -80,7 +80,8 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
GlyphIterator baseIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreLigatures*/)); GlyphIterator baseIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreLigatures*/));
LEGlyphID baseGlyph = findBaseGlyph(&baseIterator); LEGlyphID baseGlyph = findBaseGlyph(&baseIterator);
le_int32 baseCoverage = getBaseCoverage(base, (LEGlyphID) baseGlyph, success); le_int32 baseCoverage = getBaseCoverage(base, (LEGlyphID) baseGlyph, success);
const BaseArray *baseArray = (const BaseArray *) ((char *) this + SWAPW(baseArrayOffset)); LEReferenceTo<BaseArray> baseArray(base, success, (const BaseArray *) ((char *) this + SWAPW(baseArrayOffset)));
if(LE_FAILURE(success)) return 0;
le_uint16 baseCount = SWAPW(baseArray->baseRecordCount); le_uint16 baseCount = SWAPW(baseArray->baseRecordCount);
if (baseCoverage < 0 || baseCoverage >= baseCount) { if (baseCoverage < 0 || baseCoverage >= baseCount) {
...@@ -89,19 +90,23 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl ...@@ -89,19 +90,23 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
// table is mal-formed... // table is mal-formed...
return 0; return 0;
} }
LEReferenceTo<BaseRecord> baseRecord(base, success, &baseArray->baseRecordArray[baseCoverage * mcCount]);
if( LE_FAILURE(success) ) { return 0; }
LEReferenceToArrayOf<Offset> baseAnchorTableOffsetArray(base, success, &(baseRecord->baseAnchorTableOffsetArray[0]), markClass+1);
const BaseRecord *baseRecord = &baseArray->baseRecordArray[baseCoverage * mcCount]; if( LE_FAILURE(success) ) { return 0; }
Offset anchorTableOffset = SWAPW(baseRecord->baseAnchorTableOffsetArray[markClass]); Offset anchorTableOffset = SWAPW(baseRecord->baseAnchorTableOffsetArray[markClass]);
const AnchorTable *anchorTable = (const AnchorTable *) ((char *) baseArray + anchorTableOffset); if (anchorTableOffset <= 0) {
LEPoint baseAnchor, markAdvance, pixels;
if (anchorTableOffset == 0) {
// this means the table is mal-formed... // this means the table is mal-formed...
glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition()); glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition());
return 0; return 0;
} }
anchorTable->getAnchor(baseGlyph, fontInstance, baseAnchor); LEReferenceTo<AnchorTable> anchorTable(baseArray, success, anchorTableOffset);
LEPoint baseAnchor, markAdvance, pixels;
anchorTable->getAnchor(anchorTable, baseGlyph, fontInstance, baseAnchor, success);
fontInstance->getGlyphAdvance(markGlyph, pixels); fontInstance->getGlyphAdvance(markGlyph, pixels);
fontInstance->pixelsToUnits(pixels, markAdvance); fontInstance->pixelsToUnits(pixels, markAdvance);
...@@ -109,6 +114,8 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl ...@@ -109,6 +114,8 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
float anchorDiffX = baseAnchor.fX - markAnchor.fX; float anchorDiffX = baseAnchor.fX - markAnchor.fX;
float anchorDiffY = baseAnchor.fY - markAnchor.fY; float anchorDiffY = baseAnchor.fY - markAnchor.fY;
_LETRACE("Offset: (%.2f, %.2f) glyph 0x%X", anchorDiffX, anchorDiffY, markGlyph);
glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition()); glyphIterator->setCurrGlyphBaseOffset(baseIterator.getCurrStreamPosition());
if (glyphIterator->isRightToLeft()) { if (glyphIterator->isRightToLeft()) {
...@@ -132,7 +139,6 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl ...@@ -132,7 +139,6 @@ le_int32 MarkToBasePositioningSubtable::process(const LETableReference &base, Gl
gi.next(); gi.next();
} }
// end of JK patch // end of JK patch
fontInstance->pixelsToUnits(pixels, baseAdvance); fontInstance->pixelsToUnits(pixels, baseAdvance);
glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - baseAdvance.fX, anchorDiffY - baseAdvance.fY, -markAdvance.fX, -markAdvance.fY); glyphIterator->setCurrGlyphPositionAdjustment(anchorDiffX - baseAdvance.fX, anchorDiffY - baseAdvance.fY, -markAdvance.fX, -markAdvance.fY);
......
...@@ -65,8 +65,11 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base ...@@ -65,8 +65,11 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base
} }
LEPoint markAnchor; LEPoint markAnchor;
const MarkArray *markArray = (const MarkArray *) ((char *) this + SWAPW(markArrayOffset)); LEReferenceTo<MarkArray> markArray(base, success, SWAPW(markArrayOffset));
le_int32 markClass = markArray->getMarkClass(markGlyph, markCoverage, fontInstance, markAnchor); if( LE_FAILURE(success) ) {
return 0;
}
le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success);
le_uint16 mcCount = SWAPW(classCount); le_uint16 mcCount = SWAPW(classCount);
if (markClass < 0 || markClass >= mcCount) { if (markClass < 0 || markClass >= mcCount) {
...@@ -79,7 +82,7 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base ...@@ -79,7 +82,7 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base
GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/)); GlyphIterator ligatureIterator(*glyphIterator, (le_uint16) (lfIgnoreMarks /*| lfIgnoreBaseGlyphs*/));
LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator); LEGlyphID ligatureGlyph = findLigatureGlyph(&ligatureIterator);
le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success); le_int32 ligatureCoverage = getBaseCoverage(base, (LEGlyphID) ligatureGlyph, success);
const LigatureArray *ligatureArray = (const LigatureArray *) ((char *) this + SWAPW(baseArrayOffset)); LEReferenceTo<LigatureArray> ligatureArray(base, success, SWAPW(baseArrayOffset));
le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount); le_uint16 ligatureCount = SWAPW(ligatureArray->ligatureCount);
if (ligatureCoverage < 0 || ligatureCoverage >= ligatureCount) { if (ligatureCoverage < 0 || ligatureCoverage >= ligatureCount) {
...@@ -91,7 +94,7 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base ...@@ -91,7 +94,7 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base
le_int32 markPosition = glyphIterator->getCurrStreamPosition(); le_int32 markPosition = glyphIterator->getCurrStreamPosition();
Offset ligatureAttachOffset = SWAPW(ligatureArray->ligatureAttachTableOffsetArray[ligatureCoverage]); Offset ligatureAttachOffset = SWAPW(ligatureArray->ligatureAttachTableOffsetArray[ligatureCoverage]);
const LigatureAttachTable *ligatureAttachTable = (const LigatureAttachTable *) ((char *) ligatureArray + ligatureAttachOffset); LEReferenceTo<LigatureAttachTable> ligatureAttachTable(ligatureArray, success, ligatureAttachOffset);
le_int32 componentCount = SWAPW(ligatureAttachTable->componentCount); le_int32 componentCount = SWAPW(ligatureAttachTable->componentCount);
le_int32 component = ligatureIterator.getMarkComponent(markPosition); le_int32 component = ligatureIterator.getMarkComponent(markPosition);
...@@ -100,12 +103,14 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base ...@@ -100,12 +103,14 @@ le_int32 MarkToLigaturePositioningSubtable::process(const LETableReference &base
component = componentCount - 1; component = componentCount - 1;
} }
const ComponentRecord *componentRecord = &ligatureAttachTable->componentRecordArray[component * mcCount]; LEReferenceTo<ComponentRecord> componentRecord(base, success, &ligatureAttachTable->componentRecordArray[component * mcCount]);
LEReferenceToArrayOf<Offset> ligatureAnchorTableOffsetArray(base, success, &(componentRecord->ligatureAnchorTableOffsetArray[0]), markClass+1);
if( LE_FAILURE(success) ) { return 0; }
Offset anchorTableOffset = SWAPW(componentRecord->ligatureAnchorTableOffsetArray[markClass]); Offset anchorTableOffset = SWAPW(componentRecord->ligatureAnchorTableOffsetArray[markClass]);
const AnchorTable *anchorTable = (const AnchorTable *) ((char *) ligatureAttachTable + anchorTableOffset); LEReferenceTo<AnchorTable> anchorTable(ligatureAttachTable, success, anchorTableOffset);
LEPoint ligatureAnchor, markAdvance, pixels; LEPoint ligatureAnchor, markAdvance, pixels;
anchorTable->getAnchor(ligatureGlyph, fontInstance, ligatureAnchor); anchorTable->getAnchor(anchorTable, ligatureGlyph, fontInstance, ligatureAnchor, success);
fontInstance->getGlyphAdvance(markGlyph, pixels); fontInstance->getGlyphAdvance(markGlyph, pixels);
fontInstance->pixelsToUnits(pixels, markAdvance); fontInstance->pixelsToUnits(pixels, markAdvance);
......
...@@ -66,8 +66,11 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl ...@@ -66,8 +66,11 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
} }
LEPoint markAnchor; LEPoint markAnchor;
const MarkArray *markArray = (const MarkArray *) ((char *) this + SWAPW(markArrayOffset)); LEReferenceTo<MarkArray> markArray(base, success, SWAPW(markArrayOffset));
le_int32 markClass = markArray->getMarkClass(markGlyph, markCoverage, fontInstance, markAnchor); if(LE_FAILURE(success)) {
return 0;
}
le_int32 markClass = markArray->getMarkClass(markArray, markGlyph, markCoverage, fontInstance, markAnchor, success);
le_uint16 mcCount = SWAPW(classCount); le_uint16 mcCount = SWAPW(classCount);
if (markClass < 0 || markClass >= mcCount) { if (markClass < 0 || markClass >= mcCount) {
...@@ -79,7 +82,8 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl ...@@ -79,7 +82,8 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
GlyphIterator mark2Iterator(*glyphIterator); GlyphIterator mark2Iterator(*glyphIterator);
LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator); LEGlyphID mark2Glyph = findMark2Glyph(&mark2Iterator);
le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success); le_int32 mark2Coverage = getBaseCoverage(base, (LEGlyphID) mark2Glyph, success);
const Mark2Array *mark2Array = (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset)); LEReferenceTo<Mark2Array> mark2Array(base, success, (const Mark2Array *) ((char *) this + SWAPW(baseArrayOffset)));
if(LE_FAILURE(success)) return 0;
le_uint16 mark2Count = SWAPW(mark2Array->mark2RecordCount); le_uint16 mark2Count = SWAPW(mark2Array->mark2RecordCount);
if (mark2Coverage < 0 || mark2Coverage >= mark2Count) { if (mark2Coverage < 0 || mark2Coverage >= mark2Count) {
...@@ -89,9 +93,11 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl ...@@ -89,9 +93,11 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
return 0; return 0;
} }
const Mark2Record *mark2Record = &mark2Array->mark2RecordArray[mark2Coverage * mcCount]; LEReferenceTo<Mark2Record> mark2Record(base, success, &mark2Array->mark2RecordArray[mark2Coverage * mcCount]);
if(LE_FAILURE(success)) return 0;
Offset anchorTableOffset = SWAPW(mark2Record->mark2AnchorTableOffsetArray[markClass]); Offset anchorTableOffset = SWAPW(mark2Record->mark2AnchorTableOffsetArray[markClass]);
const AnchorTable *anchorTable = (const AnchorTable *) ((char *) mark2Array + anchorTableOffset); LEReferenceTo<AnchorTable> anchorTable(mark2Array, success, anchorTableOffset);
if(LE_FAILURE(success)) return 0;
LEPoint mark2Anchor, markAdvance, pixels; LEPoint mark2Anchor, markAdvance, pixels;
if (anchorTableOffset == 0) { if (anchorTableOffset == 0) {
...@@ -99,7 +105,7 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl ...@@ -99,7 +105,7 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
return 0; return 0;
} }
anchorTable->getAnchor(mark2Glyph, fontInstance, mark2Anchor); anchorTable->getAnchor(anchorTable, mark2Glyph, fontInstance, mark2Anchor, success);
fontInstance->getGlyphAdvance(markGlyph, pixels); fontInstance->getGlyphAdvance(markGlyph, pixels);
fontInstance->pixelsToUnits(pixels, markAdvance); fontInstance->pixelsToUnits(pixels, markAdvance);
...@@ -107,6 +113,8 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl ...@@ -107,6 +113,8 @@ le_int32 MarkToMarkPositioningSubtable::process(const LETableReference &base, Gl
float anchorDiffX = mark2Anchor.fX - markAnchor.fX; float anchorDiffX = mark2Anchor.fX - markAnchor.fX;
float anchorDiffY = mark2Anchor.fY - markAnchor.fY; float anchorDiffY = mark2Anchor.fY - markAnchor.fY;
_LETRACE("Offset: (%.2f, %.2f) glyph 0x%X mark2 0x%X", anchorDiffX, anchorDiffY, markGlyph, mark2Glyph);
glyphIterator->setCurrGlyphBaseOffset(mark2Iterator.getCurrStreamPosition()); glyphIterator->setCurrGlyphBaseOffset(mark2Iterator.getCurrStreamPosition());
if (glyphIterator->isRightToLeft()) { if (glyphIterator->isRightToLeft()) {
......
...@@ -54,9 +54,10 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -54,9 +54,10 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl
// FIXME: is this always the right thing to do? // FIXME: is this always the right thing to do?
// FIXME: should this only be done for a non-zero // FIXME: should this only be done for a non-zero
// glyphCount? // glyphCount?
if (filter != NULL && filter->accept(glyph)) { if (filter != NULL && filter->accept(glyph, success)) {
return 0; return 0;
} }
if(LE_FAILURE(success)) return 0;
le_int32 coverageIndex = getGlyphCoverage(base, glyph, success); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
le_uint16 seqCount = SWAPW(sequenceCount); le_uint16 seqCount = SWAPW(sequenceCount);
...@@ -67,7 +68,7 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -67,7 +68,7 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl
if (coverageIndex >= 0 && coverageIndex < seqCount) { if (coverageIndex >= 0 && coverageIndex < seqCount) {
Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]); Offset sequenceTableOffset = SWAPW(sequenceTableOffsetArray[coverageIndex]);
const SequenceTable *sequenceTable = (const SequenceTable *) ((char *) this + sequenceTableOffset); LEReferenceTo<SequenceTable> sequenceTable(base, success, sequenceTableOffset);
le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount); le_uint16 glyphCount = SWAPW(sequenceTable->glyphCount);
if (glyphCount == 0) { if (glyphCount == 0) {
...@@ -76,7 +77,7 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -76,7 +77,7 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl
} else if (glyphCount == 1) { } else if (glyphCount == 1) {
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]); TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[0]);
if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute))) { if (filter != NULL && ! filter->accept(LE_SET_GLYPH(glyph, substitute), success)) {
return 0; return 0;
} }
...@@ -89,7 +90,7 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl ...@@ -89,7 +90,7 @@ le_uint32 MultipleSubstitutionSubtable::process(const LETableReference &base, Gl
for (le_int32 i = 0; i < glyphCount; i += 1) { for (le_int32 i = 0; i < glyphCount; i += 1) {
TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]); TTGlyphID substitute = SWAPW(sequenceTable->substituteArray[i]);
if (! filter->accept(substitute)) { if (! filter->accept(substitute, success)) {
return 0; return 0;
} }
} }
......
...@@ -470,6 +470,7 @@ le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 o ...@@ -470,6 +470,7 @@ le_int32 OpenTypeLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 o
void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse, void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
LEGlyphStorage &glyphStorage, LEErrorCode &success) LEGlyphStorage &glyphStorage, LEErrorCode &success)
{ {
_LETRACE("OTLE::adjustGPOS");
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return; return;
} }
...@@ -510,14 +511,17 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 ...@@ -510,14 +511,17 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
if (!fGPOSTable.isEmpty()) { if (!fGPOSTable.isEmpty()) {
if (fScriptTagV2 != nullScriptTag && if (fScriptTagV2 != nullScriptTag &&
fGPOSTable->coversScriptAndLanguage(fGPOSTable, fScriptTagV2,fLangSysTag,success)) { fGPOSTable->coversScriptAndLanguage(fGPOSTable, fScriptTagV2,fLangSysTag,success)) {
_LETRACE("OTLE::process [0]");
fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag, fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTagV2, fLangSysTag,
fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder); fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder);
} else { } else {
_LETRACE("OTLE::process [1]");
fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag, fGPOSTable->process(fGPOSTable, glyphStorage, adjustments, reverse, fScriptTag, fLangSysTag,
fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder); fGDEFTable, success, fFontInstance, fFeatureMap, fFeatureMapCount, fFeatureOrder);
} }
} else if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */ } else if (fTypoFlags & LE_Kerning_FEATURE_FLAG) { /* kerning enabled */
_LETRACE("OTLE::kerning");
LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success); LETableReference kernTable(fFontInstance, LE_KERN_TABLE_TAG, success);
KernTable kt(kernTable, success); KernTable kt(kernTable, success);
kt.process(glyphStorage, success); kt.process(glyphStorage, success);
...@@ -546,6 +550,7 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3 ...@@ -546,6 +550,7 @@ void OpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], le_int3
xPlacement = fFontInstance->xUnitsToPoints(xPlacement); xPlacement = fFontInstance->xUnitsToPoints(xPlacement);
yPlacement = fFontInstance->yUnitsToPoints(yPlacement); yPlacement = fFontInstance->yUnitsToPoints(yPlacement);
_LETRACE("OTLE GPOS: #%d, (%.2f,%.2f)", i, xPlacement, yPlacement);
glyphStorage.adjustPosition(i, xAdjust + xPlacement, -(yAdjust + yPlacement), success); glyphStorage.adjustPosition(i, xAdjust + xPlacement, -(yAdjust + yPlacement), success);
xAdjust += fFontInstance->xUnitsToPoints(xAdvance); xAdjust += fFontInstance->xUnitsToPoints(xAdvance);
......
...@@ -46,15 +46,14 @@ class OpenTypeUtilities /* not : public UObject because all methods are static * ...@@ -46,15 +46,14 @@ class OpenTypeUtilities /* not : public UObject because all methods are static *
public: public:
static le_int8 highBit(le_int32 value); static le_int8 highBit(le_int32 value);
static Offset getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success); static Offset getTagOffset(LETag tag, const LEReferenceToArrayOf<TagAndOffsetRecord> &records, LEErrorCode &success);
/** #if LE_ENABLE_RAW
* @deprecated TODO remove
*/
static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount) { static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const GlyphRangeRecord *records, le_int32 recordCount) {
LEErrorCode success = LE_NO_ERROR; LEErrorCode success = LE_NO_ERROR;
LETableReference recordRef0((const le_uint8*)records); LETableReference recordRef0((const le_uint8*)records);
LEReferenceToArrayOf<GlyphRangeRecord> recordRef(recordRef0, success, (size_t)0, recordCount); LEReferenceToArrayOf<GlyphRangeRecord> recordRef(recordRef0, success, (size_t)0, recordCount);
return getGlyphRangeIndex(glyphID, recordRef, success); return getGlyphRangeIndex(glyphID, recordRef, success);
} }
#endif
static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const LEReferenceToArrayOf<GlyphRangeRecord> &records, LEErrorCode &success); static le_int32 getGlyphRangeIndex(TTGlyphID glyphID, const LEReferenceToArrayOf<GlyphRangeRecord> &records, LEErrorCode &success);
static le_int32 search(le_uint16 value, const le_uint16 array[], le_int32 count); static le_int32 search(le_uint16 value, const le_uint16 array[], le_int32 count);
static le_int32 search(le_uint32 value, const le_uint32 array[], le_int32 count); static le_int32 search(le_uint32 value, const le_uint32 array[], le_int32 count);
......
...@@ -76,19 +76,17 @@ le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositi ...@@ -76,19 +76,17 @@ le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositi
{ {
LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID(); LEGlyphID firstGlyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success); le_int32 coverageIndex = getGlyphCoverage(base, firstGlyph, success);
if (LE_FAILURE(success)) {
return 0;
}
GlyphIterator tempIterator(*glyphIterator); GlyphIterator tempIterator(*glyphIterator);
if (coverageIndex >= 0 && glyphIterator->next()) { LEReferenceToArrayOf<Offset> pairSetTableOffsetArrayRef(base, success, pairSetTableOffsetArray, SWAPW(pairSetCount));
if (LE_SUCCESS(success) && coverageIndex >= 0 && glyphIterator->next() && (le_uint32)coverageIndex < pairSetTableOffsetArrayRef.getCount()) {
Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]); Offset pairSetTableOffset = SWAPW(pairSetTableOffsetArray[coverageIndex]);
LEReferenceTo<PairSetTable> pairSetTable(base, success, ((char *) this + pairSetTableOffset)); LEReferenceTo<PairSetTable> pairSetTable(base, success, pairSetTableOffset);
if (LE_FAILURE(success)) { if( LE_FAILURE(success) ) return 0;
return 0;
}
le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount); le_uint16 pairValueCount = SWAPW(pairSetTable->pairValueCount);
LEReferenceTo<PairValueRecord> pairValueRecordArray(pairSetTable, success, pairSetTable->pairValueRecordArray);
if( LE_FAILURE(success) ) return 0;
le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1)); le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2)); le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size; le_int16 recordSize = sizeof(PairValueRecord) - sizeof(ValueRecord) + valueRecord1Size + valueRecord2Size;
...@@ -96,21 +94,22 @@ le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositi ...@@ -96,21 +94,22 @@ le_uint32 PairPositioningFormat1Subtable::process(const LEReferenceTo<PairPositi
LEReferenceTo<PairValueRecord> pairValueRecord; LEReferenceTo<PairValueRecord> pairValueRecord;
if (pairValueCount != 0) { if (pairValueCount != 0) {
pairValueRecord = findPairValueRecord(base, (TTGlyphID) LE_GET_GLYPH(secondGlyph), pairSetTable->pairValueRecordArray, pairValueCount, recordSize, success); pairValueRecord = findPairValueRecord((TTGlyphID) LE_GET_GLYPH(secondGlyph), pairValueRecordArray, pairValueCount, recordSize, success);
} }
if (pairValueRecord.isEmpty()) { if (pairValueRecord.isEmpty() || LE_FAILURE(success)) {
return 0; return 0;
} }
if (valueFormat1 != 0) { if (valueFormat1 != 0) {
pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance); pairValueRecord->valueRecord1.adjustPosition(SWAPW(valueFormat1), base, tempIterator, fontInstance, success);
} }
if (valueFormat2 != 0) { if (valueFormat2 != 0) {
const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size); LEReferenceTo<ValueRecord> valueRecord2(base, success, ((char *) &pairValueRecord->valueRecord1 + valueRecord1Size));
if(LE_SUCCESS(success)) {
valueRecord2->adjustPosition(SWAPW(valueFormat2), (char *) this, *glyphIterator, fontInstance); valueRecord2->adjustPosition(SWAPW(valueFormat2), base, *glyphIterator, fontInstance, success);
}
} }
// back up glyphIterator so second glyph can be // back up glyphIterator so second glyph can be
...@@ -135,26 +134,28 @@ le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositi ...@@ -135,26 +134,28 @@ le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositi
if (coverageIndex >= 0 && glyphIterator->next()) { if (coverageIndex >= 0 && glyphIterator->next()) {
LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID(); LEGlyphID secondGlyph = glyphIterator->getCurrGlyphID();
const ClassDefinitionTable *classDef1 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef1Offset)); const LEReferenceTo<ClassDefinitionTable> classDef1(base, success, SWAPW(classDef1Offset));
const ClassDefinitionTable *classDef2 = (const ClassDefinitionTable *) ((char *) this + SWAPW(classDef2Offset)); const LEReferenceTo<ClassDefinitionTable> classDef2(base, success, SWAPW(classDef2Offset));
le_int32 class1 = classDef1->getGlyphClass(firstGlyph); le_int32 class1 = classDef1->getGlyphClass(classDef1, firstGlyph, success);
le_int32 class2 = classDef2->getGlyphClass(secondGlyph); le_int32 class2 = classDef2->getGlyphClass(classDef2, secondGlyph, success);
le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1)); le_int16 valueRecord1Size = ValueRecord::getSize(SWAPW(valueFormat1));
le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2)); le_int16 valueRecord2Size = ValueRecord::getSize(SWAPW(valueFormat2));
le_int16 class2RecordSize = valueRecord1Size + valueRecord2Size; le_int16 class2RecordSize = valueRecord1Size + valueRecord2Size;
le_int16 class1RecordSize = class2RecordSize * SWAPW(class2Count); le_int16 class1RecordSize = class2RecordSize * SWAPW(class2Count);
const Class1Record *class1Record = (const Class1Record *) ((char *) class1RecordArray + (class1RecordSize * class1)); const LEReferenceTo<Class1Record> class1Record(base, success, (const Class1Record *) ((char *) class1RecordArray + (class1RecordSize * class1)));
const Class2Record *class2Record = (const Class2Record *) ((char *) class1Record->class2RecordArray + (class2RecordSize * class2)); const LEReferenceTo<Class2Record> class2Record(base, success, (const Class2Record *) ((char *) class1Record->class2RecordArray + (class2RecordSize * class2)));
if( LE_SUCCESS(success) ) {
if (valueFormat1 != 0) { if (valueFormat1 != 0) {
class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), (char *) this, tempIterator, fontInstance); class2Record->valueRecord1.adjustPosition(SWAPW(valueFormat1), base, tempIterator, fontInstance, success);
} }
if (valueFormat2 != 0) {
if (valueFormat2 != 0) { const LEReferenceTo<ValueRecord> valueRecord2(base, success, ((char *) &class2Record->valueRecord1) + valueRecord1Size);
const ValueRecord *valueRecord2 = (const ValueRecord *) ((char *) &class2Record->valueRecord1 + valueRecord1Size); LEReferenceTo<PairPositioningFormat2Subtable> thisRef(base, success, this);
if(LE_SUCCESS(success)) {
valueRecord2->adjustPosition(SWAPW(valueFormat2), (const char *) this, *glyphIterator, fontInstance); valueRecord2->adjustPosition(SWAPW(valueFormat2), thisRef, *glyphIterator, fontInstance, success);
}
}
} }
// back up glyphIterator so second glyph can be // back up glyphIterator so second glyph can be
...@@ -166,23 +167,24 @@ le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositi ...@@ -166,23 +167,24 @@ le_uint32 PairPositioningFormat2Subtable::process(const LEReferenceTo<PairPositi
return 0; return 0;
} }
LEReferenceTo<PairValueRecord> PairPositioningFormat1Subtable::findPairValueRecord(const LETableReference &base, TTGlyphID glyphID, const PairValueRecord *records, le_uint16 recordCount, le_uint16 recordSize, LEErrorCode &success) const LEReferenceTo<PairValueRecord>
PairPositioningFormat1Subtable::findPairValueRecord(TTGlyphID glyphID, LEReferenceTo<PairValueRecord>& records,
le_uint16 recordCount,
le_uint16 recordSize, LEErrorCode &success) const
{ {
#if 1 #if 1
// The OpenType spec. says that the ValueRecord table is // The OpenType spec. says that the ValueRecord table is
// sorted by secondGlyph. Unfortunately, there are fonts // sorted by secondGlyph. Unfortunately, there are fonts
// around that have an unsorted ValueRecord table. // around that have an unsorted ValueRecord table.
LEReferenceTo<PairValueRecord> record(base, success, records); LEReferenceTo<PairValueRecord> record(records);
record.verifyLength(0, recordSize, success);
for(le_int32 r = 0; r < recordCount; r += 1) { for(le_int32 r = 0; r < recordCount; r += 1) {
if (LE_FAILURE(success)) return (const PairValueRecord*)NULL; if(LE_FAILURE(success)) return LEReferenceTo<PairValueRecord>();
if (SWAPW(record->secondGlyph) == glyphID) { if (SWAPW(record->secondGlyph) == glyphID) {
return record; return record;
} }
record = LEReferenceTo<PairValueRecord>(base, success, ((const char*)record.getAlias())+ recordSize); record.addOffset(recordSize, success);
record.verifyLength(0, recordSize, success);
} }
#else #else
#error dead code - not updated. #error dead code - not updated.
...@@ -211,7 +213,7 @@ LEReferenceTo<PairValueRecord> PairPositioningFormat1Subtable::findPairValueReco ...@@ -211,7 +213,7 @@ LEReferenceTo<PairValueRecord> PairPositioningFormat1Subtable::findPairValueReco
} }
#endif #endif
return (const PairValueRecord*)NULL; return LEReferenceTo<PairValueRecord>();
} }
U_NAMESPACE_END U_NAMESPACE_END
...@@ -77,9 +77,8 @@ struct PairPositioningFormat1Subtable : PairPositioningSubtable ...@@ -77,9 +77,8 @@ struct PairPositioningFormat1Subtable : PairPositioningSubtable
le_uint32 process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const; le_uint32 process(const LEReferenceTo<PairPositioningFormat1Subtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
private: private:
LEReferenceTo<PairValueRecord> findPairValueRecord(const LETableReference &base, TTGlyphID glyphID, const PairValueRecord *records, LEReferenceTo<PairValueRecord> findPairValueRecord(TTGlyphID glyphID, LEReferenceTo<PairValueRecord> &records,
le_uint16 recordCount, le_uint16 recordSize, LEErrorCode &success) const; le_uint16 recordCount, le_uint16 recordSize, LEErrorCode &success) const;
}; };
LE_VAR_ARRAY(PairPositioningFormat1Subtable, pairSetTableOffsetArray) LE_VAR_ARRAY(PairPositioningFormat1Subtable, pairSetTableOffsetArray)
......
...@@ -106,7 +106,8 @@ LEReferenceTo<ScriptTable> ScriptListTable::findScript(const LETableReference &b ...@@ -106,7 +106,8 @@ LEReferenceTo<ScriptTable> ScriptListTable::findScript(const LETableReference &b
} }
} else { } else {
LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], count); LEReferenceToArrayOf<ScriptRecord> scriptRecordArrayRef(base, success, &scriptRecordArray[0], count);
scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArrayRef, success); // TODO
scriptTableOffset = OpenTypeUtilities::getTagOffset(scriptTag, scriptRecordArrayRef, success);
} }
if (scriptTableOffset != 0) { if (scriptTableOffset != 0) {
......
...@@ -126,13 +126,13 @@ const LETag OpenTypeLayoutEngine::scriptTags[] = { ...@@ -126,13 +126,13 @@ const LETag OpenTypeLayoutEngine::scriptTags[] = {
linaScriptTag, /* 'lina' (LINA) */ linaScriptTag, /* 'lina' (LINA) */
mandScriptTag, /* 'mand' (MANDAIC) */ mandScriptTag, /* 'mand' (MANDAIC) */
mayaScriptTag, /* 'maya' (MAYA) */ mayaScriptTag, /* 'maya' (MAYA) */
meroScriptTag, /* 'mero' (MERO) */ meroScriptTag, /* 'mero' (MEROITIC_HIEROGLYPHS) */
nkooScriptTag, /* 'nko ' (NKO) */ nkooScriptTag, /* 'nko ' (NKO) */
orkhScriptTag, /* 'orkh' (OLD_TURKIC) */ orkhScriptTag, /* 'orkh' (OLD_TURKIC) */
permScriptTag, /* 'perm' (PERM) */ permScriptTag, /* 'perm' (PERM) */
phagScriptTag, /* 'phag' (PHAGS_PA) */ phagScriptTag, /* 'phag' (PHAGS_PA) */
phnxScriptTag, /* 'phnx' (PHOENICIAN) */ phnxScriptTag, /* 'phnx' (PHOENICIAN) */
plrdScriptTag, /* 'plrd' (PLRD) */ plrdScriptTag, /* 'plrd' (MIAO/POLLARD) */
roroScriptTag, /* 'roro' (RORO) */ roroScriptTag, /* 'roro' (RORO) */
saraScriptTag, /* 'sara' (SARA) */ saraScriptTag, /* 'sara' (SARA) */
syreScriptTag, /* 'syre' (SYRE) */ syreScriptTag, /* 'syre' (SYRE) */
...@@ -158,7 +158,7 @@ const LETag OpenTypeLayoutEngine::scriptTags[] = { ...@@ -158,7 +158,7 @@ const LETag OpenTypeLayoutEngine::scriptTags[] = {
mteiScriptTag, /* 'mtei' (MEETEI_MAYEK) */ mteiScriptTag, /* 'mtei' (MEETEI_MAYEK) */
armiScriptTag, /* 'armi' (IMPERIAL_ARAMAIC) */ armiScriptTag, /* 'armi' (IMPERIAL_ARAMAIC) */
avstScriptTag, /* 'avst' (AVESTAN) */ avstScriptTag, /* 'avst' (AVESTAN) */
cakmScriptTag, /* 'cakm' (CAKM) */ cakmScriptTag, /* 'cakm' (CHAKMA) */
koreScriptTag, /* 'kore' (KORE) */ koreScriptTag, /* 'kore' (KORE) */
kthiScriptTag, /* 'kthi' (KAITHI) */ kthiScriptTag, /* 'kthi' (KAITHI) */
maniScriptTag, /* 'mani' (MANI) */ maniScriptTag, /* 'mani' (MANI) */
...@@ -181,7 +181,7 @@ const LETag OpenTypeLayoutEngine::scriptTags[] = { ...@@ -181,7 +181,7 @@ const LETag OpenTypeLayoutEngine::scriptTags[] = {
kpelScriptTag, /* 'kpel' (KPEL) */ kpelScriptTag, /* 'kpel' (KPEL) */
lomaScriptTag, /* 'loma' (LOMA) */ lomaScriptTag, /* 'loma' (LOMA) */
mendScriptTag, /* 'mend' (MEND) */ mendScriptTag, /* 'mend' (MEND) */
mercScriptTag, /* 'merc' (MERC) */ mercScriptTag, /* 'merc' (MEROITIC_CURSIVE) */
narbScriptTag, /* 'narb' (NARB) */ narbScriptTag, /* 'narb' (NARB) */
nbatScriptTag, /* 'nbat' (NBAT) */ nbatScriptTag, /* 'nbat' (NBAT) */
palmScriptTag, /* 'palm' (PALM) */ palmScriptTag, /* 'palm' (PALM) */
......
...@@ -140,13 +140,13 @@ const LETag lepcScriptTag = 0x6C657063; /* 'lepc' (LEPCHA) */ ...@@ -140,13 +140,13 @@ const LETag lepcScriptTag = 0x6C657063; /* 'lepc' (LEPCHA) */
const LETag linaScriptTag = 0x6C696E61; /* 'lina' (LINA) */ const LETag linaScriptTag = 0x6C696E61; /* 'lina' (LINA) */
const LETag mandScriptTag = 0x6D616E64; /* 'mand' (MANDAIC) */ const LETag mandScriptTag = 0x6D616E64; /* 'mand' (MANDAIC) */
const LETag mayaScriptTag = 0x6D617961; /* 'maya' (MAYA) */ const LETag mayaScriptTag = 0x6D617961; /* 'maya' (MAYA) */
const LETag meroScriptTag = 0x6D65726F; /* 'mero' (MERO) */ const LETag meroScriptTag = 0x6D65726F; /* 'mero' (MEROITIC_HIEROGLYPHS) */
const LETag nkooScriptTag = 0x6E6B6F20; /* 'nko ' (NKO) */ const LETag nkooScriptTag = 0x6E6B6F20; /* 'nko ' (NKO) */
const LETag orkhScriptTag = 0x6F726B68; /* 'orkh' (OLD_TURKIC) */ const LETag orkhScriptTag = 0x6F726B68; /* 'orkh' (OLD_TURKIC) */
const LETag permScriptTag = 0x7065726D; /* 'perm' (PERM) */ const LETag permScriptTag = 0x7065726D; /* 'perm' (PERM) */
const LETag phagScriptTag = 0x70686167; /* 'phag' (PHAGS_PA) */ const LETag phagScriptTag = 0x70686167; /* 'phag' (PHAGS_PA) */
const LETag phnxScriptTag = 0x70686E78; /* 'phnx' (PHOENICIAN) */ const LETag phnxScriptTag = 0x70686E78; /* 'phnx' (PHOENICIAN) */
const LETag plrdScriptTag = 0x706C7264; /* 'plrd' (PLRD) */ const LETag plrdScriptTag = 0x706C7264; /* 'plrd' (MIAO) */
const LETag roroScriptTag = 0x726F726F; /* 'roro' (RORO) */ const LETag roroScriptTag = 0x726F726F; /* 'roro' (RORO) */
const LETag saraScriptTag = 0x73617261; /* 'sara' (SARA) */ const LETag saraScriptTag = 0x73617261; /* 'sara' (SARA) */
const LETag syreScriptTag = 0x73797265; /* 'syre' (SYRE) */ const LETag syreScriptTag = 0x73797265; /* 'syre' (SYRE) */
...@@ -172,7 +172,7 @@ const LETag moonScriptTag = 0x6D6F6F6E; /* 'moon' (MOON) */ ...@@ -172,7 +172,7 @@ const LETag moonScriptTag = 0x6D6F6F6E; /* 'moon' (MOON) */
const LETag mteiScriptTag = 0x6D746569; /* 'mtei' (MEETEI_MAYEK) */ const LETag mteiScriptTag = 0x6D746569; /* 'mtei' (MEETEI_MAYEK) */
const LETag armiScriptTag = 0x61726D69; /* 'armi' (IMPERIAL_ARAMAIC) */ const LETag armiScriptTag = 0x61726D69; /* 'armi' (IMPERIAL_ARAMAIC) */
const LETag avstScriptTag = 0x61767374; /* 'avst' (AVESTAN) */ const LETag avstScriptTag = 0x61767374; /* 'avst' (AVESTAN) */
const LETag cakmScriptTag = 0x63616B6D; /* 'cakm' (CAKM) */ const LETag cakmScriptTag = 0x63616B6D; /* 'cakm' (CHAKMA) */
const LETag koreScriptTag = 0x6B6F7265; /* 'kore' (KORE) */ const LETag koreScriptTag = 0x6B6F7265; /* 'kore' (KORE) */
const LETag kthiScriptTag = 0x6B746869; /* 'kthi' (KAITHI) */ const LETag kthiScriptTag = 0x6B746869; /* 'kthi' (KAITHI) */
const LETag maniScriptTag = 0x6D616E69; /* 'mani' (MANI) */ const LETag maniScriptTag = 0x6D616E69; /* 'mani' (MANI) */
...@@ -195,7 +195,7 @@ const LETag granScriptTag = 0x6772616E; /* 'gran' (GRAN) */ ...@@ -195,7 +195,7 @@ const LETag granScriptTag = 0x6772616E; /* 'gran' (GRAN) */
const LETag kpelScriptTag = 0x6B70656C; /* 'kpel' (KPEL) */ const LETag kpelScriptTag = 0x6B70656C; /* 'kpel' (KPEL) */
const LETag lomaScriptTag = 0x6C6F6D61; /* 'loma' (LOMA) */ const LETag lomaScriptTag = 0x6C6F6D61; /* 'loma' (LOMA) */
const LETag mendScriptTag = 0x6D656E64; /* 'mend' (MEND) */ const LETag mendScriptTag = 0x6D656E64; /* 'mend' (MEND) */
const LETag mercScriptTag = 0x6D657263; /* 'merc' (MERC) */ const LETag mercScriptTag = 0x6D657263; /* 'merc' (MEROITIC_CURSIVE) */
const LETag narbScriptTag = 0x6E617262; /* 'narb' (NARB) */ const LETag narbScriptTag = 0x6E617262; /* 'narb' (NARB) */
const LETag nbatScriptTag = 0x6E626174; /* 'nbat' (NBAT) */ const LETag nbatScriptTag = 0x6E626174; /* 'nbat' (NBAT) */
const LETag palmScriptTag = 0x70616C6D; /* 'palm' (PALM) */ const LETag palmScriptTag = 0x70616C6D; /* 'palm' (PALM) */
......
...@@ -65,17 +65,18 @@ void SegmentArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode & ...@@ -65,17 +65,18 @@ void SegmentArrayProcessor2::process(LEGlyphStorage &glyphStorage, LEErrorCode &
for (glyph = 0; glyph < glyphCount; glyph += 1) { for (glyph = 0; glyph < glyphCount; glyph += 1) {
LEGlyphID thisGlyph = glyphStorage[glyph]; LEGlyphID thisGlyph = glyphStorage[glyph];
// lookupSegment already range checked by lookupSegment() function.
const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segmentArrayLookupTable, segments, thisGlyph, success); const LookupSegment *lookupSegment = segmentArrayLookupTable->lookupSegment(segmentArrayLookupTable, segments, thisGlyph, success);
if (lookupSegment != NULL) { if (lookupSegment != NULL&& LE_SUCCESS(success)) {
TTGlyphID firstGlyph = SWAPW(lookupSegment->firstGlyph); TTGlyphID firstGlyph = SWAPW(lookupSegment->firstGlyph);
TTGlyphID lastGlyph = SWAPW(lookupSegment->lastGlyph);
le_int16 offset = SWAPW(lookupSegment->value); le_int16 offset = SWAPW(lookupSegment->value);
TTGlyphID thisGlyphId= LE_GET_GLYPH(thisGlyph);
if (offset != 0) { LEReferenceToArrayOf<TTGlyphID> glyphArray(subtableHeader, success, offset, lastGlyph - firstGlyph + 1);
TTGlyphID *glyphArray = (TTGlyphID *) ((char *) subtableHeader.getAliasTODO() + offset); if (offset != 0 && thisGlyphId <= lastGlyph && thisGlyphId >= firstGlyph && LE_SUCCESS(success) ) {
TTGlyphID newGlyph = SWAPW(glyphArray[LE_GET_GLYPH(thisGlyph) - firstGlyph]); TTGlyphID newGlyph = SWAPW(glyphArray[thisGlyphId]);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
glyphStorage[glyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
} }
} }
} }
......
...@@ -75,7 +75,7 @@ le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePo ...@@ -75,7 +75,7 @@ le_uint32 SinglePositioningFormat1Subtable::process(const LEReferenceTo<SinglePo
} }
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
valueRecord.adjustPosition(SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance); valueRecord.adjustPosition(SWAPW(valueFormat), base, *glyphIterator, fontInstance, success);
return 1; return 1;
} }
...@@ -92,7 +92,7 @@ le_uint32 SinglePositioningFormat2Subtable::process(const LEReferenceTo<SinglePo ...@@ -92,7 +92,7 @@ le_uint32 SinglePositioningFormat2Subtable::process(const LEReferenceTo<SinglePo
} }
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
valueRecordArray[0].adjustPosition(coverageIndex, SWAPW(valueFormat), (const char *) this, *glyphIterator, fontInstance); valueRecordArray[0].adjustPosition(coverageIndex, SWAPW(valueFormat), base, *glyphIterator, fontInstance, success);
return 1; return 1;
} }
......
...@@ -76,7 +76,7 @@ le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleS ...@@ -76,7 +76,7 @@ le_uint32 SingleSubstitutionFormat1Subtable::process(const LEReferenceTo<SingleS
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
TTGlyphID substitute = ((TTGlyphID) LE_GET_GLYPH(glyph)) + SWAPW(deltaGlyphID); TTGlyphID substitute = ((TTGlyphID) LE_GET_GLYPH(glyph)) + SWAPW(deltaGlyphID);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute))) { if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute), success)) {
glyphIterator->setCurrGlyphID(substitute); glyphIterator->setCurrGlyphID(substitute);
} }
...@@ -97,7 +97,7 @@ le_uint32 SingleSubstitutionFormat2Subtable::process(const LEReferenceTo<SingleS ...@@ -97,7 +97,7 @@ le_uint32 SingleSubstitutionFormat2Subtable::process(const LEReferenceTo<SingleS
if (coverageIndex >= 0) { if (coverageIndex >= 0) {
TTGlyphID substitute = SWAPW(substituteArray[coverageIndex]); TTGlyphID substitute = SWAPW(substituteArray[coverageIndex]);
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute))) { if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, substitute), success)) {
glyphIterator->setCurrGlyphID(substitute); glyphIterator->setCurrGlyphID(substitute);
} }
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
*/ */
#ifndef __TIBETANREORDERING_H #ifndef __TIBETANREORDERING_H
#define __TIBETANORDERING_H #define __TIBETANREORDERING_H
/** /**
* \file * \file
......
...@@ -59,8 +59,8 @@ le_int16 ValueRecord::getFieldValue(le_int16 index, ValueFormat valueFormat, Val ...@@ -59,8 +59,8 @@ le_int16 ValueRecord::getFieldValue(le_int16 index, ValueFormat valueFormat, Val
return SWAPW(value); return SWAPW(value);
} }
void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, GlyphIterator &glyphIterator, void ValueRecord::adjustPosition(ValueFormat valueFormat, const LETableReference& base, GlyphIterator &glyphIterator,
const LEFontInstance *fontInstance) const const LEFontInstance *fontInstance, LEErrorCode &success) const
{ {
float xPlacementAdjustment = 0; float xPlacementAdjustment = 0;
float yPlacementAdjustment = 0; float yPlacementAdjustment = 0;
...@@ -118,8 +118,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp ...@@ -118,8 +118,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp
Offset dtOffset = getFieldValue(valueFormat, vrfXPlaDevice); Offset dtOffset = getFieldValue(valueFormat, vrfXPlaDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 xAdj = dt->getAdjustment(xppem); le_int16 xAdj = dt->getAdjustment(dt, xppem, success);
xPlacementAdjustment += fontInstance->xPixelsToUnits(xAdj); xPlacementAdjustment += fontInstance->xPixelsToUnits(xAdj);
} }
...@@ -129,8 +129,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp ...@@ -129,8 +129,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp
Offset dtOffset = getFieldValue(valueFormat, vrfYPlaDevice); Offset dtOffset = getFieldValue(valueFormat, vrfYPlaDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 yAdj = dt->getAdjustment(yppem); le_int16 yAdj = dt->getAdjustment(dt, yppem, success);
yPlacementAdjustment += fontInstance->yPixelsToUnits(yAdj); yPlacementAdjustment += fontInstance->yPixelsToUnits(yAdj);
} }
...@@ -140,8 +140,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp ...@@ -140,8 +140,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp
Offset dtOffset = getFieldValue(valueFormat, vrfXAdvDevice); Offset dtOffset = getFieldValue(valueFormat, vrfXAdvDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 xAdj = dt->getAdjustment(xppem); le_int16 xAdj = dt->getAdjustment(dt, xppem, success);
xAdvanceAdjustment += fontInstance->xPixelsToUnits(xAdj); xAdvanceAdjustment += fontInstance->xPixelsToUnits(xAdj);
} }
...@@ -151,10 +151,10 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp ...@@ -151,10 +151,10 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp
Offset dtOffset = getFieldValue(valueFormat, vrfYAdvDevice); Offset dtOffset = getFieldValue(valueFormat, vrfYAdvDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 yAdj = dt->getAdjustment(yppem); le_int16 yAdj = dt->getAdjustment(dt, yppem, success);
yAdvanceAdjustment += fontInstance->yPixelsToUnits(yAdj); yAdvanceAdjustment += fontInstance->yPixelsToUnits(yAdj);
} }
} }
} }
...@@ -163,8 +163,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp ...@@ -163,8 +163,8 @@ void ValueRecord::adjustPosition(ValueFormat valueFormat, const char *base, Glyp
xPlacementAdjustment, yPlacementAdjustment, xAdvanceAdjustment, yAdvanceAdjustment); xPlacementAdjustment, yPlacementAdjustment, xAdvanceAdjustment, yAdvanceAdjustment);
} }
void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const char *base, GlyphIterator &glyphIterator, void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const LETableReference& base, GlyphIterator &glyphIterator,
const LEFontInstance *fontInstance) const const LEFontInstance *fontInstance, LEErrorCode &success) const
{ {
float xPlacementAdjustment = 0; float xPlacementAdjustment = 0;
float yPlacementAdjustment = 0; float yPlacementAdjustment = 0;
...@@ -222,8 +222,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const ...@@ -222,8 +222,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const
Offset dtOffset = getFieldValue(index, valueFormat, vrfXPlaDevice); Offset dtOffset = getFieldValue(index, valueFormat, vrfXPlaDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 xAdj = dt->getAdjustment(xppem); le_int16 xAdj = dt->getAdjustment(dt, xppem, success);
xPlacementAdjustment += fontInstance->xPixelsToUnits(xAdj); xPlacementAdjustment += fontInstance->xPixelsToUnits(xAdj);
} }
...@@ -233,8 +233,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const ...@@ -233,8 +233,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const
Offset dtOffset = getFieldValue(index, valueFormat, vrfYPlaDevice); Offset dtOffset = getFieldValue(index, valueFormat, vrfYPlaDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 yAdj = dt->getAdjustment(yppem); le_int16 yAdj = dt->getAdjustment(dt, yppem, success);
yPlacementAdjustment += fontInstance->yPixelsToUnits(yAdj); yPlacementAdjustment += fontInstance->yPixelsToUnits(yAdj);
} }
...@@ -244,8 +244,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const ...@@ -244,8 +244,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const
Offset dtOffset = getFieldValue(index, valueFormat, vrfXAdvDevice); Offset dtOffset = getFieldValue(index, valueFormat, vrfXAdvDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 xAdj = dt->getAdjustment(xppem); le_int16 xAdj = dt->getAdjustment(dt, xppem, success);
xAdvanceAdjustment += fontInstance->xPixelsToUnits(xAdj); xAdvanceAdjustment += fontInstance->xPixelsToUnits(xAdj);
} }
...@@ -255,8 +255,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const ...@@ -255,8 +255,8 @@ void ValueRecord::adjustPosition(le_int16 index, ValueFormat valueFormat, const
Offset dtOffset = getFieldValue(index, valueFormat, vrfYAdvDevice); Offset dtOffset = getFieldValue(index, valueFormat, vrfYAdvDevice);
if (dtOffset != 0) { if (dtOffset != 0) {
const DeviceTable *dt = (const DeviceTable *) (base + dtOffset); LEReferenceTo<DeviceTable> dt(base, success, dtOffset);
le_int16 yAdj = dt->getAdjustment(yppem); le_int16 yAdj = dt->getAdjustment(dt, yppem, success);
yAdvanceAdjustment += fontInstance->yPixelsToUnits(yAdj); yAdvanceAdjustment += fontInstance->yPixelsToUnits(yAdj);
} }
......
...@@ -53,10 +53,10 @@ struct ValueRecord ...@@ -53,10 +53,10 @@ struct ValueRecord
le_int16 getFieldValue(ValueFormat valueFormat, ValueRecordField field) const; le_int16 getFieldValue(ValueFormat valueFormat, ValueRecordField field) const;
le_int16 getFieldValue(le_int16 index, ValueFormat valueFormat, ValueRecordField field) const; le_int16 getFieldValue(le_int16 index, ValueFormat valueFormat, ValueRecordField field) const;
void adjustPosition(ValueFormat valueFormat, const char *base, GlyphIterator &glyphIterator, void adjustPosition(ValueFormat valueFormat, const LETableReference &base, GlyphIterator &glyphIterator,
const LEFontInstance *fontInstance) const; const LEFontInstance *fontInstance, LEErrorCode &success) const;
void adjustPosition(le_int16 index, ValueFormat valueFormat, const char *base, GlyphIterator &glyphIterator, void adjustPosition(le_int16 index, ValueFormat valueFormat, const LETableReference &base, GlyphIterator &glyphIterator,
const LEFontInstance *fontInstance) const; const LEFontInstance *fontInstance, LEErrorCode &success) const;
static le_int16 getSize(ValueFormat valueFormat); static le_int16 getSize(ValueFormat valueFormat);
......
...@@ -215,6 +215,11 @@ void LinLerp1D(register const cmsUInt16Number Value[], ...@@ -215,6 +215,11 @@ void LinLerp1D(register const cmsUInt16Number Value[],
Output[0] = LinearInterp(rest, y0, y1); Output[0] = LinearInterp(rest, y0, y1);
} }
// To prevent out of bounds indexing
cmsINLINE cmsFloat32Number fclamp(cmsFloat32Number v)
{
return v < 0.0f ? 0.0f : (v > 1.0f ? 1.0f : v);
}
// Floating-point version of 1D interpolation // Floating-point version of 1D interpolation
static static
...@@ -227,13 +232,15 @@ void LinLerp1Dfloat(const cmsFloat32Number Value[], ...@@ -227,13 +232,15 @@ void LinLerp1Dfloat(const cmsFloat32Number Value[],
int cell0, cell1; int cell0, cell1;
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table; const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
val2 = fclamp(Value[0]);
// if last value... // if last value...
if (Value[0] == 1.0) { if (val2 == 1.0) {
Output[0] = LutTable[p -> Domain[0]]; Output[0] = LutTable[p -> Domain[0]];
return; return;
} }
val2 = p -> Domain[0] * Value[0]; val2 *= p -> Domain[0];
cell0 = (int) floor(val2); cell0 = (int) floor(val2);
cell1 = (int) ceil(val2); cell1 = (int) ceil(val2);
...@@ -292,13 +299,15 @@ void Eval1InputFloat(const cmsFloat32Number Value[], ...@@ -292,13 +299,15 @@ void Eval1InputFloat(const cmsFloat32Number Value[],
cmsUInt32Number OutChan; cmsUInt32Number OutChan;
const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table; const cmsFloat32Number* LutTable = (cmsFloat32Number*) p ->Table;
val2 = fclamp(Value[0]);
// if last value... // if last value...
if (Value[0] == 1.0) { if (val2 == 1.0) {
Output[0] = LutTable[p -> Domain[0]]; Output[0] = LutTable[p -> Domain[0]];
return; return;
} }
val2 = p -> Domain[0] * Value[0]; val2 *= p -> Domain[0];
cell0 = (int) floor(val2); cell0 = (int) floor(val2);
cell1 = (int) ceil(val2); cell1 = (int) ceil(val2);
...@@ -339,8 +348,8 @@ void BilinearInterpFloat(const cmsFloat32Number Input[], ...@@ -339,8 +348,8 @@ void BilinearInterpFloat(const cmsFloat32Number Input[],
dxy; dxy;
TotalOut = p -> nOutputs; TotalOut = p -> nOutputs;
px = Input[0] * p->Domain[0]; px = fclamp(Input[0]) * p->Domain[0];
py = Input[1] * p->Domain[1]; py = fclamp(Input[1]) * p->Domain[1];
x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0; x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0; y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
...@@ -454,20 +463,9 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[], ...@@ -454,20 +463,9 @@ void TrilinearInterpFloat(const cmsFloat32Number Input[],
TotalOut = p -> nOutputs; TotalOut = p -> nOutputs;
// We need some clipping here // We need some clipping here
px = Input[0]; px = fclamp(Input[0]) * p->Domain[0];
py = Input[1]; py = fclamp(Input[1]) * p->Domain[1];
pz = Input[2]; pz = fclamp(Input[2]) * p->Domain[2];
if (px < 0) px = 0;
if (px > 1) px = 1;
if (py < 0) py = 0;
if (py > 1) py = 1;
if (pz < 0) pz = 0;
if (pz > 1) pz = 1;
px *= p->Domain[0];
py *= p->Domain[1];
pz *= p->Domain[2];
x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0; x0 = (int) _cmsQuickFloor(px); fx = px - (cmsFloat32Number) x0;
y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0; y0 = (int) _cmsQuickFloor(py); fy = py - (cmsFloat32Number) y0;
...@@ -609,20 +607,9 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[], ...@@ -609,20 +607,9 @@ void TetrahedralInterpFloat(const cmsFloat32Number Input[],
TotalOut = p -> nOutputs; TotalOut = p -> nOutputs;
// We need some clipping here // We need some clipping here
px = Input[0]; px = fclamp(Input[0]) * p->Domain[0];
py = Input[1]; py = fclamp(Input[1]) * p->Domain[1];
pz = Input[2]; pz = fclamp(Input[2]) * p->Domain[2];
if (px < 0) px = 0;
if (px > 1) px = 1;
if (py < 0) py = 0;
if (py > 1) py = 1;
if (pz < 0) pz = 0;
if (pz > 1) pz = 1;
px *= p->Domain[0];
py *= p->Domain[1];
pz *= p->Domain[2];
x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0); x0 = (int) _cmsQuickFloor(px); rx = (px - (cmsFloat32Number) x0);
y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0); y0 = (int) _cmsQuickFloor(py); ry = (py - (cmsFloat32Number) y0);
...@@ -1039,8 +1026,7 @@ void Eval4InputsFloat(const cmsFloat32Number Input[], ...@@ -1039,8 +1026,7 @@ void Eval4InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1; cmsInterpParams p1;
pk = fclamp(Input[0]) * p->Domain[0];
pk = Input[0] * p->Domain[0];
k0 = _cmsQuickFloor(pk); k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0; rest = pk - (cmsFloat32Number) k0;
...@@ -1127,7 +1113,7 @@ void Eval5InputsFloat(const cmsFloat32Number Input[], ...@@ -1127,7 +1113,7 @@ void Eval5InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1; cmsInterpParams p1;
pk = Input[0] * p->Domain[0]; pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk); k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0; rest = pk - (cmsFloat32Number) k0;
...@@ -1214,7 +1200,7 @@ void Eval6InputsFloat(const cmsFloat32Number Input[], ...@@ -1214,7 +1200,7 @@ void Eval6InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1; cmsInterpParams p1;
pk = Input[0] * p->Domain[0]; pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk); k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0; rest = pk - (cmsFloat32Number) k0;
...@@ -1299,7 +1285,7 @@ void Eval7InputsFloat(const cmsFloat32Number Input[], ...@@ -1299,7 +1285,7 @@ void Eval7InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1; cmsInterpParams p1;
pk = Input[0] * p->Domain[0]; pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk); k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0; rest = pk - (cmsFloat32Number) k0;
...@@ -1384,7 +1370,7 @@ void Eval8InputsFloat(const cmsFloat32Number Input[], ...@@ -1384,7 +1370,7 @@ void Eval8InputsFloat(const cmsFloat32Number Input[],
cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS]; cmsFloat32Number Tmp1[MAX_STAGE_CHANNELS], Tmp2[MAX_STAGE_CHANNELS];
cmsInterpParams p1; cmsInterpParams p1;
pk = Input[0] * p->Domain[0]; pk = fclamp(Input[0]) * p->Domain[0];
k0 = _cmsQuickFloor(pk); k0 = _cmsQuickFloor(pk);
rest = pk - (cmsFloat32Number) k0; rest = pk - (cmsFloat32Number) k0;
......
...@@ -577,8 +577,8 @@ SplashEventLoop(Splash * splash) { ...@@ -577,8 +577,8 @@ SplashEventLoop(Splash * splash) {
SplashUnlock(splash); SplashUnlock(splash);
rc = poll(pfd, 2, timeout); rc = poll(pfd, 2, timeout);
SplashLock(splash); SplashLock(splash);
if (splash->isVisible>0 && SplashTime() >= splash->time + if (splash->isVisible > 0 && splash->currentFrame >= 0 &&
splash->frames[splash->currentFrame].delay) { SplashTime() >= splash->time + splash->frames[splash->currentFrame].delay) {
SplashNextFrame(splash); SplashNextFrame(splash);
SplashUpdateShape(splash); SplashUpdateShape(splash);
SplashRedrawWindow(splash); SplashRedrawWindow(splash);
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
/* /*
* @test * @test
* @bug 6741606 7146431 8000450 8019830 * @bug 6741606 7146431 8000450 8019830 8022945
* @summary Make sure all restricted packages listed in the package.access * @summary Make sure all restricted packages listed in the package.access
* property in the java.security file are blocked * property in the java.security file are blocked
* @run main/othervm CheckPackageAccess * @run main/othervm CheckPackageAccess
...@@ -56,6 +56,7 @@ public class CheckPackageAccess { ...@@ -56,6 +56,7 @@ public class CheckPackageAccess {
"com.sun.istack.internal.", "com.sun.istack.internal.",
"com.sun.jmx.", "com.sun.jmx.",
"com.sun.media.sound.", "com.sun.media.sound.",
"com.sun.naming.internal.",
"com.sun.proxy.", "com.sun.proxy.",
"com.sun.corba.se.", "com.sun.corba.se.",
"com.sun.org.apache.bcel.internal.", "com.sun.org.apache.bcel.internal.",
......
...@@ -239,13 +239,13 @@ public class TimestampCheck { ...@@ -239,13 +239,13 @@ public class TimestampCheck {
" -J-Djava.security.egd=file:/dev/./urandom" + " -J-Djava.security.egd=file:/dev/./urandom" +
" -debug -keystore " + TSKS + " -storepass changeit" + " -debug -keystore " + TSKS + " -storepass changeit" +
" -tsa http://localhost:" + port + "/%d" + " -tsa http://localhost:" + port + "/%d" +
" -signedjar new.jar " + JAR + " old"; " -signedjar new_%d.jar " + JAR + " old";
} else { } else {
cmd = System.getProperty("java.home") + "/bin/jarsigner" + cmd = System.getProperty("java.home") + "/bin/jarsigner" +
" -J-Djava.security.egd=file:/dev/./urandom" + " -J-Djava.security.egd=file:/dev/./urandom" +
" -debug -keystore " + TSKS + " -storepass changeit" + " -debug -keystore " + TSKS + " -storepass changeit" +
" -tsa http://localhost:" + port + "/%d" + " -tsa http://localhost:" + port + "/%d" +
" -signedjar new.jar " + JAR + " old"; " -signedjar new_%d.jar " + JAR + " old";
} }
try { try {
...@@ -280,7 +280,7 @@ public class TimestampCheck { ...@@ -280,7 +280,7 @@ public class TimestampCheck {
static void jarsigner(String cmd, int path, boolean expected) static void jarsigner(String cmd, int path, boolean expected)
throws Exception { throws Exception {
System.err.println("Test " + path); System.err.println("Test " + path);
Process p = Runtime.getRuntime().exec(String.format(cmd, path)); Process p = Runtime.getRuntime().exec(String.format(cmd, path, path));
BufferedReader reader = new BufferedReader( BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getErrorStream())); new InputStreamReader(p.getErrorStream()));
while (true) { while (true) {
...@@ -288,9 +288,25 @@ public class TimestampCheck { ...@@ -288,9 +288,25 @@ public class TimestampCheck {
if (s == null) break; if (s == null) break;
System.err.println(s); System.err.println(s);
} }
// Will not see noTimestamp warning
boolean seeWarning = false;
reader = new BufferedReader(
new InputStreamReader(p.getInputStream()));
while (true) {
String s = reader.readLine();
if (s == null) break;
System.err.println(s);
if (s.indexOf("Warning:") >= 0) {
seeWarning = true;
}
}
int result = p.waitFor(); int result = p.waitFor();
if (expected && result != 0 || !expected && result == 0) { if (expected && result != 0 || !expected && result == 0) {
throw new Exception("Failed"); throw new Exception("Failed");
} }
if (seeWarning) {
throw new Exception("See warning");
}
} }
} }
...@@ -139,7 +139,6 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l` ...@@ -139,7 +139,6 @@ LINES=`$JARSIGNER -verify a.jar -verbose:summary -certs | grep "more)" | wc -l`
# 16 and 32 already covered in the first part # 16 and 32 already covered in the first part
# ========================================================== # ==========================================================
$KT -genkeypair -alias expiring -dname CN=expiring -startdate -1m
$KT -genkeypair -alias expired -dname CN=expired -startdate -10m $KT -genkeypair -alias expired -dname CN=expired -startdate -10m
$KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m $KT -genkeypair -alias notyetvalid -dname CN=notyetvalid -startdate +1m
$KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365 $KT -genkeypair -alias badku -dname CN=badku -ext KU=cRLSign -validity 365
...@@ -154,9 +153,6 @@ $KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \ ...@@ -154,9 +153,6 @@ $KT -certreq -alias badchain | $KT -gencert -alias ca -validity 365 | \
$KT -importcert -alias badchain $KT -importcert -alias badchain
$KT -delete -alias ca $KT -delete -alias ca
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expiring
[ $? = 2 ] || exit $LINENO
$JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired $JARSIGNER -strict -keystore js.jks -storepass changeit a.jar expired
[ $? = 4 ] || exit $LINENO [ $? = 4 ] || exit $LINENO
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
# #
# @test # @test
# @bug 6543842 6543440 6939248 8009636 # @bug 6543842 6543440 6939248 8009636 8024302
# @summary checking response of timestamp # @summary checking response of timestamp
# #
# @run shell/timeout=600 ts.sh # @run shell/timeout=600 ts.sh
...@@ -53,7 +53,7 @@ fi ...@@ -53,7 +53,7 @@ fi
JAR="${TESTJAVA}${FS}bin${FS}jar" JAR="${TESTJAVA}${FS}bin${FS}jar"
JAVA="${TESTJAVA}${FS}bin${FS}java" JAVA="${TESTJAVA}${FS}bin${FS}java"
JAVAC="${TESTJAVA}${FS}bin${FS}javac" JAVAC="${TESTJAVA}${FS}bin${FS}javac"
KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa" KT="${TESTJAVA}${FS}bin${FS}keytool -keystore tsks -storepass changeit -keypass changeit -keyalg rsa -validity 200"
rm tsks rm tsks
echo Nothing > A echo Nothing > A
......
#
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code 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 General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
# @test
# @bug 8024302
# @bug 8026037
# @summary Clarify jar verifications
#
if [ "${TESTJAVA}" = "" ] ; then
JAVAC_CMD=`which javac`
TESTJAVA=`dirname $JAVAC_CMD`/..
fi
# set platform-dependent variables
OS=`uname -s`
case "$OS" in
Windows_* )
FS="\\"
;;
* )
FS="/"
;;
esac
KS=warnings.jks
JFILE=warnings.jar
KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit \
-keystore $KS"
JAR=$TESTJAVA${FS}bin${FS}jar
JARSIGNER="$TESTJAVA${FS}bin${FS}jarsigner -keystore $KS -storepass changeit"
rm $KS 2> /dev/null
LANG=C
export LANG
echo 12345 > file
ERR=""
# Normal signer expiring on 2100-01-01
$KT -alias s1 -dname CN=s1 -genkey -startdate 2000/01/01 -validity 36525 || ERR="$ERR keytool s1,"
# Cert expiring soon, informational warning
$KT -alias s2 -dname CN=s2 -genkey -validity 100 || ERR="$ERR keytool s2,"
# Cert expired, severe warning
$KT -alias s3 -dname CN=s3 -genkey -startdate -200d -validity 100 || ERR="$ERR keytool s3,"
# noTimestamp is informatiional warning and includes a date
$JAR cvf $JFILE file
$JARSIGNER $JFILE s1 > output1 || ERR="$ERR jarsigner s1,"
$JARSIGNER -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict,"
$JARSIGNER -verify $JFILE s1 >> output1 || ERR="$ERR jarsigner s1,"
$JARSIGNER -verify -strict $JFILE s1 >> output1 || ERR="$ERR jarsigner s1 strict,"
cat output1 | grep Warning || ERR="$ERR s1 warning,"
cat output1 | grep Error && ERR="$ERR s1 error,"
cat output1 | grep timestamp | grep 2100-01-01 || ERR="$ERR s1 timestamp,"
cat output1 | grep "with signer errors" && ERR="$ERR s1 err,"
# hasExpiringCert is informatiional warning
$JAR cvf $JFILE file
$JARSIGNER $JFILE s2 > output2 || ERR="$ERR jarsigner s2,"
$JARSIGNER -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict,"
$JARSIGNER -verify $JFILE s2 >> output2 || ERR="$ERR jarsigner s2,"
$JARSIGNER -verify -strict $JFILE s2 >> output2 || ERR="$ERR jarsigner s2 strict,"
cat output2 | grep Warning || ERR="$ERR s2 warning,"
cat output2 | grep Error && ERR="$ERR s2 error,"
cat output2 | grep timestamp || ERR="$ERR s2 timestamp,"
cat output2 | grep "will expire" || ERR="$ERR s2 expiring,"
cat output2 | grep "with signer errors" && ERR="$ERR s2 err,"
# hasExpiredCert is severe warning
$JAR cvf $JFILE file
$JARSIGNER $JFILE s3 > output3 || ERR="$ERR jarsigner s3,"
$JARSIGNER -strict $JFILE s3 > output3s && ERR="$ERR jarsigner s3 strict,"
$JARSIGNER -verify $JFILE s3 >> output3 || ERR="$ERR jarsigner s3,"
$JARSIGNER -verify -strict $JFILE s3 >> output3s && ERR="$ERR jarsigner s3 strict,"
# warning without -strict
cat output3 | grep Warning || ERR="$ERR s3 warning,"
cat output3 | grep Error && ERR="$ERR s3 error,"
cat output3 | grep "with signer errors" && ERR="$ERR s3 err,"
# error with -strict
cat output3s | grep Warning || ERR="$ERR s3s warning,"
cat output3s | grep Error || ERR="$ERR s3s error,"
cat output3s | grep "with signer errors" || ERR="$ERR s3 err,"
if [ "$ERR" = "" ]; then
exit 0
else
echo "ERR is $ERR"
exit 1
fi
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册