提交 8a936420 编写于 作者: C chegar

Merge

...@@ -106,7 +106,21 @@ FILES_cpp_shared = \ ...@@ -106,7 +106,21 @@ FILES_cpp_shared = \
OpenTypeLayoutEngine.cpp \ OpenTypeLayoutEngine.cpp \
ThaiLayoutEngine.cpp \ ThaiLayoutEngine.cpp \
ScriptAndLanguageTags.cpp \ ScriptAndLanguageTags.cpp \
FontInstanceAdapter.cpp FontInstanceAdapter.cpp \
ContextualGlyphInsertionProc2.cpp \
ContextualGlyphSubstProc2.cpp \
GXLayoutEngine2.cpp \
IndicRearrangementProcessor2.cpp \
LigatureSubstProc2.cpp \
MorphTables2.cpp \
NonContextualGlyphSubstProc2.cpp \
SegmentArrayProcessor2.cpp \
SegmentSingleProcessor2.cpp \
SimpleArrayProcessor2.cpp \
SingleTableProcessor2.cpp \
StateTableProcessor2.cpp \
SubtableProcessor2.cpp \
TrimmedArrayProcessor2.cpp
ifeq ($(PLATFORM),windows) ifeq ($(PLATFORM),windows)
......
...@@ -170,7 +170,7 @@ public class LWWindowPeer ...@@ -170,7 +170,7 @@ public class LWWindowPeer
setTitle(((Dialog) getTarget()).getTitle()); setTitle(((Dialog) getTarget()).getTitle());
} }
setAlwaysOnTop(getTarget().isAlwaysOnTop()); updateAlwaysOnTopState();
updateMinimumSize(); updateMinimumSize();
final Shape shape = getTarget().getShape(); final Shape shape = getTarget().getShape();
...@@ -357,8 +357,8 @@ public class LWWindowPeer ...@@ -357,8 +357,8 @@ public class LWWindowPeer
} }
@Override @Override
public void setAlwaysOnTop(boolean value) { public void updateAlwaysOnTopState() {
platformWindow.setAlwaysOnTop(value); platformWindow.setAlwaysOnTop(getTarget().isAlwaysOnTop());
} }
@Override @Override
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 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
...@@ -180,7 +180,7 @@ class CFileDialog implements FileDialogPeer { ...@@ -180,7 +180,7 @@ class CFileDialog implements FileDialogPeer {
} }
@Override @Override
public void setAlwaysOnTop(boolean alwaysOnTop) { public void updateAlwaysOnTopState() {
} }
@Override @Override
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 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
...@@ -87,7 +87,7 @@ public class CPrinterDialogPeer extends LWWindowPeer { ...@@ -87,7 +87,7 @@ public class CPrinterDialogPeer extends LWWindowPeer {
} }
// 1.6 peer method // 1.6 peer method
public void setAlwaysOnTop(boolean value) { public void updateAlwaysOnTopState() {
// no-op, since we just show the native print dialog // no-op, since we just show the native print dialog
} }
......
...@@ -243,12 +243,17 @@ public class JPEGImageReader extends ImageReader { ...@@ -243,12 +243,17 @@ public class JPEGImageReader extends ImageReader {
* sending warnings to listeners. * sending warnings to listeners.
*/ */
protected void warningOccurred(int code) { protected void warningOccurred(int code) {
if ((code < 0) || (code > MAX_WARNING)){ cbLock.lock();
throw new InternalError("Invalid warning index"); try {
if ((code < 0) || (code > MAX_WARNING)){
throw new InternalError("Invalid warning index");
}
processWarningOccurred
("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources",
Integer.toString(code));
} finally {
cbLock.unlock();
} }
processWarningOccurred
("com.sun.imageio.plugins.jpeg.JPEGImageReaderResources",
Integer.toString(code));
} }
/** /**
...@@ -265,7 +270,12 @@ public class JPEGImageReader extends ImageReader { ...@@ -265,7 +270,12 @@ public class JPEGImageReader extends ImageReader {
* library warnings from being printed to stderr. * library warnings from being printed to stderr.
*/ */
protected void warningWithMessage(String msg) { protected void warningWithMessage(String msg) {
processWarningOccurred(msg); cbLock.lock();
try {
processWarningOccurred(msg);
} finally {
cbLock.unlock();
}
} }
public void setInput(Object input, public void setInput(Object input,
...@@ -274,18 +284,55 @@ public class JPEGImageReader extends ImageReader { ...@@ -274,18 +284,55 @@ public class JPEGImageReader extends ImageReader {
{ {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.setInput(input, seekForwardOnly, ignoreMetadata); super.setInput(input, seekForwardOnly, ignoreMetadata);
this.ignoreMetadata = ignoreMetadata; this.ignoreMetadata = ignoreMetadata;
resetInternalState(); resetInternalState();
iis = (ImageInputStream) input; // Always works iis = (ImageInputStream) input; // Always works
setSource(structPointer, iis); setSource(structPointer);
} finally { } finally {
clearThreadLock(); clearThreadLock();
} }
} }
private native void setSource(long structPointer, /**
ImageInputStream source); * This method is called from native code in order to fill
* native input buffer.
*
* We block any attempt to change the reading state during this
* method, in order to prevent a corruption of the native decoder
* state.
*
* @return number of bytes read from the stream.
*/
private int readInputData(byte[] buf, int off, int len) throws IOException {
cbLock.lock();
try {
return iis.read(buf, off, len);
} finally {
cbLock.unlock();
}
}
/**
* This method is called from the native code in order to
* skip requested number of bytes in the input stream.
*
* @param n
* @return
* @throws IOException
*/
private long skipInputBytes(long n) throws IOException {
cbLock.lock();
try {
return iis.skipBytes(n);
} finally {
cbLock.unlock();
}
}
private native void setSource(long structPointer);
private void checkTablesOnly() throws IOException { private void checkTablesOnly() throws IOException {
if (debug) { if (debug) {
...@@ -337,6 +384,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -337,6 +384,8 @@ public class JPEGImageReader extends ImageReader {
public int getNumImages(boolean allowSearch) throws IOException { public int getNumImages(boolean allowSearch) throws IOException {
setThreadLock(); setThreadLock();
try { // locked thread try { // locked thread
cbLock.check();
return getNumImagesOnThread(allowSearch); return getNumImagesOnThread(allowSearch);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -536,8 +585,13 @@ public class JPEGImageReader extends ImageReader { ...@@ -536,8 +585,13 @@ public class JPEGImageReader extends ImageReader {
if (debug) { if (debug) {
System.out.println("pushing back " + num + " bytes"); System.out.println("pushing back " + num + " bytes");
} }
iis.seek(iis.getStreamPosition()-num); cbLock.lock();
// The buffer is clear after this, so no need to set haveSeeked. try {
iis.seek(iis.getStreamPosition()-num);
// The buffer is clear after this, so no need to set haveSeeked.
} finally {
cbLock.unlock();
}
} }
/** /**
...@@ -644,7 +698,12 @@ public class JPEGImageReader extends ImageReader { ...@@ -644,7 +698,12 @@ public class JPEGImageReader extends ImageReader {
* Ignore this profile. * Ignore this profile.
*/ */
iccCS = null; iccCS = null;
warningOccurred(WARNING_IGNORE_INVALID_ICC); cbLock.lock();
try {
warningOccurred(WARNING_IGNORE_INVALID_ICC);
} finally {
cbLock.unlock();
}
} }
} }
} }
...@@ -653,6 +712,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -653,6 +712,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
return width; return width;
...@@ -665,6 +725,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -665,6 +725,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
return height; return height;
...@@ -693,6 +754,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -693,6 +754,8 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
...@@ -716,6 +779,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -716,6 +779,7 @@ public class JPEGImageReader extends ImageReader {
private Iterator getImageTypesOnThread(int imageIndex) private Iterator getImageTypesOnThread(int imageIndex)
throws IOException { throws IOException {
if (currentImage != imageIndex) { if (currentImage != imageIndex) {
cbLock.check();
readHeader(imageIndex, true); readHeader(imageIndex, true);
} }
...@@ -931,6 +995,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -931,6 +995,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
try { try {
if (!tablesOnlyChecked) { if (!tablesOnlyChecked) {
cbLock.check();
checkTablesOnly(); checkTablesOnly();
} }
return streamMetadata; return streamMetadata;
...@@ -951,6 +1016,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -951,6 +1016,8 @@ public class JPEGImageReader extends ImageReader {
return imageMetadata; return imageMetadata;
} }
cbLock.check();
gotoImage(imageIndex); gotoImage(imageIndex);
imageMetadata = new JPEGMetadata(false, false, iis, this); imageMetadata = new JPEGMetadata(false, false, iis, this);
...@@ -967,6 +1034,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -967,6 +1034,7 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
try { try {
readInternal(imageIndex, param, false); readInternal(imageIndex, param, false);
} catch (RuntimeException e) { } catch (RuntimeException e) {
...@@ -1196,58 +1264,63 @@ public class JPEGImageReader extends ImageReader { ...@@ -1196,58 +1264,63 @@ public class JPEGImageReader extends ImageReader {
} }
target.setRect(destROI.x, destROI.y + y, raster); target.setRect(destROI.x, destROI.y + y, raster);
processImageUpdate(image, cbLock.lock();
destROI.x, destROI.y+y, try {
raster.getWidth(), 1, processImageUpdate(image,
1, 1, destROI.x, destROI.y+y,
destinationBands); raster.getWidth(), 1,
if ((y > 0) && (y%progInterval == 0)) { 1, 1,
int height = target.getHeight()-1; destinationBands);
float percentOfPass = ((float)y)/height; if ((y > 0) && (y%progInterval == 0)) {
if (progressive) { int height = target.getHeight()-1;
if (knownPassCount != UNKNOWN) { float percentOfPass = ((float)y)/height;
processImageProgress((pass + percentOfPass)*100.0F if (progressive) {
/ knownPassCount); if (knownPassCount != UNKNOWN) {
} else if (maxProgressivePass != Integer.MAX_VALUE) { processImageProgress((pass + percentOfPass)*100.0F
// Use the range of allowed progressive passes / knownPassCount);
processImageProgress((pass + percentOfPass)*100.0F } else if (maxProgressivePass != Integer.MAX_VALUE) {
/ (maxProgressivePass - minProgressivePass + 1)); // Use the range of allowed progressive passes
} else { processImageProgress((pass + percentOfPass)*100.0F
// Assume there are a minimum of MIN_ESTIMATED_PASSES / (maxProgressivePass - minProgressivePass + 1));
// and that there is always one more pass } else {
// Compute the percentage as the percentage at the end // Assume there are a minimum of MIN_ESTIMATED_PASSES
// of the previous pass, plus the percentage of this // and that there is always one more pass
// pass scaled to be the percentage of the total remaining, // Compute the percentage as the percentage at the end
// assuming a minimum of MIN_ESTIMATED_PASSES passes and // of the previous pass, plus the percentage of this
// that there is always one more pass. This is monotonic // pass scaled to be the percentage of the total remaining,
// and asymptotic to 1.0, which is what we need. // assuming a minimum of MIN_ESTIMATED_PASSES passes and
int remainingPasses = // including this one // that there is always one more pass. This is monotonic
Math.max(2, MIN_ESTIMATED_PASSES-pass); // and asymptotic to 1.0, which is what we need.
int totalPasses = pass + remainingPasses-1; int remainingPasses = // including this one
progInterval = Math.max(height/20*totalPasses, Math.max(2, MIN_ESTIMATED_PASSES-pass);
totalPasses); int totalPasses = pass + remainingPasses-1;
if (y%progInterval == 0) { progInterval = Math.max(height/20*totalPasses,
percentToDate = previousPassPercentage + totalPasses);
(1.0F - previousPassPercentage) if (y%progInterval == 0) {
* (percentOfPass)/remainingPasses; percentToDate = previousPassPercentage +
if (debug) { (1.0F - previousPassPercentage)
System.out.print("pass= " + pass); * (percentOfPass)/remainingPasses;
System.out.print(", y= " + y); if (debug) {
System.out.print(", progInt= " + progInterval); System.out.print("pass= " + pass);
System.out.print(", % of pass: " + percentOfPass); System.out.print(", y= " + y);
System.out.print(", rem. passes: " System.out.print(", progInt= " + progInterval);
+ remainingPasses); System.out.print(", % of pass: " + percentOfPass);
System.out.print(", prev%: " System.out.print(", rem. passes: "
+ previousPassPercentage); + remainingPasses);
System.out.print(", %ToDate: " + percentToDate); System.out.print(", prev%: "
System.out.print(" "); + previousPassPercentage);
System.out.print(", %ToDate: " + percentToDate);
System.out.print(" ");
}
processImageProgress(percentToDate*100.0F);
} }
processImageProgress(percentToDate*100.0F);
} }
} else {
processImageProgress(percentOfPass * 100.0F);
} }
} else {
processImageProgress(percentOfPass * 100.0F);
} }
} finally {
cbLock.unlock();
} }
} }
...@@ -1260,33 +1333,58 @@ public class JPEGImageReader extends ImageReader { ...@@ -1260,33 +1333,58 @@ public class JPEGImageReader extends ImageReader {
} }
private void passStarted (int pass) { private void passStarted (int pass) {
this.pass = pass; cbLock.lock();
previousPassPercentage = percentToDate; try {
processPassStarted(image, this.pass = pass;
pass, previousPassPercentage = percentToDate;
minProgressivePass, processPassStarted(image,
maxProgressivePass, pass,
0, 0, minProgressivePass,
1,1, maxProgressivePass,
destinationBands); 0, 0,
1,1,
destinationBands);
} finally {
cbLock.unlock();
}
} }
private void passComplete () { private void passComplete () {
processPassComplete(image); cbLock.lock();
try {
processPassComplete(image);
} finally {
cbLock.unlock();
}
} }
void thumbnailStarted(int thumbnailIndex) { void thumbnailStarted(int thumbnailIndex) {
processThumbnailStarted(currentImage, thumbnailIndex); cbLock.lock();
try {
processThumbnailStarted(currentImage, thumbnailIndex);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailProgress(float percentageDone) { void thumbnailProgress(float percentageDone) {
processThumbnailProgress(percentageDone); cbLock.lock();
try {
processThumbnailProgress(percentageDone);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailComplete() { void thumbnailComplete() {
processThumbnailComplete(); cbLock.lock();
try {
processThumbnailComplete();
} finally {
cbLock.unlock();
}
} }
/** /**
...@@ -1310,6 +1408,11 @@ public class JPEGImageReader extends ImageReader { ...@@ -1310,6 +1408,11 @@ public class JPEGImageReader extends ImageReader {
public void abort() { public void abort() {
setThreadLock(); setThreadLock();
try { try {
/**
* NB: we do not check the call back lock here,
* we allow to abort the reader any time.
*/
super.abort(); super.abort();
abortRead(structPointer); abortRead(structPointer);
} finally { } finally {
...@@ -1332,6 +1435,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -1332,6 +1435,7 @@ public class JPEGImageReader extends ImageReader {
setThreadLock(); setThreadLock();
Raster retval = null; Raster retval = null;
try { try {
cbLock.check();
/* /*
* This could be further optimized by not resetting the dest. * This could be further optimized by not resetting the dest.
* offset and creating a translated raster in readInternal() * offset and creating a translated raster in readInternal()
...@@ -1371,6 +1475,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1371,6 +1475,8 @@ public class JPEGImageReader extends ImageReader {
public int getNumThumbnails(int imageIndex) throws IOException { public int getNumThumbnails(int imageIndex) throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
getImageMetadata(imageIndex); // checks iis state for us getImageMetadata(imageIndex); // checks iis state for us
// Now check the jfif segments // Now check the jfif segments
JFIFMarkerSegment jfif = JFIFMarkerSegment jfif =
...@@ -1391,6 +1497,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1391,6 +1497,8 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if ((thumbnailIndex < 0) if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) { || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail"); throw new IndexOutOfBoundsException("No such thumbnail");
...@@ -1409,6 +1517,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1409,6 +1517,8 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if ((thumbnailIndex < 0) if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) { || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail"); throw new IndexOutOfBoundsException("No such thumbnail");
...@@ -1428,6 +1538,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1428,6 +1538,8 @@ public class JPEGImageReader extends ImageReader {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if ((thumbnailIndex < 0) if ((thumbnailIndex < 0)
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) { || (thumbnailIndex >= getNumThumbnails(imageIndex))) {
throw new IndexOutOfBoundsException("No such thumbnail"); throw new IndexOutOfBoundsException("No such thumbnail");
...@@ -1468,6 +1580,7 @@ public class JPEGImageReader extends ImageReader { ...@@ -1468,6 +1580,7 @@ public class JPEGImageReader extends ImageReader {
public void reset() { public void reset() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.reset(); super.reset();
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1479,6 +1592,8 @@ public class JPEGImageReader extends ImageReader { ...@@ -1479,6 +1592,8 @@ public class JPEGImageReader extends ImageReader {
public void dispose() { public void dispose() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (structPointer != 0) { if (structPointer != 0) {
disposerRecord.dispose(); disposerRecord.dispose();
structPointer = 0; structPointer = 0;
...@@ -1540,6 +1655,36 @@ public class JPEGImageReader extends ImageReader { ...@@ -1540,6 +1655,36 @@ public class JPEGImageReader extends ImageReader {
theThread = null; theThread = null;
} }
} }
private CallBackLock cbLock = new CallBackLock();
private static class CallBackLock {
private State lockState;
CallBackLock() {
lockState = State.Unlocked;
}
void check() {
if (lockState != State.Unlocked) {
throw new IllegalStateException("Access to the reader is not allowed");
}
}
private void lock() {
lockState = State.Locked;
}
private void unlock() {
lockState = State.Unlocked;
}
private static enum State {
Unlocked,
Locked
}
}
} }
/** /**
......
...@@ -183,8 +183,7 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -183,8 +183,7 @@ public class JPEGImageWriter extends ImageWriter {
return null; return null;
} }
}); });
initWriterIDs(ImageOutputStream.class, initWriterIDs(JPEGQTable.class,
JPEGQTable.class,
JPEGHuffmanTable.class); JPEGHuffmanTable.class);
} }
...@@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter {
public void setOutput(Object output) { public void setOutput(Object output) {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.setOutput(output); // validates output super.setOutput(output); // validates output
resetInternalState(); resetInternalState();
ios = (ImageOutputStream) output; // so this will always work ios = (ImageOutputStream) output; // so this will always work
// Set the native destination // Set the native destination
setDest(structPointer, ios); setDest(structPointer);
} finally { } finally {
clearThreadLock(); clearThreadLock();
} }
...@@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter {
ImageWriteParam param) throws IOException { ImageWriteParam param) throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
writeOnThread(streamMetadata, image, param); writeOnThread(streamMetadata, image, param);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1082,13 +1085,18 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1082,13 +1085,18 @@ public class JPEGImageWriter extends ImageWriter {
haveMetadata, haveMetadata,
restartInterval); restartInterval);
if (aborted) { cbLock.lock();
processWriteAborted(); try {
} else { if (aborted) {
processImageComplete(); processWriteAborted();
} } else {
processImageComplete();
}
ios.flush(); ios.flush();
} finally {
cbLock.unlock();
}
currentImage++; // After a successful write currentImage++; // After a successful write
} }
...@@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
prepareWriteSequenceOnThread(streamMetadata); prepareWriteSequenceOnThread(streamMetadata);
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter {
throws IOException { throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (sequencePrepared == false) { if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!"); throw new IllegalStateException("sequencePrepared not called!");
} }
...@@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter {
public void endWriteSequence() throws IOException { public void endWriteSequence() throws IOException {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (sequencePrepared == false) { if (sequencePrepared == false) {
throw new IllegalStateException("sequencePrepared not called!"); throw new IllegalStateException("sequencePrepared not called!");
} }
...@@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter {
public synchronized void abort() { public synchronized void abort() {
setThreadLock(); setThreadLock();
try { try {
/**
* NB: we do not check the call back lock here, we allow to abort
* the reader any time.
*/
super.abort(); super.abort();
abortWrite(structPointer); abortWrite(structPointer);
} finally { } finally {
...@@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter {
public void reset() { public void reset() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
super.reset(); super.reset();
} finally { } finally {
clearThreadLock(); clearThreadLock();
...@@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter {
public void dispose() { public void dispose() {
setThreadLock(); setThreadLock();
try { try {
cbLock.check();
if (structPointer != 0) { if (structPointer != 0) {
disposerRecord.dispose(); disposerRecord.dispose();
structPointer = 0; structPointer = 0;
...@@ -1251,13 +1273,18 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1251,13 +1273,18 @@ public class JPEGImageWriter extends ImageWriter {
* sending warnings to listeners. * sending warnings to listeners.
*/ */
void warningOccurred(int code) { void warningOccurred(int code) {
if ((code < 0) || (code > MAX_WARNING)){ cbLock.lock();
throw new InternalError("Invalid warning index"); try {
if ((code < 0) || (code > MAX_WARNING)){
throw new InternalError("Invalid warning index");
}
processWarningOccurred
(currentImage,
"com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
Integer.toString(code));
} finally {
cbLock.unlock();
} }
processWarningOccurred
(currentImage,
"com.sun.imageio.plugins.jpeg.JPEGImageWriterResources",
Integer.toString(code));
} }
/** /**
...@@ -1274,21 +1301,41 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1274,21 +1301,41 @@ public class JPEGImageWriter extends ImageWriter {
* library warnings from being printed to stderr. * library warnings from being printed to stderr.
*/ */
void warningWithMessage(String msg) { void warningWithMessage(String msg) {
processWarningOccurred(currentImage, msg); cbLock.lock();
try {
processWarningOccurred(currentImage, msg);
} finally {
cbLock.unlock();
}
} }
void thumbnailStarted(int thumbnailIndex) { void thumbnailStarted(int thumbnailIndex) {
processThumbnailStarted(currentImage, thumbnailIndex); cbLock.lock();
try {
processThumbnailStarted(currentImage, thumbnailIndex);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailProgress(float percentageDone) { void thumbnailProgress(float percentageDone) {
processThumbnailProgress(percentageDone); cbLock.lock();
try {
processThumbnailProgress(percentageDone);
} finally {
cbLock.unlock();
}
} }
// Provide access to protected superclass method // Provide access to protected superclass method
void thumbnailComplete() { void thumbnailComplete() {
processThumbnailComplete(); cbLock.lock();
try {
processThumbnailComplete();
} finally {
cbLock.unlock();
}
} }
///////// End of Package-access API ///////// End of Package-access API
...@@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter {
////////////// Native methods and callbacks ////////////// Native methods and callbacks
/** Sets up static native structures. */ /** Sets up static native structures. */
private static native void initWriterIDs(Class iosClass, private static native void initWriterIDs(Class qTableClass,
Class qTableClass,
Class huffClass); Class huffClass);
/** Sets up per-writer native structure and returns a pointer to it. */ /** Sets up per-writer native structure and returns a pointer to it. */
private native long initJPEGImageWriter(); private native long initJPEGImageWriter();
/** Sets up native structures for output stream */ /** Sets up native structures for output stream */
private native void setDest(long structPointer, private native void setDest(long structPointer);
ImageOutputStream ios);
/** /**
* Returns <code>true</code> if the write was aborted. * Returns <code>true</code> if the write was aborted.
...@@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter {
} }
raster.setRect(sourceLine); raster.setRect(sourceLine);
if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines if ((y > 7) && (y%8 == 0)) { // Every 8 scanlines
processImageProgress((float) y / (float) sourceHeight * 100.0F); cbLock.lock();
try {
processImageProgress((float) y / (float) sourceHeight * 100.0F);
} finally {
cbLock.unlock();
}
} }
} }
...@@ -1777,6 +1827,25 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1777,6 +1827,25 @@ public class JPEGImageWriter extends ImageWriter {
} }
} }
/**
* This method is called from native code in order to write encoder
* output to the destination.
*
* We block any attempt to change the writer state during this
* method, in order to prevent a corruption of the native encoder
* state.
*/
private void writeOutputData(byte[] data, int offset, int len)
throws IOException
{
cbLock.lock();
try {
ios.write(data, offset, len);
} finally {
cbLock.unlock();
}
}
private Thread theThread = null; private Thread theThread = null;
private int theLockCount = 0; private int theLockCount = 0;
...@@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter { ...@@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter {
theThread = null; theThread = null;
} }
} }
private CallBackLock cbLock = new CallBackLock();
private static class CallBackLock {
private State lockState;
CallBackLock() {
lockState = State.Unlocked;
}
void check() {
if (lockState != State.Unlocked) {
throw new IllegalStateException("Access to the writer is not allowed");
}
}
private void lock() {
lockState = State.Locked;
}
private void unlock() {
lockState = State.Unlocked;
}
private static enum State {
Unlocked,
Locked
}
}
} }
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 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
...@@ -32,6 +32,7 @@ import java.io.IOException; ...@@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Modifier;
import java.security.Permission; import java.security.Permission;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
...@@ -213,7 +214,6 @@ public class MBeanInstantiator { ...@@ -213,7 +214,6 @@ public class MBeanInstantiator {
Object moi; Object moi;
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
Constructor<?> cons = findConstructor(theClass, null); Constructor<?> cons = findConstructor(theClass, null);
...@@ -224,6 +224,7 @@ public class MBeanInstantiator { ...@@ -224,6 +224,7 @@ public class MBeanInstantiator {
// Instantiate the new object // Instantiate the new object
try { try {
ReflectUtil.checkPackageAccess(theClass); ReflectUtil.checkPackageAccess(theClass);
ensureClassAccess(theClass);
moi= cons.newInstance(); moi= cons.newInstance();
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
// Wrap the exception. // Wrap the exception.
...@@ -270,7 +271,6 @@ public class MBeanInstantiator { ...@@ -270,7 +271,6 @@ public class MBeanInstantiator {
checkMBeanPermission(theClass, null, null, "instantiate"); checkMBeanPermission(theClass, null, null, "instantiate");
// Instantiate the new object // Instantiate the new object
// ------------------------------ // ------------------------------
// ------------------------------ // ------------------------------
final Class<?>[] tab; final Class<?>[] tab;
...@@ -300,6 +300,7 @@ public class MBeanInstantiator { ...@@ -300,6 +300,7 @@ public class MBeanInstantiator {
} }
try { try {
ReflectUtil.checkPackageAccess(theClass); ReflectUtil.checkPackageAccess(theClass);
ensureClassAccess(theClass);
moi = cons.newInstance(params); moi = cons.newInstance(params);
} }
catch (NoSuchMethodError error) { catch (NoSuchMethodError error) {
...@@ -741,4 +742,13 @@ public class MBeanInstantiator { ...@@ -741,4 +742,13 @@ public class MBeanInstantiator {
sm.checkPermission(perm); sm.checkPermission(perm);
} }
} }
private static void ensureClassAccess(Class clazz)
throws IllegalAccessException
{
int mod = clazz.getModifiers();
if (!Modifier.isPublic(mod)) {
throw new IllegalAccessException("Class is not public and can't be instantiated");
}
}
} }
...@@ -56,7 +56,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -56,7 +56,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
// from simultaneous creation and destruction // from simultaneous creation and destruction
// reduces possibility of deadlock, compared to // reduces possibility of deadlock, compared to
// synchronizing to the class instance // synchronizing to the class instance
private Object traRecLock = new Object(); private final Object traRecLock = new Object();
// DEVICE ATTRIBUTES // DEVICE ATTRIBUTES
...@@ -474,7 +474,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -474,7 +474,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
This is necessary for Receivers retrieved via MidiSystem.getReceiver() This is necessary for Receivers retrieved via MidiSystem.getReceiver()
(which opens the device implicitely). (which opens the device implicitely).
*/ */
protected abstract class AbstractReceiver implements MidiDeviceReceiver { abstract class AbstractReceiver implements MidiDeviceReceiver {
private boolean open = true; private boolean open = true;
...@@ -483,24 +483,24 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -483,24 +483,24 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
Receiver. Therefore, subclasses should not override this method. Receiver. Therefore, subclasses should not override this method.
Instead, they should implement implSend(). Instead, they should implement implSend().
*/ */
public synchronized void send(MidiMessage message, long timeStamp) { @Override
if (open) { public final synchronized void send(final MidiMessage message,
implSend(message, timeStamp); final long timeStamp) {
} else { if (!open) {
throw new IllegalStateException("Receiver is not open"); throw new IllegalStateException("Receiver is not open");
} }
implSend(message, timeStamp);
} }
abstract void implSend(MidiMessage message, long timeStamp);
protected abstract void implSend(MidiMessage message, long timeStamp);
/** Close the Receiver. /** Close the Receiver.
* Here, the call to the magic method closeInternal() takes place. * Here, the call to the magic method closeInternal() takes place.
* Therefore, subclasses that override this method must call * Therefore, subclasses that override this method must call
* 'super.close()'. * 'super.close()'.
*/ */
public void close() { @Override
public final void close() {
open = false; open = false;
synchronized (AbstractMidiDevice.this.traRecLock) { synchronized (AbstractMidiDevice.this.traRecLock) {
AbstractMidiDevice.this.getReceiverList().remove(this); AbstractMidiDevice.this.getReceiverList().remove(this);
...@@ -508,11 +508,12 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice ...@@ -508,11 +508,12 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
AbstractMidiDevice.this.closeInternal(this); AbstractMidiDevice.this.closeInternal(this);
} }
public MidiDevice getMidiDevice() { @Override
public final MidiDevice getMidiDevice() {
return AbstractMidiDevice.this; return AbstractMidiDevice.this;
} }
protected boolean isOpen() { final boolean isOpen() {
return open; return open;
} }
......
...@@ -32,7 +32,7 @@ import javax.sound.midi.*; ...@@ -32,7 +32,7 @@ import javax.sound.midi.*;
* *
* @author Florian Bomers * @author Florian Bomers
*/ */
class FastShortMessage extends ShortMessage { final class FastShortMessage extends ShortMessage {
private int packedMsg; private int packedMsg;
public FastShortMessage(int packedMsg) throws InvalidMidiDataException { public FastShortMessage(int packedMsg) throws InvalidMidiDataException {
......
...@@ -32,7 +32,7 @@ import javax.sound.midi.*; ...@@ -32,7 +32,7 @@ import javax.sound.midi.*;
* *
* @author Florian Bomers * @author Florian Bomers
*/ */
class FastSysexMessage extends SysexMessage { final class FastSysexMessage extends SysexMessage {
FastSysexMessage(byte[] data) throws InvalidMidiDataException { FastSysexMessage(byte[] data) throws InvalidMidiDataException {
super(data); super(data);
......
...@@ -103,9 +103,9 @@ class MidiOutDevice extends AbstractMidiDevice { ...@@ -103,9 +103,9 @@ class MidiOutDevice extends AbstractMidiDevice {
class MidiOutReceiver extends AbstractReceiver { class MidiOutReceiver extends AbstractReceiver {
protected void implSend(MidiMessage message, long timeStamp) { void implSend(final MidiMessage message, final long timeStamp) {
int length = message.getLength(); final int length = message.getLength();
int status = message.getStatus(); final int status = message.getStatus();
if (length <= 3 && status != 0xF0 && status != 0xF7) { if (length <= 3 && status != 0xF0 && status != 0xF7) {
int packedMsg; int packedMsg;
if (message instanceof ShortMessage) { if (message instanceof ShortMessage) {
...@@ -140,11 +140,15 @@ class MidiOutDevice extends AbstractMidiDevice { ...@@ -140,11 +140,15 @@ class MidiOutDevice extends AbstractMidiDevice {
} }
nSendShortMessage(id, packedMsg, timeStamp); nSendShortMessage(id, packedMsg, timeStamp);
} else { } else {
final byte[] data;
if (message instanceof FastSysexMessage) { if (message instanceof FastSysexMessage) {
nSendLongMessage(id, ((FastSysexMessage) message).getReadOnlyMessage(), data = ((FastSysexMessage) message).getReadOnlyMessage();
length, timeStamp);
} else { } else {
nSendLongMessage(id, message.getMessage(), length, timeStamp); data = message.getMessage();
}
final int dataLength = Math.min(length, data.length);
if (dataLength > 0) {
nSendLongMessage(id, data, dataLength, timeStamp);
} }
} }
} }
......
...@@ -1026,7 +1026,7 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon ...@@ -1026,7 +1026,7 @@ class RealTimeSequencer extends AbstractMidiDevice implements Sequencer, AutoCon
class SequencerReceiver extends AbstractReceiver { class SequencerReceiver extends AbstractReceiver {
protected void implSend(MidiMessage message, long timeStamp) { void implSend(MidiMessage message, long timeStamp) {
if (recording) { if (recording) {
long tickPos = 0; long tickPos = 0;
......
/* /*
* Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 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
...@@ -2234,7 +2234,7 @@ public class Window extends Container implements Accessible { ...@@ -2234,7 +2234,7 @@ public class Window extends Container implements Accessible {
WindowPeer peer = (WindowPeer)this.peer; WindowPeer peer = (WindowPeer)this.peer;
synchronized(getTreeLock()) { synchronized(getTreeLock()) {
if (peer != null) { if (peer != null) {
peer.setAlwaysOnTop(alwaysOnTop); peer.updateAlwaysOnTopState();
} }
} }
} }
......
/* /*
* Copyright (c) 1995, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1995, 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
...@@ -53,15 +53,14 @@ public interface WindowPeer extends ContainerPeer { ...@@ -53,15 +53,14 @@ public interface WindowPeer extends ContainerPeer {
void toBack(); void toBack();
/** /**
* Sets if the window should always stay on top of all other windows or * Updates the window's always-on-top state.
* not. * Sets if the window should always stay
* * on top of all other windows or not.
* @param alwaysOnTop if the window should always stay on top of all other
* windows or not
* *
* @see Window#getAlwaysOnTop()
* @see Window#setAlwaysOnTop(boolean) * @see Window#setAlwaysOnTop(boolean)
*/ */
void setAlwaysOnTop(boolean alwaysOnTop); void updateAlwaysOnTopState();
/** /**
* Updates the window's focusable state. * Updates the window's focusable state.
......
/* /*
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 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
...@@ -29,7 +29,6 @@ import com.sun.beans.finder.BeanInfoFinder; ...@@ -29,7 +29,6 @@ import com.sun.beans.finder.BeanInfoFinder;
import com.sun.beans.finder.PropertyEditorFinder; import com.sun.beans.finder.PropertyEditorFinder;
import java.awt.GraphicsEnvironment; import java.awt.GraphicsEnvironment;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.WeakHashMap; import java.util.WeakHashMap;
...@@ -42,7 +41,7 @@ import java.util.WeakHashMap; ...@@ -42,7 +41,7 @@ import java.util.WeakHashMap;
*/ */
final class ThreadGroupContext { final class ThreadGroupContext {
private static final Map<ThreadGroup, ThreadGroupContext> contexts = new WeakHashMap<>(); private static final WeakIdentityMap<ThreadGroupContext> contexts = new WeakIdentityMap<>();
/** /**
* Returns the appropriate {@code AppContext} for the caller, * Returns the appropriate {@code AppContext} for the caller,
...@@ -69,6 +68,8 @@ final class ThreadGroupContext { ...@@ -69,6 +68,8 @@ final class ThreadGroupContext {
private BeanInfoFinder beanInfoFinder; private BeanInfoFinder beanInfoFinder;
private PropertyEditorFinder propertyEditorFinder; private PropertyEditorFinder propertyEditorFinder;
private ThreadGroupContext() {
}
boolean isDesignTime() { boolean isDesignTime() {
return this.isDesignTime; return this.isDesignTime;
......
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package java.beans;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
/**
* Hash table based mapping, which uses weak references to store keys
* and reference-equality in place of object-equality to compare them.
* An entry will automatically be removed when its key is no longer
* in ordinary use. Both null values and the null key are supported.
*
* @see java.util.IdentityHashMap
* @see java.util.WeakHashMap
*/
final class WeakIdentityMap<T> {
private static final int MAXIMUM_CAPACITY = 1 << 30; // it MUST be a power of two
private static final Object NULL = new Object(); // special object for null key
private final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
private Entry<T>[] table = newTable(1<<3); // table's length MUST be a power of two
private int threshold = 6; // the next size value at which to resize
private int size = 0; // the number of key-value mappings
public T get(Object key) {
removeStaleEntries();
if (key == null) {
key = NULL;
}
int hash = key.hashCode();
int index = getIndex(this.table, hash);
for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
if (entry.isMatched(key, hash)) {
return entry.value;
}
}
return null;
}
public T put(Object key, T value) {
removeStaleEntries();
if (key == null) {
key = NULL;
}
int hash = key.hashCode();
int index = getIndex(this.table, hash);
for (Entry<T> entry = this.table[index]; entry != null; entry = entry.next) {
if (entry.isMatched(key, hash)) {
T oldValue = entry.value;
entry.value = value;
return oldValue;
}
}
this.table[index] = new Entry<T>(key, hash, value, this.queue, this.table[index]);
if (++this.size >= this.threshold) {
if (this.table.length == MAXIMUM_CAPACITY) {
this.threshold = Integer.MAX_VALUE;
}
else {
removeStaleEntries();
Entry<T>[] table = newTable(this.table.length * 2);
transfer(this.table, table);
// If ignoring null elements and processing ref queue caused massive
// shrinkage, then restore old table. This should be rare, but avoids
// unbounded expansion of garbage-filled tables.
if (this.size >= this.threshold / 2) {
this.table = table;
this.threshold *= 2;
}
else {
transfer(table, this.table);
}
}
}
return null;
}
private void removeStaleEntries() {
for (Object ref = this.queue.poll(); ref != null; ref = this.queue.poll()) {
@SuppressWarnings("unchecked")
Entry<T> entry = (Entry<T>) ref;
int index = getIndex(this.table, entry.hash);
Entry<T> prev = this.table[index];
Entry<T> current = prev;
while (current != null) {
Entry<T> next = current.next;
if (current == entry) {
if (prev == entry) {
this.table[index] = next;
}
else {
prev.next = next;
}
entry.value = null; // Help GC
entry.next = null; // Help GC
this.size--;
break;
}
prev = current;
current = next;
}
}
}
private void transfer(Entry<T>[] oldTable, Entry<T>[] newTable) {
for (int i = 0; i < oldTable.length; i++) {
Entry<T> entry = oldTable[i];
oldTable[i] = null;
while (entry != null) {
Entry<T> next = entry.next;
Object key = entry.get();
if (key == null) {
entry.value = null; // Help GC
entry.next = null; // Help GC
this.size--;
}
else {
int index = getIndex(newTable, entry.hash);
entry.next = newTable[index];
newTable[index] = entry;
}
entry = next;
}
}
}
@SuppressWarnings("unchecked")
private Entry<T>[] newTable(int length) {
return (Entry<T>[]) new Entry<?>[length];
}
private static int getIndex(Entry<?>[] table, int hash) {
return hash & (table.length - 1);
}
private static class Entry<T> extends WeakReference<Object> {
private final int hash;
private T value;
private Entry<T> next;
Entry(Object key, int hash, T value, ReferenceQueue<Object> queue, Entry<T> next) {
super(key, queue);
this.hash = hash;
this.value = value;
this.next = next;
}
boolean isMatched(Object key, int hash) {
return (this.hash == hash) && (key == get());
}
}
}
...@@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -41,6 +41,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import static java.io.ObjectStreamClass.processQueue; import static java.io.ObjectStreamClass.processQueue;
import sun.reflect.misc.ReflectUtil;
/** /**
* An ObjectInputStream deserializes primitive data and objects previously * An ObjectInputStream deserializes primitive data and objects previously
...@@ -1519,6 +1520,12 @@ public class ObjectInputStream ...@@ -1519,6 +1520,12 @@ public class ObjectInputStream
} }
} }
private boolean isCustomSubclass() {
// Return true if this class is a custom subclass of ObjectInputStream
return getClass().getClassLoader()
!= ObjectInputStream.class.getClassLoader();
}
/** /**
* Reads in and returns class descriptor for a dynamic proxy class. Sets * Reads in and returns class descriptor for a dynamic proxy class. Sets
* passHandle to proxy class descriptor's assigned handle. If proxy class * passHandle to proxy class descriptor's assigned handle. If proxy class
...@@ -1548,6 +1555,15 @@ public class ObjectInputStream ...@@ -1548,6 +1555,15 @@ public class ObjectInputStream
try { try {
if ((cl = resolveProxyClass(ifaces)) == null) { if ((cl = resolveProxyClass(ifaces)) == null) {
resolveEx = new ClassNotFoundException("null class"); resolveEx = new ClassNotFoundException("null class");
} else if (!Proxy.isProxyClass(cl)) {
throw new InvalidClassException("Not a proxy");
} else {
// ReflectUtil.checkProxyPackageAccess makes a test
// equivalent to isCustomSubclass so there's no need
// to condition this call to isCustomSubclass == true here.
ReflectUtil.checkProxyPackageAccess(
getClass().getClassLoader(),
cl.getInterfaces());
} }
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
resolveEx = ex; resolveEx = ex;
...@@ -1589,9 +1605,12 @@ public class ObjectInputStream ...@@ -1589,9 +1605,12 @@ public class ObjectInputStream
Class<?> cl = null; Class<?> cl = null;
ClassNotFoundException resolveEx = null; ClassNotFoundException resolveEx = null;
bin.setBlockDataMode(true); bin.setBlockDataMode(true);
final boolean checksRequired = isCustomSubclass();
try { try {
if ((cl = resolveClass(readDesc)) == null) { if ((cl = resolveClass(readDesc)) == null) {
resolveEx = new ClassNotFoundException("null class"); resolveEx = new ClassNotFoundException("null class");
} else if (checksRequired) {
ReflectUtil.checkPackageAccess(cl);
} }
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
resolveEx = ex; resolveEx = ex;
......
...@@ -30,6 +30,7 @@ import java.io.IOException; ...@@ -30,6 +30,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.security.AccessControlException;
import java.util.Arrays; import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -1024,13 +1025,24 @@ public final class ProcessBuilder ...@@ -1024,13 +1025,24 @@ public final class ProcessBuilder
redirects, redirects,
redirectErrorStream); redirectErrorStream);
} catch (IOException e) { } catch (IOException e) {
String exceptionInfo = ": " + e.getMessage();
Throwable cause = e;
if (security != null) {
// Can not disclose the fail reason for read-protected files.
try {
security.checkRead(prog);
} catch (AccessControlException ace) {
exceptionInfo = "";
cause = ace;
}
}
// It's much easier for us to create a high-quality error // It's much easier for us to create a high-quality error
// message than the low-level C code which found the problem. // message than the low-level C code which found the problem.
throw new IOException( throw new IOException(
"Cannot run program \"" + prog + "\"" "Cannot run program \"" + prog + "\""
+ (dir == null ? "" : " (in directory \"" + dir + "\")") + (dir == null ? "" : " (in directory \"" + dir + "\")")
+ ": " + e.getMessage(), + exceptionInfo,
e); cause);
} }
} }
} }
...@@ -1237,6 +1237,30 @@ return mh1; ...@@ -1237,6 +1237,30 @@ return mh1;
checkMethod(refKind, refc, method); checkMethod(refKind, refc, method);
if (method.isMethodHandleInvoke()) if (method.isMethodHandleInvoke())
return fakeMethodHandleInvoke(method); return fakeMethodHandleInvoke(method);
Class<?> refcAsSuper;
if (refKind == REF_invokeSpecial &&
refc != lookupClass() &&
refc != (refcAsSuper = lookupClass().getSuperclass()) &&
refc.isAssignableFrom(lookupClass())) {
assert(!method.getName().equals("<init>")); // not this code path
// Per JVMS 6.5, desc. of invokespecial instruction:
// If the method is in a superclass of the LC,
// and if our original search was above LC.super,
// repeat the search (symbolic lookup) from LC.super.
// FIXME: MemberName.resolve should handle this instead.
MemberName m2 = new MemberName(refcAsSuper,
method.getName(),
method.getMethodType(),
REF_invokeSpecial);
m2 = IMPL_NAMES.resolveOrNull(refKind, m2, lookupClassOrNull());
if (m2 == null) throw new InternalError(method.toString());
method = m2;
refc = refcAsSuper;
// redo basic checks
checkMethod(refKind, refc, method);
}
MethodHandle mh = DirectMethodHandle.make(refKind, refc, method); MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
mh = maybeBindCaller(method, mh, callerClass); mh = maybeBindCaller(method, mh, callerClass);
mh = mh.setVarargs(method); mh = mh.setVarargs(method);
......
...@@ -38,9 +38,9 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -38,9 +38,9 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
*/ */
static native void invokeFinalizeMethod(Object o) throws Throwable; static native void invokeFinalizeMethod(Object o) throws Throwable;
static private ReferenceQueue queue = new ReferenceQueue(); private static ReferenceQueue queue = new ReferenceQueue();
static private Finalizer unfinalized = null; private static Finalizer unfinalized = null;
static private Object lock = new Object(); private static final Object lock = new Object();
private Finalizer private Finalizer
next = null, next = null,
...@@ -142,7 +142,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -142,7 +142,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
/* Called by Runtime.runFinalization() */ /* Called by Runtime.runFinalization() */
static void runFinalization() { static void runFinalization() {
forkSecondaryFinalizer(new Runnable() { forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() { public void run() {
if (running)
return;
running = true;
for (;;) { for (;;) {
Finalizer f = (Finalizer)queue.poll(); Finalizer f = (Finalizer)queue.poll();
if (f == null) break; if (f == null) break;
...@@ -155,7 +159,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -155,7 +159,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
/* Invoked by java.lang.Shutdown */ /* Invoked by java.lang.Shutdown */
static void runAllFinalizers() { static void runAllFinalizers() {
forkSecondaryFinalizer(new Runnable() { forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() { public void run() {
if (running)
return;
running = true;
for (;;) { for (;;) {
Finalizer f; Finalizer f;
synchronized (lock) { synchronized (lock) {
...@@ -168,10 +176,14 @@ final class Finalizer extends FinalReference { /* Package-private; must be in ...@@ -168,10 +176,14 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
} }
private static class FinalizerThread extends Thread { private static class FinalizerThread extends Thread {
private volatile boolean running;
FinalizerThread(ThreadGroup g) { FinalizerThread(ThreadGroup g) {
super(g, "Finalizer"); super(g, "Finalizer");
} }
public void run() { public void run() {
if (running)
return;
running = true;
for (;;) { for (;;) {
try { try {
Finalizer f = (Finalizer)queue.remove(); Finalizer f = (Finalizer)queue.remove();
......
...@@ -122,7 +122,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl ...@@ -122,7 +122,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
* not connected already. * not connected already.
*/ */
protected void disconnect() { protected void disconnect() {
disconnect0(connectedAddress.family); disconnect0(connectedAddress.holder().getFamily());
connected = false; connected = false;
connectedAddress = null; connectedAddress = null;
connectedPort = -1; connectedPort = -1;
......
...@@ -100,27 +100,28 @@ class Inet4Address extends InetAddress { ...@@ -100,27 +100,28 @@ class Inet4Address extends InetAddress {
Inet4Address() { Inet4Address() {
super(); super();
hostName = null; holder().hostName = null;
address = 0; holder().address = 0;
family = IPv4; holder().family = IPv4;
} }
Inet4Address(String hostName, byte addr[]) { Inet4Address(String hostName, byte addr[]) {
this.hostName = hostName; holder().hostName = hostName;
this.family = IPv4; holder().family = IPv4;
if (addr != null) { if (addr != null) {
if (addr.length == INADDRSZ) { if (addr.length == INADDRSZ) {
address = addr[3] & 0xFF; int address = addr[3] & 0xFF;
address |= ((addr[2] << 8) & 0xFF00); address |= ((addr[2] << 8) & 0xFF00);
address |= ((addr[1] << 16) & 0xFF0000); address |= ((addr[1] << 16) & 0xFF0000);
address |= ((addr[0] << 24) & 0xFF000000); address |= ((addr[0] << 24) & 0xFF000000);
holder().address = address;
} }
} }
} }
Inet4Address(String hostName, int address) { Inet4Address(String hostName, int address) {
this.hostName = hostName; holder().hostName = hostName;
this.family = IPv4; holder().family = IPv4;
this.address = address; holder().address = address;
} }
/** /**
...@@ -134,8 +135,8 @@ class Inet4Address extends InetAddress { ...@@ -134,8 +135,8 @@ class Inet4Address extends InetAddress {
private Object writeReplace() throws ObjectStreamException { private Object writeReplace() throws ObjectStreamException {
// will replace the to be serialized 'this' object // will replace the to be serialized 'this' object
InetAddress inet = new InetAddress(); InetAddress inet = new InetAddress();
inet.hostName = this.hostName; inet.holder().hostName = holder().getHostName();
inet.address = this.address; inet.holder().address = holder().getAddress();
/** /**
* Prior to 1.4 an InetAddress was created with a family * Prior to 1.4 an InetAddress was created with a family
...@@ -143,7 +144,7 @@ class Inet4Address extends InetAddress { ...@@ -143,7 +144,7 @@ class Inet4Address extends InetAddress {
* For compatibility reasons we must therefore write the * For compatibility reasons we must therefore write the
* the InetAddress with this family. * the InetAddress with this family.
*/ */
inet.family = 2; inet.holder().family = 2;
return inet; return inet;
} }
...@@ -157,7 +158,7 @@ class Inet4Address extends InetAddress { ...@@ -157,7 +158,7 @@ class Inet4Address extends InetAddress {
* @since JDK1.1 * @since JDK1.1
*/ */
public boolean isMulticastAddress() { public boolean isMulticastAddress() {
return ((address & 0xf0000000) == 0xe0000000); return ((holder().getAddress() & 0xf0000000) == 0xe0000000);
} }
/** /**
...@@ -167,7 +168,7 @@ class Inet4Address extends InetAddress { ...@@ -167,7 +168,7 @@ class Inet4Address extends InetAddress {
* @since 1.4 * @since 1.4
*/ */
public boolean isAnyLocalAddress() { public boolean isAnyLocalAddress() {
return address == 0; return holder().getAddress() == 0;
} }
/** /**
...@@ -195,6 +196,7 @@ class Inet4Address extends InetAddress { ...@@ -195,6 +196,7 @@ class Inet4Address extends InetAddress {
// defined in "Documenting Special Use IPv4 Address Blocks // defined in "Documenting Special Use IPv4 Address Blocks
// that have been Registered with IANA" by Bill Manning // that have been Registered with IANA" by Bill Manning
// draft-manning-dsua-06.txt // draft-manning-dsua-06.txt
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 169) return (((address >>> 24) & 0xFF) == 169)
&& (((address >>> 16) & 0xFF) == 254); && (((address >>> 16) & 0xFF) == 254);
} }
...@@ -211,6 +213,7 @@ class Inet4Address extends InetAddress { ...@@ -211,6 +213,7 @@ class Inet4Address extends InetAddress {
// 10/8 prefix // 10/8 prefix
// 172.16/12 prefix // 172.16/12 prefix
// 192.168/16 prefix // 192.168/16 prefix
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 10) return (((address >>> 24) & 0xFF) == 10)
|| ((((address >>> 24) & 0xFF) == 172) || ((((address >>> 24) & 0xFF) == 172)
&& (((address >>> 16) & 0xF0) == 16)) && (((address >>> 16) & 0xF0) == 16))
...@@ -257,6 +260,7 @@ class Inet4Address extends InetAddress { ...@@ -257,6 +260,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean isMCLinkLocal() { public boolean isMCLinkLocal() {
// 224.0.0/24 prefix and ttl == 1 // 224.0.0/24 prefix and ttl == 1
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 224) return (((address >>> 24) & 0xFF) == 224)
&& (((address >>> 16) & 0xFF) == 0) && (((address >>> 16) & 0xFF) == 0)
&& (((address >>> 8) & 0xFF) == 0); && (((address >>> 8) & 0xFF) == 0);
...@@ -272,6 +276,7 @@ class Inet4Address extends InetAddress { ...@@ -272,6 +276,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean isMCSiteLocal() { public boolean isMCSiteLocal() {
// 239.255/16 prefix or ttl < 32 // 239.255/16 prefix or ttl < 32
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239) return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) == 255); && (((address >>> 16) & 0xFF) == 255);
} }
...@@ -287,6 +292,7 @@ class Inet4Address extends InetAddress { ...@@ -287,6 +292,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean isMCOrgLocal() { public boolean isMCOrgLocal() {
// 239.192 - 239.195 // 239.192 - 239.195
int address = holder().getAddress();
return (((address >>> 24) & 0xFF) == 239) return (((address >>> 24) & 0xFF) == 239)
&& (((address >>> 16) & 0xFF) >= 192) && (((address >>> 16) & 0xFF) >= 192)
&& (((address >>> 16) & 0xFF) <= 195); && (((address >>> 16) & 0xFF) <= 195);
...@@ -300,6 +306,7 @@ class Inet4Address extends InetAddress { ...@@ -300,6 +306,7 @@ class Inet4Address extends InetAddress {
* @return the raw IP address of this object. * @return the raw IP address of this object.
*/ */
public byte[] getAddress() { public byte[] getAddress() {
int address = holder().getAddress();
byte[] addr = new byte[INADDRSZ]; byte[] addr = new byte[INADDRSZ];
addr[0] = (byte) ((address >>> 24) & 0xFF); addr[0] = (byte) ((address >>> 24) & 0xFF);
...@@ -325,7 +332,7 @@ class Inet4Address extends InetAddress { ...@@ -325,7 +332,7 @@ class Inet4Address extends InetAddress {
* @return a hash code value for this IP address. * @return a hash code value for this IP address.
*/ */
public int hashCode() { public int hashCode() {
return address; return holder().getAddress();
} }
/** /**
...@@ -346,7 +353,7 @@ class Inet4Address extends InetAddress { ...@@ -346,7 +353,7 @@ class Inet4Address extends InetAddress {
*/ */
public boolean equals(Object obj) { public boolean equals(Object obj) {
return (obj != null) && (obj instanceof Inet4Address) && return (obj != null) && (obj instanceof Inet4Address) &&
(((InetAddress)obj).address == address); (((InetAddress)obj).holder().getAddress() == holder().getAddress());
} }
// Utilities // Utilities
......
...@@ -40,7 +40,7 @@ class Inet4AddressImpl implements InetAddressImpl { ...@@ -40,7 +40,7 @@ class Inet4AddressImpl implements InetAddressImpl {
public synchronized InetAddress anyLocalAddress() { public synchronized InetAddress anyLocalAddress() {
if (anyLocalAddress == null) { if (anyLocalAddress == null) {
anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00} anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
anyLocalAddress.hostName = "0.0.0.0"; anyLocalAddress.holder().hostName = "0.0.0.0";
} }
return anyLocalAddress; return anyLocalAddress;
} }
......
...@@ -210,18 +210,18 @@ class Inet6Address extends InetAddress { ...@@ -210,18 +210,18 @@ class Inet6Address extends InetAddress {
Inet6Address() { Inet6Address() {
super(); super();
hostName = null; holder().hostName = null;
ipaddress = new byte[INADDRSZ]; ipaddress = new byte[INADDRSZ];
family = IPv6; holder().family = IPv6;
} }
/* checking of value for scope_id should be done by caller /* checking of value for scope_id should be done by caller
* scope_id must be >= 0, or -1 to indicate not being set * scope_id must be >= 0, or -1 to indicate not being set
*/ */
Inet6Address(String hostName, byte addr[], int scope_id) { Inet6Address(String hostName, byte addr[], int scope_id) {
this.hostName = hostName; holder().hostName = hostName;
if (addr.length == INADDRSZ) { // normal IPv6 address if (addr.length == INADDRSZ) { // normal IPv6 address
family = IPv6; holder().family = IPv6;
ipaddress = addr.clone(); ipaddress = addr.clone();
} }
if (scope_id >= 0) { if (scope_id >= 0) {
...@@ -335,9 +335,9 @@ class Inet6Address extends InetAddress { ...@@ -335,9 +335,9 @@ class Inet6Address extends InetAddress {
private void initif(String hostName, byte addr[],NetworkInterface nif) private void initif(String hostName, byte addr[],NetworkInterface nif)
throws UnknownHostException throws UnknownHostException
{ {
this.hostName = hostName; holder().hostName = hostName;
if (addr.length == INADDRSZ) { // normal IPv6 address if (addr.length == INADDRSZ) { // normal IPv6 address
family = IPv6; holder().family = IPv6;
ipaddress = addr.clone(); ipaddress = addr.clone();
} }
if (nif != null) { if (nif != null) {
...@@ -420,6 +420,11 @@ class Inet6Address extends InetAddress { ...@@ -420,6 +420,11 @@ class Inet6Address extends InetAddress {
*/ */
private void readObject(ObjectInputStream s) private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
s.defaultReadObject(); s.defaultReadObject();
if (ifname != null && !ifname.equals("")) { if (ifname != null && !ifname.equals("")) {
...@@ -447,7 +452,7 @@ class Inet6Address extends InetAddress { ...@@ -447,7 +452,7 @@ class Inet6Address extends InetAddress {
ipaddress.length); ipaddress.length);
} }
if (family != IPv6) { if (holder().getFamily() != IPv6) {
throw new InvalidObjectException("invalid address family type"); throw new InvalidObjectException("invalid address family type");
} }
} }
......
...@@ -81,7 +81,7 @@ class Inet6AddressImpl implements InetAddressImpl { ...@@ -81,7 +81,7 @@ class Inet6AddressImpl implements InetAddressImpl {
if (anyLocalAddress == null) { if (anyLocalAddress == null) {
if (InetAddress.preferIPv6Address) { if (InetAddress.preferIPv6Address) {
anyLocalAddress = new Inet6Address(); anyLocalAddress = new Inet6Address();
anyLocalAddress.hostName = "::"; anyLocalAddress.holder().hostName = "::";
} else { } else {
anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress(); anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
} }
......
...@@ -35,8 +35,12 @@ import java.util.ArrayList; ...@@ -35,8 +35,12 @@ import java.util.ArrayList;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import java.security.AccessController; import java.security.AccessController;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
import java.io.IOException; import java.io.IOException;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.io.ObjectInputStream.GetField;
import java.io.ObjectOutputStream;
import java.io.ObjectOutputStream.PutField;
import sun.security.action.*; import sun.security.action.*;
import sun.net.InetAddressCachePolicy; import sun.net.InetAddressCachePolicy;
import sun.net.util.IPAddressUtil; import sun.net.util.IPAddressUtil;
...@@ -199,25 +203,48 @@ class InetAddress implements java.io.Serializable { ...@@ -199,25 +203,48 @@ class InetAddress implements java.io.Serializable {
/* Specify address family preference */ /* Specify address family preference */
static transient boolean preferIPv6Address = false; static transient boolean preferIPv6Address = false;
/** static class InetAddressHolder {
* @serial
*/
String hostName;
/** InetAddressHolder() {}
* Holds a 32-bit IPv4 address.
*
* @serial
*/
int address;
/** InetAddressHolder(String hostName, int address, int family) {
* Specifies the address family type, for instance, '1' for IPv4 this.hostName = hostName;
* addresses, and '2' for IPv6 addresses. this.address = address;
* this.family = family;
* @serial }
*/
int family; String hostName;
String getHostName() {
return hostName;
}
/**
* Holds a 32-bit IPv4 address.
*/
int address;
int getAddress() {
return address;
}
/**
* Specifies the address family type, for instance, '1' for IPv4
* addresses, and '2' for IPv6 addresses.
*/
int family;
int getFamily() {
return family;
}
}
/* Used to store the serializable fields of InetAddress */
private final transient InetAddressHolder holder;
InetAddressHolder holder() {
return holder;
}
/* Used to store the name service provider */ /* Used to store the name service provider */
private static List<NameService> nameServices = null; private static List<NameService> nameServices = null;
...@@ -251,6 +278,7 @@ class InetAddress implements java.io.Serializable { ...@@ -251,6 +278,7 @@ class InetAddress implements java.io.Serializable {
* put in the address cache, since it is not created by name. * put in the address cache, since it is not created by name.
*/ */
InetAddress() { InetAddress() {
holder = new InetAddressHolder();
} }
/** /**
...@@ -263,7 +291,7 @@ class InetAddress implements java.io.Serializable { ...@@ -263,7 +291,7 @@ class InetAddress implements java.io.Serializable {
*/ */
private Object readResolve() throws ObjectStreamException { private Object readResolve() throws ObjectStreamException {
// will replace the deserialized 'this' object // will replace the deserialized 'this' object
return new Inet4Address(this.hostName, this.address); return new Inet4Address(holder().getHostName(), holder().getAddress());
} }
/** /**
...@@ -500,10 +528,10 @@ class InetAddress implements java.io.Serializable { ...@@ -500,10 +528,10 @@ class InetAddress implements java.io.Serializable {
* @see SecurityManager#checkConnect * @see SecurityManager#checkConnect
*/ */
String getHostName(boolean check) { String getHostName(boolean check) {
if (hostName == null) { if (holder().getHostName() == null) {
hostName = InetAddress.getHostFromNameService(this, check); holder().hostName = InetAddress.getHostFromNameService(this, check);
} }
return hostName; return holder().getHostName();
} }
/** /**
...@@ -666,6 +694,7 @@ class InetAddress implements java.io.Serializable { ...@@ -666,6 +694,7 @@ class InetAddress implements java.io.Serializable {
* @return a string representation of this IP address. * @return a string representation of this IP address.
*/ */
public String toString() { public String toString() {
String hostName = holder().getHostName();
return ((hostName != null) ? hostName : "") return ((hostName != null) ? hostName : "")
+ "/" + getHostAddress(); + "/" + getHostAddress();
} }
...@@ -1522,14 +1551,58 @@ class InetAddress implements java.io.Serializable { ...@@ -1522,14 +1551,58 @@ class InetAddress implements java.io.Serializable {
} }
} }
private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE;
static {
try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset(
InetAddress.class.getDeclaredField("holder")
);
UNSAFE = unsafe;
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private void readObject (ObjectInputStream s) throws private void readObject (ObjectInputStream s) throws
IOException, ClassNotFoundException { IOException, ClassNotFoundException {
s.defaultReadObject ();
if (getClass().getClassLoader() != null) { if (getClass().getClassLoader() != null) {
hostName = null;
address = 0;
throw new SecurityException ("invalid address type"); throw new SecurityException ("invalid address type");
} }
GetField gf = s.readFields();
String host = (String)gf.get("hostName", null);
int address= gf.get("address", 0);
int family= gf.get("family", 0);
InetAddressHolder h = new InetAddressHolder(host, address, family);
UNSAFE.putObject(this, FIELDS_OFFSET, h);
}
/* needed because the serializable fields no longer exist */
/**
* @serialField hostName String
* @serialField address int
* @serialField family int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("hostName", String.class),
new ObjectStreamField("address", int.class),
new ObjectStreamField("family", int.class),
};
private void writeObject (ObjectOutputStream s) throws
IOException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
PutField pf = s.putFields();
pf.put("hostName", holder().getHostName());
pf.put("address", holder().getAddress());
pf.put("family", holder().getFamily());
s.writeFields();
s.flush();
} }
} }
......
...@@ -87,8 +87,8 @@ public class InetSocketAddress ...@@ -87,8 +87,8 @@ public class InetSocketAddress
if (hostname != null) if (hostname != null)
return hostname; return hostname;
if (addr != null) { if (addr != null) {
if (addr.hostName != null) if (addr.holder().getHostName() != null)
return addr.hostName; return addr.holder().getHostName();
else else
return addr.getHostAddress(); return addr.getHostAddress();
} }
......
/* /*
* Copyright (c) 1996, 2011, 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
...@@ -120,6 +120,13 @@ public class LogStream extends PrintStream { ...@@ -120,6 +120,13 @@ public class LogStream extends PrintStream {
*/ */
@Deprecated @Deprecated
public static synchronized void setDefaultStream(PrintStream newDefault) { public static synchronized void setDefaultStream(PrintStream newDefault) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new java.util.logging.LoggingPermission("control", null));
}
defaultStream = newDefault; defaultStream = newDefault;
} }
......
...@@ -556,7 +556,7 @@ public class DriverManager { ...@@ -556,7 +556,7 @@ public class DriverManager {
*/ */
try{ try{
while(driversIterator.hasNext()) { while(driversIterator.hasNext()) {
println(" Loading done by the java.util.ServiceLoader : "+driversIterator.next()); driversIterator.next();
} }
} catch(Throwable t) { } catch(Throwable t) {
// Do nothing // Do nothing
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
*/ */
package java.util.concurrent; package java.util.concurrent;
import java.io.ObjectInputStream;
import java.util.concurrent.locks.*; import java.util.concurrent.locks.*;
import java.util.*; import java.util.*;
import java.io.Serializable; import java.io.Serializable;
...@@ -1483,7 +1484,23 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> ...@@ -1483,7 +1484,23 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void readObject(java.io.ObjectInputStream s) private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException { throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject(); // Don't call defaultReadObject()
ObjectInputStream.GetField oisFields = s.readFields();
final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null);
final int ssize = oisSegments.length;
if (ssize < 1 || ssize > MAX_SEGMENTS
|| (ssize & (ssize-1)) != 0 ) // ssize not power of two
throw new java.io.InvalidObjectException("Bad number of segments:"
+ ssize);
int sshift = 0, ssizeTmp = ssize;
while (ssizeTmp > 1) {
++sshift;
ssizeTmp >>>= 1;
}
UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift);
UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1);
UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments);
// set hashMask // set hashMask
UNSAFE.putIntVolatile(this, HASHSEED_OFFSET, UNSAFE.putIntVolatile(this, HASHSEED_OFFSET,
...@@ -1517,6 +1534,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> ...@@ -1517,6 +1534,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
private static final long TBASE; private static final long TBASE;
private static final int TSHIFT; private static final int TSHIFT;
private static final long HASHSEED_OFFSET; private static final long HASHSEED_OFFSET;
private static final long SEGSHIFT_OFFSET;
private static final long SEGMASK_OFFSET;
private static final long SEGMENTS_OFFSET;
static { static {
int ss, ts; int ss, ts;
...@@ -1530,6 +1550,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V> ...@@ -1530,6 +1550,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
ss = UNSAFE.arrayIndexScale(sc); ss = UNSAFE.arrayIndexScale(sc);
HASHSEED_OFFSET = UNSAFE.objectFieldOffset( HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("hashSeed")); ConcurrentHashMap.class.getDeclaredField("hashSeed"));
SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("segmentShift"));
SEGMASK_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("segmentMask"));
SEGMENTS_OFFSET = UNSAFE.objectFieldOffset(
ConcurrentHashMap.class.getDeclaredField("segments"));
} catch (Exception e) { } catch (Exception e) {
throw new Error(e); throw new Error(e);
} }
......
...@@ -539,7 +539,7 @@ public abstract class EmbeddedFrame extends Frame ...@@ -539,7 +539,7 @@ public abstract class EmbeddedFrame extends Frame
public void toBack() {} public void toBack() {}
public void updateFocusableWindowState() {} public void updateFocusableWindowState() {}
public void updateAlwaysOnTop() {} public void updateAlwaysOnTop() {}
public void setAlwaysOnTop(boolean alwaysOnTop) {} public void updateAlwaysOnTopState() {}
public Component getGlobalHeavyweightFocusOwner() { return null; } public Component getGlobalHeavyweightFocusOwner() { return null; }
public void setBoundsPrivate(int x, int y, int width, int height) { public void setBoundsPrivate(int x, int y, int width, int height) {
setBounds(x, y, width, height, SET_BOUNDS); setBounds(x, y, width, height, SET_BOUNDS);
......
...@@ -102,11 +102,11 @@ public class TransferableProxy implements Transferable { ...@@ -102,11 +102,11 @@ public class TransferableProxy implements Transferable {
protected final boolean isLocal; protected final boolean isLocal;
} }
class ClassLoaderObjectOutputStream extends ObjectOutputStream { final class ClassLoaderObjectOutputStream extends ObjectOutputStream {
private final Map<Set<String>, ClassLoader> map = private final Map<Set<String>, ClassLoader> map =
new HashMap<Set<String>, ClassLoader>(); new HashMap<Set<String>, ClassLoader>();
public ClassLoaderObjectOutputStream(OutputStream os) throws IOException { ClassLoaderObjectOutputStream(OutputStream os) throws IOException {
super(os); super(os);
} }
...@@ -140,16 +140,16 @@ class ClassLoaderObjectOutputStream extends ObjectOutputStream { ...@@ -140,16 +140,16 @@ class ClassLoaderObjectOutputStream extends ObjectOutputStream {
map.put(s, classLoader); map.put(s, classLoader);
} }
public Map<Set<String>, ClassLoader> getClassLoaderMap() { Map<Set<String>, ClassLoader> getClassLoaderMap() {
return new HashMap(map); return new HashMap(map);
} }
} }
class ClassLoaderObjectInputStream extends ObjectInputStream { final class ClassLoaderObjectInputStream extends ObjectInputStream {
private final Map<Set<String>, ClassLoader> map; private final Map<Set<String>, ClassLoader> map;
public ClassLoaderObjectInputStream(InputStream is, ClassLoaderObjectInputStream(InputStream is,
Map<Set<String>, ClassLoader> map) Map<Set<String>, ClassLoader> map)
throws IOException { throws IOException {
super(is); super(is);
if (map == null) { if (map == null) {
...@@ -166,8 +166,11 @@ class ClassLoaderObjectInputStream extends ObjectInputStream { ...@@ -166,8 +166,11 @@ class ClassLoaderObjectInputStream extends ObjectInputStream {
s.add(className); s.add(className);
ClassLoader classLoader = map.get(s); ClassLoader classLoader = map.get(s);
if (classLoader != null) {
return Class.forName(className, false, classLoader); return Class.forName(className, false, classLoader);
} else {
return super.resolveClass(classDesc);
}
} }
protected Class<?> resolveProxyClass(String[] interfaces) protected Class<?> resolveProxyClass(String[] interfaces)
...@@ -179,6 +182,9 @@ class ClassLoaderObjectInputStream extends ObjectInputStream { ...@@ -179,6 +182,9 @@ class ClassLoaderObjectInputStream extends ObjectInputStream {
} }
ClassLoader classLoader = map.get(s); ClassLoader classLoader = map.get(s);
if (classLoader == null) {
return super.resolveProxyClass(interfaces);
}
// The code below is mostly copied from the superclass. // The code below is mostly copied from the superclass.
ClassLoader nonPublicLoader = null; ClassLoader nonPublicLoader = null;
......
...@@ -868,6 +868,15 @@ public class ByteComponentRaster extends SunWritableRaster { ...@@ -868,6 +868,15 @@ public class ByteComponentRaster extends SunWritableRaster {
* or if data buffer has not enough capacity. * or if data buffer has not enough capacity.
*/ */
protected final void verify() { protected final void verify() {
/* Need to re-verify the dimensions since a sample model may be
* specified to the constructor
*/
if (width <= 0 || height <= 0 ||
height > (Integer.MAX_VALUE / width))
{
throw new RasterFormatException("Invalid raster dimension");
}
for (int i = 0; i < dataOffsets.length; i++) { for (int i = 0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) { if (dataOffsets[i] < 0) {
throw new RasterFormatException("Data offsets for band " + i throw new RasterFormatException("Data offsets for band " + i
...@@ -905,13 +914,14 @@ public class ByteComponentRaster extends SunWritableRaster { ...@@ -905,13 +914,14 @@ public class ByteComponentRaster extends SunWritableRaster {
lastPixelOffset += lastScanOffset; lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) { for (int i = 0; i < numDataElements; i++) {
size = lastPixelOffset + dataOffsets[i];
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: " throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]); + dataOffsets[i]);
} }
size = lastPixelOffset + dataOffsets[i];
if (size > maxSize) { if (size > maxSize) {
maxSize = size; maxSize = size;
} }
......
...@@ -1368,11 +1368,35 @@ public class BytePackedRaster extends SunWritableRaster { ...@@ -1368,11 +1368,35 @@ public class BytePackedRaster extends SunWritableRaster {
throw new RasterFormatException("Data offsets must be >= 0"); throw new RasterFormatException("Data offsets must be >= 0");
} }
/* Need to re-verify the dimensions since a sample model may be
* specified to the constructor
*/
if (width <= 0 || height <= 0 ||
height > (Integer.MAX_VALUE / width))
{
throw new RasterFormatException("Invalid raster dimension");
}
/*
* pixelBitstride was verified in constructor, so just make
* sure that it is safe to multiply it by width.
*/
if ((width - 1) > Integer.MAX_VALUE / pixelBitStride) {
throw new RasterFormatException("Invalid raster dimension");
}
if (scanlineStride < 0 ||
scanlineStride > (Integer.MAX_VALUE / height))
{
throw new RasterFormatException("Invalid scanline stride");
}
int lastbit = (dataBitOffset int lastbit = (dataBitOffset
+ (height-1) * scanlineStride * 8 + (height-1) * scanlineStride * 8
+ (width-1) * pixelBitStride + (width-1) * pixelBitStride
+ pixelBitStride - 1); + pixelBitStride - 1);
if (lastbit / 8 >= data.length) { if (lastbit < 0 || lastbit / 8 >= data.length) {
throw new RasterFormatException("raster dimensions overflow " + throw new RasterFormatException("raster dimensions overflow " +
"array bounds"); "array bounds");
} }
......
...@@ -333,10 +333,10 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer ...@@ -333,10 +333,10 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer
hints = h; hints = h;
} }
private native void setICMpixels(int x, int y, int w, int h, int[] lut, private native boolean setICMpixels(int x, int y, int w, int h, int[] lut,
byte[] pix, int off, int scansize, byte[] pix, int off, int scansize,
IntegerComponentRaster ict); IntegerComponentRaster ict);
private native int setDiffICM(int x, int y, int w, int h, int[] lut, private native boolean setDiffICM(int x, int y, int w, int h, int[] lut,
int transPix, int numLut, IndexColorModel icm, int transPix, int numLut, IndexColorModel icm,
byte[] pix, int off, int scansize, byte[] pix, int off, int scansize,
ByteComponentRaster bct, int chanOff); ByteComponentRaster bct, int chanOff);
...@@ -426,10 +426,10 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer ...@@ -426,10 +426,10 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer
IndexColorModel icm = (IndexColorModel) model; IndexColorModel icm = (IndexColorModel) model;
ByteComponentRaster bct = (ByteComponentRaster) biRaster; ByteComponentRaster bct = (ByteComponentRaster) biRaster;
int numlut = numSrcLUT; int numlut = numSrcLUT;
if (setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex, if (!setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
numSrcLUT, icm, numSrcLUT, icm,
pix, off, scansize, bct, pix, off, scansize, bct,
bct.getDataOffset(0)) == 0) { bct.getDataOffset(0))) {
convertToRGB(); convertToRGB();
} }
else { else {
...@@ -470,9 +470,14 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer ...@@ -470,9 +470,14 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer
if (s_useNative) { if (s_useNative) {
// Note that setICMpixels modifies the raster directly // Note that setICMpixels modifies the raster directly
// so we must mark it as changed afterwards // so we must mark it as changed afterwards
setICMpixels(x, y, w, h, srcLUT, pix, off, scansize, if (setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
iraster); iraster))
iraster.markDirty(); {
iraster.markDirty();
} else {
abort();
return;
}
} }
else { else {
int[] storage = new int[w*h]; int[] storage = new int[w*h];
......
...@@ -208,7 +208,7 @@ public class IntegerComponentRaster extends SunWritableRaster { ...@@ -208,7 +208,7 @@ public class IntegerComponentRaster extends SunWritableRaster {
" SinglePixelPackedSampleModel"); " SinglePixelPackedSampleModel");
} }
verify(false); verify();
} }
...@@ -629,16 +629,26 @@ public class IntegerComponentRaster extends SunWritableRaster { ...@@ -629,16 +629,26 @@ public class IntegerComponentRaster extends SunWritableRaster {
} }
/** /**
* Verify that the layout parameters are consistent with * Verify that the layout parameters are consistent with the data.
* the data. If strictCheck *
* is false, this method will check for ArrayIndexOutOfBounds conditions. If * The method verifies whether scanline stride and pixel stride do not
* strictCheck is true, this method will check for additional error * cause an integer overflow during calculation of a position of the pixel
* conditions such as line wraparound (width of a line greater than * in data buffer. It also verifies whether the data buffer has enough data
* the scanline stride). * to correspond the raster layout attributes.
* @return String Error string, if the layout is incompatible with *
* the data. Otherwise returns null. * @throws RasterFormatException if an integer overflow is detected,
* or if data buffer has not enough capacity.
*/ */
private void verify (boolean strictCheck) { protected final void verify() {
/* Need to re-verify the dimensions since a sample model may be
* specified to the constructor
*/
if (width <= 0 || height <= 0 ||
height > (Integer.MAX_VALUE / width))
{
throw new RasterFormatException("Invalid raster dimension");
}
if (dataOffsets[0] < 0) { if (dataOffsets[0] < 0) {
throw new RasterFormatException("Data offset ("+dataOffsets[0]+ throw new RasterFormatException("Data offset ("+dataOffsets[0]+
") must be >= 0"); ") must be >= 0");
...@@ -647,17 +657,46 @@ public class IntegerComponentRaster extends SunWritableRaster { ...@@ -647,17 +657,46 @@ public class IntegerComponentRaster extends SunWritableRaster {
int maxSize = 0; int maxSize = 0;
int size; int size;
for (int i=0; i < numDataElements; i++) { // we can be sure that width and height are greater than 0
size = (height-1)*scanlineStride + (width-1)*pixelStride + if (scanlineStride < 0 ||
dataOffsets[i]; scanlineStride > (Integer.MAX_VALUE / height))
{
// integer overflow
throw new RasterFormatException("Incorrect scanline stride: "
+ scanlineStride);
}
int lastScanOffset = (height - 1) * scanlineStride;
if (pixelStride < 0 ||
pixelStride > (Integer.MAX_VALUE / width))
{
// integer overflow
throw new RasterFormatException("Incorrect pixel stride: "
+ pixelStride);
}
int lastPixelOffset = (width - 1) * pixelStride;
if (lastPixelOffset > (Integer.MAX_VALUE - lastScanOffset)) {
// integer overflow
throw new RasterFormatException("Incorrect raster attributes");
}
lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) {
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]);
}
size = lastPixelOffset + dataOffsets[i];
if (size > maxSize) { if (size > maxSize) {
maxSize = size; maxSize = size;
} }
} }
if (data.length < maxSize) { if (data.length < maxSize) {
throw new RasterFormatException("Data array too small (should be "+ throw new RasterFormatException("Data array too small (should be "
maxSize + maxSize + " )");
+" but is "+data.length+" )");
} }
} }
......
...@@ -151,7 +151,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { ...@@ -151,7 +151,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster {
throw new RasterFormatException("IntegerInterleavedRasters must have"+ throw new RasterFormatException("IntegerInterleavedRasters must have"+
" SinglePixelPackedSampleModel"); " SinglePixelPackedSampleModel");
} }
verify(false); verify();
} }
...@@ -540,31 +540,6 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster { ...@@ -540,31 +540,6 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster {
return createCompatibleWritableRaster(width,height); return createCompatibleWritableRaster(width,height);
} }
/**
* Verify that the layout parameters are consistent with
* the data. If strictCheck
* is false, this method will check for ArrayIndexOutOfBounds conditions. If
* strictCheck is true, this method will check for additional error
* conditions such as line wraparound (width of a line greater than
* the scanline stride).
* @return String Error string, if the layout is incompatible with
* the data. Otherwise returns null.
*/
private void verify (boolean strictCheck) {
int maxSize = 0;
int size;
size = (height-1)*scanlineStride + (width-1) + dataOffsets[0];
if (size > maxSize) {
maxSize = size;
}
if (data.length < maxSize) {
throw new RasterFormatException("Data array too small (should be "+
maxSize
+" but is "+data.length+" )");
}
}
public String toString() { public String toString() {
return new String ("IntegerInterleavedRaster: width = "+width return new String ("IntegerInterleavedRaster: width = "+width
+" height = " + height +" height = " + height
......
...@@ -802,6 +802,15 @@ public class ShortComponentRaster extends SunWritableRaster { ...@@ -802,6 +802,15 @@ public class ShortComponentRaster extends SunWritableRaster {
* or if data buffer has not enough capacity. * or if data buffer has not enough capacity.
*/ */
protected final void verify() { protected final void verify() {
/* Need to re-verify the dimensions since a sample model may be
* specified to the constructor
*/
if (width <= 0 || height <= 0 ||
height > (Integer.MAX_VALUE / width))
{
throw new RasterFormatException("Invalid raster dimension");
}
for (int i = 0; i < dataOffsets.length; i++) { for (int i = 0; i < dataOffsets.length; i++) {
if (dataOffsets[i] < 0) { if (dataOffsets[i] < 0) {
throw new RasterFormatException("Data offsets for band " + i throw new RasterFormatException("Data offsets for band " + i
...@@ -839,12 +848,13 @@ public class ShortComponentRaster extends SunWritableRaster { ...@@ -839,12 +848,13 @@ public class ShortComponentRaster extends SunWritableRaster {
lastPixelOffset += lastScanOffset; lastPixelOffset += lastScanOffset;
for (int i = 0; i < numDataElements; i++) { for (int i = 0; i < numDataElements; i++) {
size = lastPixelOffset + dataOffsets[i];
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) { if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
throw new RasterFormatException("Incorrect band offset: " throw new RasterFormatException("Incorrect band offset: "
+ dataOffsets[i]); + dataOffsets[i]);
} }
size = lastPixelOffset + dataOffsets[i];
if (size > maxSize) { if (size > maxSize) {
maxSize = size; maxSize = size;
} }
......
...@@ -841,7 +841,6 @@ abstract class CMap { ...@@ -841,7 +841,6 @@ abstract class CMap {
CMapFormat6(ByteBuffer bbuffer, int offset, char[] xlat) { CMapFormat6(ByteBuffer bbuffer, int offset, char[] xlat) {
System.err.println("WARNING: CMapFormat8 is untested.");
bbuffer.position(offset+6); bbuffer.position(offset+6);
CharBuffer buffer = bbuffer.asCharBuffer(); CharBuffer buffer = bbuffer.asCharBuffer();
firstCode = buffer.get(); firstCode = buffer.get();
...@@ -884,7 +883,6 @@ abstract class CMap { ...@@ -884,7 +883,6 @@ abstract class CMap {
CMapFormat8(ByteBuffer bbuffer, int offset, char[] xlat) { CMapFormat8(ByteBuffer bbuffer, int offset, char[] xlat) {
System.err.println("WARNING: CMapFormat8 is untested.");
bbuffer.position(12); bbuffer.position(12);
bbuffer.get(is32); bbuffer.get(is32);
nGroups = bbuffer.getInt(); nGroups = bbuffer.getInt();
...@@ -915,7 +913,6 @@ abstract class CMap { ...@@ -915,7 +913,6 @@ abstract class CMap {
CMapFormat10(ByteBuffer bbuffer, int offset, char[] xlat) { CMapFormat10(ByteBuffer bbuffer, int offset, char[] xlat) {
System.err.println("WARNING: CMapFormat10 is untested.");
firstCode = bbuffer.getInt() & INTMASK; firstCode = bbuffer.getInt() & INTMASK;
entryCount = bbuffer.getInt() & INTMASK; entryCount = bbuffer.getInt() & INTMASK;
bbuffer.position(offset+20); bbuffer.position(offset+20);
......
...@@ -85,45 +85,72 @@ class LCMSImageLayout { ...@@ -85,45 +85,72 @@ class LCMSImageLayout {
private boolean imageAtOnce = false; private boolean imageAtOnce = false;
Object dataArray; Object dataArray;
private LCMSImageLayout(int np, int pixelType, int pixelSize) { private int dataArrayLength; /* in bytes */
private LCMSImageLayout(int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this.pixelType = pixelType; this.pixelType = pixelType;
width = np; width = np;
height = 1; height = 1;
nextRowOffset = np * pixelSize; nextRowOffset = safeMult(pixelSize, np);
offset = 0; offset = 0;
} }
private LCMSImageLayout(int width, int height, int pixelType, private LCMSImageLayout(int width, int height, int pixelType,
int pixelSize) { int pixelSize)
throws ImageLayoutException
{
this.pixelType = pixelType; this.pixelType = pixelType;
this.width = width; this.width = width;
this.height = height; this.height = height;
nextRowOffset = width * pixelSize; nextRowOffset = safeMult(pixelSize, width);
offset = 0; offset = 0;
} }
public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize) {
public LCMSImageLayout(byte[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize); this(np, pixelType, pixelSize);
dataType = DT_BYTE; dataType = DT_BYTE;
dataArray = data; dataArray = data;
dataArrayLength = data.length;
verify();
} }
public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize) { public LCMSImageLayout(short[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize); this(np, pixelType, pixelSize);
dataType = DT_SHORT; dataType = DT_SHORT;
dataArray = data; dataArray = data;
dataArrayLength = 2 * data.length;
verify();
} }
public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize) { public LCMSImageLayout(int[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize); this(np, pixelType, pixelSize);
dataType = DT_INT; dataType = DT_INT;
dataArray = data; dataArray = data;
dataArrayLength = 4 * data.length;
verify();
} }
public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize) { public LCMSImageLayout(double[] data, int np, int pixelType, int pixelSize)
throws ImageLayoutException
{
this(np, pixelType, pixelSize); this(np, pixelType, pixelSize);
dataType = DT_DOUBLE; dataType = DT_DOUBLE;
dataArray = data; dataArray = data;
dataArrayLength = 8 * data.length;
verify();
} }
private LCMSImageLayout() { private LCMSImageLayout() {
...@@ -132,7 +159,7 @@ class LCMSImageLayout { ...@@ -132,7 +159,7 @@ class LCMSImageLayout {
/* This method creates a layout object for given image. /* This method creates a layout object for given image.
* Returns null if the image is not supported by current implementation. * Returns null if the image is not supported by current implementation.
*/ */
public static LCMSImageLayout createImageLayout(BufferedImage image) { public static LCMSImageLayout createImageLayout(BufferedImage image) throws ImageLayoutException {
LCMSImageLayout l = new LCMSImageLayout(); LCMSImageLayout l = new LCMSImageLayout();
switch (image.getType()) { switch (image.getType()) {
...@@ -193,9 +220,10 @@ class LCMSImageLayout { ...@@ -193,9 +220,10 @@ class LCMSImageLayout {
do { do {
IntegerComponentRaster intRaster = (IntegerComponentRaster) IntegerComponentRaster intRaster = (IntegerComponentRaster)
image.getRaster(); image.getRaster();
l.nextRowOffset = intRaster.getScanlineStride() * 4; l.nextRowOffset = safeMult(4, intRaster.getScanlineStride());
l.offset = intRaster.getDataOffset(0) * 4; l.offset = safeMult(4, intRaster.getDataOffset(0));
l.dataArray = intRaster.getDataStorage(); l.dataArray = intRaster.getDataStorage();
l.dataArrayLength = 4 * intRaster.getDataStorage().length;
l.dataType = DT_INT; l.dataType = DT_INT;
if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) { if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
...@@ -213,6 +241,7 @@ class LCMSImageLayout { ...@@ -213,6 +241,7 @@ class LCMSImageLayout {
int firstBand = image.getSampleModel().getNumBands() - 1; int firstBand = image.getSampleModel().getNumBands() - 1;
l.offset = byteRaster.getDataOffset(firstBand); l.offset = byteRaster.getDataOffset(firstBand);
l.dataArray = byteRaster.getDataStorage(); l.dataArray = byteRaster.getDataStorage();
l.dataArrayLength = byteRaster.getDataStorage().length;
l.dataType = DT_BYTE; l.dataType = DT_BYTE;
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) { if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
l.imageAtOnce = true; l.imageAtOnce = true;
...@@ -225,6 +254,7 @@ class LCMSImageLayout { ...@@ -225,6 +254,7 @@ class LCMSImageLayout {
ByteComponentRaster byteRaster = (ByteComponentRaster) ByteComponentRaster byteRaster = (ByteComponentRaster)
image.getRaster(); image.getRaster();
l.nextRowOffset = byteRaster.getScanlineStride(); l.nextRowOffset = byteRaster.getScanlineStride();
l.dataArrayLength = byteRaster.getDataStorage().length;
l.offset = byteRaster.getDataOffset(0); l.offset = byteRaster.getDataOffset(0);
l.dataArray = byteRaster.getDataStorage(); l.dataArray = byteRaster.getDataStorage();
l.dataType = DT_BYTE; l.dataType = DT_BYTE;
...@@ -239,9 +269,10 @@ class LCMSImageLayout { ...@@ -239,9 +269,10 @@ class LCMSImageLayout {
do { do {
ShortComponentRaster shortRaster = (ShortComponentRaster) ShortComponentRaster shortRaster = (ShortComponentRaster)
image.getRaster(); image.getRaster();
l.nextRowOffset = shortRaster.getScanlineStride() * 2; l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
l.offset = shortRaster.getDataOffset(0) * 2; l.offset = safeMult(2, shortRaster.getDataOffset(0));
l.dataArray = shortRaster.getDataStorage(); l.dataArray = shortRaster.getDataStorage();
l.dataArrayLength = 2 * shortRaster.getDataStorage().length;
l.dataType = DT_SHORT; l.dataType = DT_SHORT;
if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) { if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
...@@ -252,6 +283,7 @@ class LCMSImageLayout { ...@@ -252,6 +283,7 @@ class LCMSImageLayout {
default: default:
return null; return null;
} }
l.verify();
return l; return l;
} }
...@@ -293,6 +325,46 @@ class LCMSImageLayout { ...@@ -293,6 +325,46 @@ class LCMSImageLayout {
} }
} }
private void verify() throws ImageLayoutException {
if (offset < 0 || offset >= dataArrayLength) {
throw new ImageLayoutException("Invalid image layout");
}
int lastPixelOffset = safeMult(nextRowOffset, (height - 1));
lastPixelOffset = safeAdd(lastPixelOffset, (width - 1));
int off = safeAdd(offset, lastPixelOffset);
if (off < 0 || off >= dataArrayLength) {
throw new ImageLayoutException("Invalid image layout");
}
}
static int safeAdd(int a, int b) throws ImageLayoutException {
long res = a;
res += b;
if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
throw new ImageLayoutException("Invalid image layout");
}
return (int)res;
}
static int safeMult(int a, int b) throws ImageLayoutException {
long res = a;
res *= b;
if (res < Integer.MIN_VALUE || res > Integer.MAX_VALUE) {
throw new ImageLayoutException("Invalid image layout");
}
return (int)res;
}
public static class ImageLayoutException extends Exception {
public ImageLayoutException(String message) {
super(message);
}
}
public static LCMSImageLayout createImageLayout(Raster r) { public static LCMSImageLayout createImageLayout(Raster r) {
LCMSImageLayout l = new LCMSImageLayout(); LCMSImageLayout l = new LCMSImageLayout();
if (r instanceof ByteComponentRaster) { if (r instanceof ByteComponentRaster) {
......
...@@ -51,6 +51,7 @@ import java.awt.image.SinglePixelPackedSampleModel; ...@@ -51,6 +51,7 @@ import java.awt.image.SinglePixelPackedSampleModel;
import java.awt.image.ComponentSampleModel; import java.awt.image.ComponentSampleModel;
import sun.java2d.cmm.*; import sun.java2d.cmm.*;
import sun.java2d.cmm.lcms.*; import sun.java2d.cmm.lcms.*;
import static sun.java2d.cmm.lcms.LCMSImageLayout.ImageLayoutException;
public class LCMSTransform implements ColorTransform { public class LCMSTransform implements ColorTransform {
...@@ -162,15 +163,19 @@ public class LCMSTransform implements ColorTransform { ...@@ -162,15 +163,19 @@ public class LCMSTransform implements ColorTransform {
public void colorConvert(BufferedImage src, BufferedImage dst) { public void colorConvert(BufferedImage src, BufferedImage dst) {
LCMSImageLayout srcIL, dstIL; LCMSImageLayout srcIL, dstIL;
try {
dstIL = LCMSImageLayout.createImageLayout(dst); dstIL = LCMSImageLayout.createImageLayout(dst);
if (dstIL != null) { if (dstIL != null) {
srcIL = LCMSImageLayout.createImageLayout(src); srcIL = LCMSImageLayout.createImageLayout(src);
if (srcIL != null) { if (srcIL != null) {
doTransform(srcIL, dstIL); doTransform(srcIL, dstIL);
return; return;
}
} }
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
} }
Raster srcRas = src.getRaster(); Raster srcRas = src.getRaster();
...@@ -228,14 +233,18 @@ public class LCMSTransform implements ColorTransform { ...@@ -228,14 +233,18 @@ public class LCMSTransform implements ColorTransform {
} }
int idx; int idx;
// TODO check for src npixels = dst npixels // TODO check for src npixels = dst npixels
srcIL = new LCMSImageLayout( try {
srcLine, srcLine.length/getNumInComponents(), srcIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.BYTES_SH(1), getNumInComponents()); LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
dstIL = new LCMSImageLayout( LCMSImageLayout.BYTES_SH(1), getNumInComponents());
dstLine, dstLine.length/getNumOutComponents(), dstIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
}
// process each scanline // process each scanline
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
// convert src scanline // convert src scanline
...@@ -284,16 +293,19 @@ public class LCMSTransform implements ColorTransform { ...@@ -284,16 +293,19 @@ public class LCMSTransform implements ColorTransform {
alpha = new float[w]; alpha = new float[w];
} }
int idx; int idx;
srcIL = new LCMSImageLayout( try {
srcLine, srcLine.length/getNumInComponents(), srcIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(), dstIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert images");
}
// process each scanline // process each scanline
for (int y = 0; y < h; y++) { for (int y = 0; y < h; y++) {
// convert src scanline // convert src scanline
...@@ -402,16 +414,19 @@ public class LCMSTransform implements ColorTransform { ...@@ -402,16 +414,19 @@ public class LCMSTransform implements ColorTransform {
short[] srcLine = new short[w * srcNumBands]; short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands]; short[] dstLine = new short[w * dstNumBands];
int idx; int idx;
srcIL = new LCMSImageLayout( try {
srcLine, srcLine.length/getNumInComponents(), srcIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert rasters");
}
// process each scanline // process each scanline
for (int y = 0; y < h; y++, ys++, yd++) { for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline // get src scanline
...@@ -502,15 +517,18 @@ public class LCMSTransform implements ColorTransform { ...@@ -502,15 +517,18 @@ public class LCMSTransform implements ColorTransform {
byte[] dstLine = new byte[w * dstNumBands]; byte[] dstLine = new byte[w * dstNumBands];
int idx; int idx;
// TODO check for src npixels = dst npixels // TODO check for src npixels = dst npixels
srcIL = new LCMSImageLayout( try {
srcLine, srcLine.length/getNumInComponents(), srcIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.BYTES_SH(1), getNumInComponents()); LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
dstIL = new LCMSImageLayout( LCMSImageLayout.BYTES_SH(1), getNumInComponents());
dstLine, dstLine.length/getNumOutComponents(), dstIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert rasters");
}
// process each scanline // process each scanline
for (int y = 0; y < h; y++, ys++, yd++) { for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline // get src scanline
...@@ -542,16 +560,20 @@ public class LCMSTransform implements ColorTransform { ...@@ -542,16 +560,20 @@ public class LCMSTransform implements ColorTransform {
short[] srcLine = new short[w * srcNumBands]; short[] srcLine = new short[w * srcNumBands];
short[] dstLine = new short[w * dstNumBands]; short[] dstLine = new short[w * dstNumBands];
int idx; int idx;
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
try {
srcIL = new LCMSImageLayout(
srcLine, srcLine.length/getNumInComponents(),
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
dstIL = new LCMSImageLayout(
dstLine, dstLine.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert rasters");
}
// process each scanline // process each scanline
for (int y = 0; y < h; y++, ys++, yd++) { for (int y = 0; y < h; y++, ys++, yd++) {
// get src scanline // get src scanline
...@@ -592,19 +614,23 @@ public class LCMSTransform implements ColorTransform { ...@@ -592,19 +614,23 @@ public class LCMSTransform implements ColorTransform {
dst = new short [(src.length/getNumInComponents())*getNumOutComponents()]; dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
} }
LCMSImageLayout srcIL = new LCMSImageLayout( try {
src, src.length/getNumInComponents(), LCMSImageLayout srcIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | src, src.length/getNumInComponents(),
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2); LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
LCMSImageLayout dstIL = new LCMSImageLayout( LCMSImageLayout dstIL = new LCMSImageLayout(
dst, dst.length/getNumOutComponents(), dst, dst.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2); LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
doTransform(srcIL, dstIL); doTransform(srcIL, dstIL);
return dst; return dst;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert data");
}
} }
public byte[] colorConvert(byte[] src, byte[] dst) { public byte[] colorConvert(byte[] src, byte[] dst) {
...@@ -612,18 +638,22 @@ public class LCMSTransform implements ColorTransform { ...@@ -612,18 +638,22 @@ public class LCMSTransform implements ColorTransform {
dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()]; dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
} }
LCMSImageLayout srcIL = new LCMSImageLayout( try {
src, src.length/getNumInComponents(), LCMSImageLayout srcIL = new LCMSImageLayout(
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) | src, src.length/getNumInComponents(),
LCMSImageLayout.BYTES_SH(1), getNumInComponents()); LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
LCMSImageLayout dstIL = new LCMSImageLayout( LCMSImageLayout dstIL = new LCMSImageLayout(
dst, dst.length/getNumOutComponents(), dst, dst.length/getNumOutComponents(),
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) | LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
LCMSImageLayout.BYTES_SH(1), getNumOutComponents()); LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
doTransform(srcIL, dstIL); doTransform(srcIL, dstIL);
return dst; return dst;
} catch (ImageLayoutException e) {
throw new CMMException("Unable to convert data");
}
} }
} }
...@@ -46,8 +46,28 @@ import sun.misc.IOUtils; ...@@ -46,8 +46,28 @@ import sun.misc.IOUtils;
class Trampoline { class Trampoline {
static {
if (Trampoline.class.getClassLoader() == null) {
throw new Error(
"Trampoline must not be defined by the bootstrap classloader");
}
}
private static void ensureInvocableMethod(Method m)
throws InvocationTargetException
{
Class<?> clazz = m.getDeclaringClass();
if (clazz.equals(AccessController.class) ||
clazz.equals(Method.class) ||
clazz.getName().startsWith("java.lang.invoke."))
throw new InvocationTargetException(
new UnsupportedOperationException("invocation not supported"));
}
private static Object invoke(Method m, Object obj, Object[] params) private static Object invoke(Method m, Object obj, Object[] params)
throws InvocationTargetException, IllegalAccessException { throws InvocationTargetException, IllegalAccessException
{
ensureInvocableMethod(m);
return m.invoke(obj, params); return m.invoke(obj, params);
} }
} }
...@@ -251,16 +271,6 @@ public final class MethodUtil extends SecureClassLoader { ...@@ -251,16 +271,6 @@ public final class MethodUtil extends SecureClassLoader {
*/ */
public static Object invoke(Method m, Object obj, Object[] params) public static Object invoke(Method m, Object obj, Object[] params)
throws InvocationTargetException, IllegalAccessException { throws InvocationTargetException, IllegalAccessException {
if (m.getDeclaringClass().equals(AccessController.class) ||
(m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.class)
&& m.getName().equals("lookup")) ||
(m.getDeclaringClass().equals(java.lang.invoke.MethodHandles.Lookup.class)
&& (m.getName().startsWith("find") ||
m.getName().startsWith("bind") ||
m.getName().startsWith("unreflect"))) ||
m.getDeclaringClass().equals(Method.class))
throw new InvocationTargetException(
new UnsupportedOperationException("invocation not supported"));
try { try {
return bounce.invoke(null, new Object[] {m, obj, params}); return bounce.invoke(null, new Object[] {m, obj, params});
} catch (InvocationTargetException ie) { } catch (InvocationTargetException ie) {
...@@ -293,10 +303,10 @@ public final class MethodUtil extends SecureClassLoader { ...@@ -293,10 +303,10 @@ public final class MethodUtil extends SecureClassLoader {
Method.class, Object.class, Object[].class Method.class, Object.class, Object[].class
}; };
Method b = t.getDeclaredMethod("invoke", types); Method b = t.getDeclaredMethod("invoke", types);
((AccessibleObject)b).setAccessible(true); b.setAccessible(true);
return b; return b;
} }
}); });
} catch (Exception e) { } catch (Exception e) {
throw new InternalError("bouncer cannot be found", e); throw new InternalError("bouncer cannot be found", e);
} }
......
...@@ -55,13 +55,19 @@ import java.rmi.server.RMIClassLoader; ...@@ -55,13 +55,19 @@ import java.rmi.server.RMIClassLoader;
public class MarshalInputStream extends ObjectInputStream { public class MarshalInputStream extends ObjectInputStream {
/** /**
* value of "java.rmi.server.useCodebaseOnly" property, * Value of "java.rmi.server.useCodebaseOnly" property,
* as cached at class initialization time. * as cached at class initialization time.
*
* The default value is true. That is, the value is true
* if the property is absent or is not equal to "false".
* The value is only false when the property is present
* and is equal to "false".
*/ */
private static final boolean useCodebaseOnlyProperty = private static final boolean useCodebaseOnlyProperty =
java.security.AccessController.doPrivileged( ! java.security.AccessController.doPrivileged(
new sun.security.action.GetBooleanAction( new sun.security.action.GetPropertyAction(
"java.rmi.server.useCodebaseOnly")).booleanValue(); "java.rmi.server.useCodebaseOnly", "true"))
.equalsIgnoreCase("false");
/** table to hold sun classes to which access is explicitly permitted */ /** table to hold sun classes to which access is explicitly permitted */
protected static Map<String, Class<?>> permittedSunClasses protected static Map<String, Class<?>> permittedSunClasses
......
/* /*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 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
...@@ -101,7 +101,7 @@ abstract class SHA2 extends DigestBase { ...@@ -101,7 +101,7 @@ abstract class SHA2 extends DigestBase {
i2bBig4((int)bitsProcessed, buffer, 60); i2bBig4((int)bitsProcessed, buffer, 60);
implCompress(buffer, 0); implCompress(buffer, 0);
i2bBig(state, 0, out, ofs, 32); i2bBig(state, 0, out, ofs, engineGetDigestLength());
} }
/** /**
......
...@@ -843,5 +843,52 @@ public final class UntrustedCertificates { ...@@ -843,5 +843,52 @@ public final class UntrustedCertificates {
"zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" + "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" +
"-----END CERTIFICATE-----"); "-----END CERTIFICATE-----");
//
// Revoked code signing certificate w/ a stolen key issued by GoDaddy
// used to sign malware
//
// Subject: CN=CLEARESULT CONSULTING INC., OU=Corporate IT,
// O=CLEARESULT CONSULTING INC., L=Austin, ST=TX, C=US
// Issuer: SERIALNUMBER=07969287,
// CN=Go Daddy Secure Certification Authority,
// OU=http://certificates.godaddy.com/repository,
// O="GoDaddy.com, Inc.",
// L=Scottsdale,
// ST=Arizona,
// C=US
// Serial: 2b:73:43:2a:a8:4f:44
add("clearesult-consulting-inc-2AA84F44",
"-----BEGIN CERTIFICATE-----\n" +
"MIIFYjCCBEqgAwIBAgIHK3NDKqhPRDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" +
"BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" +
"BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" +
"aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" +
"IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" +
"ODcwHhcNMTIwMjE1MjEwOTA2WhcNMTQwMjE1MjEwOTA2WjCBjDELMAkGA1UEBgwC\n" +
"VVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0aW4xIzAhBgNVBAoMGkNMRUFS\n" +
"RVNVTFQgQ09OU1VMVElORyBJTkMuMRUwEwYDVQQLDAxDb3Jwb3JhdGUgSVQxIzAh\n" +
"BgNVBAMMGkNMRUFSRVNVTFQgQ09OU1VMVElORyBJTkMuMIIBIjANBgkqhkiG9w0B\n" +
"AQEFAAOCAQ8AMIIBCgKCAQEAtIOjCKeAicull+7ZIzt0/4ya3IeXUFlfypqKMLkU\n" +
"IbKjn0P5uMj6VE3rlbZr44RCegxvdnR6umBh1c0ZXoN3o+yc0JKcKcLiApmJJ277\n" +
"p7IbLwYDhBXRQNoIJm187IOMRPIxsKN4hL91txn9jGBmW+9zKlJlNhR5R7vjwU2E\n" +
"jrH/6oqsc9EM2yYpfjlNv6+3jSwAYZCkSWr+27PQOV+YHKmIxtJjX0upFz5FdIrV\n" +
"9CCX+L2Kji1THOkSgG4QTbYxmEcHqGViWz8hXLeNXjcbEsPuIiAu3hknxRHfUTE/\n" +
"U0Lh0Ug1e3LrJu+WnxM2SmUY4krsZ22c0yWUW9hzWITIjQIDAQABo4IBhzCCAYMw\n" +
"DwYDVR0TAQH/BAUwAwEBADATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8E\n" +
"BAMCB4AwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5LmNvbS9n\n" +
"ZHM1LTE2LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcCMDkwNwYIKwYBBQUH\n" +
"AgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8w\n" +
"gYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRk\n" +
"eS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHku\n" +
"Y29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSMEGDAWgBT9\n" +
"rGEyk2xF1uLuhV+auud2mWjM5zAdBgNVHQ4EFgQUDtdeKqeN2QkcbEp1HovFieNB\n" +
"XiowDQYJKoZIhvcNAQEFBQADggEBAD74Agw5tvi2aBl4/f/s7/VE/BClzDsKMb9K\n" +
"v9qpeC45ZA/jelxV11HKbQnVF194gDb7D2H9OsAsRUy8HVKbXEcc/8dKvwOqb+BC\n" +
"2i/EmfjLgmCfezNFtLq8xcPxF3zIRc44vPrK0z4YZsaHdH+yTEJ51p5EMdTqaLaP\n" +
"4n5m8LX3RfqlQB9dYFe6dUoYZjKm9d/pIRww3VqfOzjl42Edi1w6dWmBVMx1NZuR\n" +
"DBabJH1vJ9Gd+KwxMCmBZ6pQPl28JDimhJhI2LNqU349uADQVV0HJosddN/ARyyI\n" +
"LSIQO7BnNVKVG9Iujf33bvPNeg0qNz5qw+rKKq97Pqeum+L5oKU=\n" +
"-----END CERTIFICATE-----");
} }
} }
...@@ -146,22 +146,35 @@ keystore.type=jks ...@@ -146,22 +146,35 @@ keystore.type=jks
# corresponding RuntimePermission ("accessClassInPackage."+package) has # corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted. # been granted.
package.access=sun.,\ package.access=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools. jdk.nashorn.tools.
# #
# List of comma-separated packages that start with or equal this string # List of comma-separated packages that start with or equal this string
...@@ -174,22 +187,35 @@ package.access=sun.,\ ...@@ -174,22 +187,35 @@ package.access=sun.,\
# checkPackageDefinition. # checkPackageDefinition.
# #
package.definition=sun.,\ package.definition=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools. jdk.nashorn.tools.
# #
# Determines whether this properties file can be appended to # Determines whether this properties file can be appended to
......
...@@ -147,22 +147,34 @@ keystore.type=jks ...@@ -147,22 +147,34 @@ keystore.type=jks
# corresponding RuntimePermission ("accessClassInPackage."+package) has # corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted. # been granted.
package.access=sun.,\ package.access=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools.,\ jdk.nashorn.tools.,\
apple. apple.
# #
...@@ -176,22 +188,34 @@ package.access=sun.,\ ...@@ -176,22 +188,34 @@ package.access=sun.,\
# checkPackageDefinition. # checkPackageDefinition.
# #
package.definition=sun.,\ package.definition=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools.,\ jdk.nashorn.tools.,\
apple. apple.
# #
......
...@@ -148,22 +148,34 @@ keystore.type=jks ...@@ -148,22 +148,34 @@ keystore.type=jks
# corresponding RuntimePermission ("accessClassInPackage."+package) has # corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted. # been granted.
package.access=sun.,\ package.access=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools. jdk.nashorn.tools.
# #
# List of comma-separated packages that start with or equal this string # List of comma-separated packages that start with or equal this string
...@@ -176,22 +188,34 @@ package.access=sun.,\ ...@@ -176,22 +188,34 @@ package.access=sun.,\
# checkPackageDefinition. # checkPackageDefinition.
# #
package.definition=sun.,\ package.definition=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools. jdk.nashorn.tools.
# #
# Determines whether this properties file can be appended to # Determines whether this properties file can be appended to
......
...@@ -147,22 +147,35 @@ keystore.type=jks ...@@ -147,22 +147,35 @@ keystore.type=jks
# corresponding RuntimePermission ("accessClassInPackage."+package) has # corresponding RuntimePermission ("accessClassInPackage."+package) has
# been granted. # been granted.
package.access=sun.,\ package.access=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools. jdk.nashorn.tools.,\
com.sun.java.accessibility.
# #
# List of comma-separated packages that start with or equal this string # List of comma-separated packages that start with or equal this string
...@@ -175,22 +188,35 @@ package.access=sun.,\ ...@@ -175,22 +188,35 @@ package.access=sun.,\
# checkPackageDefinition. # checkPackageDefinition.
# #
package.definition=sun.,\ package.definition=sun.,\
com.sun.xml.internal.bind.,\ com.sun.xml.internal.,\
com.sun.xml.internal.org.jvnet.staxex.,\
com.sun.xml.internal.ws.,\
com.sun.imageio.,\ com.sun.imageio.,\
com.sun.istack.internal.,\ com.sun.istack.internal.,\
com.sun.jmx.,\ com.sun.jmx.,\
com.sun.proxy.,\ com.sun.proxy.,\
com.sun.org.apache.xerces.internal.utils.,\ com.sun.org.apache.bcel.internal.,\
com.sun.org.apache.regexp.internal.,\
com.sun.org.apache.xerces.internal.,\
com.sun.org.apache.xpath.internal.,\
com.sun.org.apache.xalan.internal.extensions.,\
com.sun.org.apache.xalan.internal.lib.,\
com.sun.org.apache.xalan.internal.res.,\
com.sun.org.apache.xalan.internal.templates.,\
com.sun.org.apache.xalan.internal.utils.,\ com.sun.org.apache.xalan.internal.utils.,\
com.sun.org.glassfish.external.,\ com.sun.org.apache.xalan.internal.xslt.,\
com.sun.org.glassfish.gmbal.,\ com.sun.org.apache.xalan.internal.xsltc.cmdline.,\
com.sun.org.apache.xalan.internal.xsltc.compiler.,\
com.sun.org.apache.xalan.internal.xsltc.trax.,\
com.sun.org.apache.xalan.internal.xsltc.util.,\
com.sun.org.apache.xml.internal.res.,\
com.sun.org.apache.xml.internal.serializer.utils.,\
com.sun.org.apache.xml.internal.utils.,\
com.sun.org.glassfish.,\
com.oracle.xmlns.internal.,\ com.oracle.xmlns.internal.,\
com.oracle.webservices.internal.,\ com.oracle.webservices.internal.,\
jdk.internal.,\ jdk.internal.,\
jdk.nashorn.internal.,\ jdk.nashorn.internal.,\
jdk.nashorn.tools. jdk.nashorn.tools.,\
com.sun.java.accessibility.
# #
# Determines whether this properties file can be appended to # Determines whether this properties file can be appended to
......
...@@ -33,8 +33,11 @@ ...@@ -33,8 +33,11 @@
*/ */
jclass ia_class; jclass ia_class;
jfieldID ia_addressID; jclass iac_class;
jfieldID ia_familyID; jfieldID ia_holderID;
jfieldID iac_addressID;
jfieldID iac_familyID;
jfieldID iac_hostNameID;
jfieldID ia_preferIPv6AddressID; jfieldID ia_preferIPv6AddressID;
/* /*
...@@ -48,10 +51,18 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) { ...@@ -48,10 +51,18 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
CHECK_NULL(c); CHECK_NULL(c);
ia_class = (*env)->NewGlobalRef(env, c); ia_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL(ia_class); CHECK_NULL(ia_class);
ia_addressID = (*env)->GetFieldID(env, ia_class, "address", "I"); c = (*env)->FindClass(env,"java/net/InetAddress$InetAddressHolder");
CHECK_NULL(ia_addressID); CHECK_NULL(c);
ia_familyID = (*env)->GetFieldID(env, ia_class, "family", "I"); iac_class = (*env)->NewGlobalRef(env, c);
CHECK_NULL(ia_familyID); ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
CHECK_NULL(ia_holderID);
ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z"); ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z");
CHECK_NULL(ia_preferIPv6AddressID); CHECK_NULL(ia_preferIPv6AddressID);
iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
CHECK_NULL(iac_addressID);
iac_familyID = (*env)->GetFieldID(env, iac_class, "family", "I");
CHECK_NULL(iac_familyID);
iac_hostNameID = (*env)->GetFieldID(env, iac_class, "hostName", "Ljava/lang/String;");
CHECK_NULL(iac_hostNameID);
} }
...@@ -84,6 +84,58 @@ void init(JNIEnv *env) { ...@@ -84,6 +84,58 @@ void init(JNIEnv *env) {
} }
} }
/* The address, and family fields used to be in InetAddress
* but are now in an implementation object. So, there is an extra
* level of indirection to access them now.
*/
extern jclass iac_class;
extern jfieldID ia_holderID;
extern jfieldID iac_addressID;
extern jfieldID iac_familyID;
void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address) {
jobject holder;
init(env);
holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
(*env)->SetIntField(env, holder, iac_addressID, address);
}
void setInetAddress_family(JNIEnv *env, jobject iaObj, int family) {
jobject holder;
init(env);
holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
(*env)->SetIntField(env, holder, iac_familyID, family);
}
void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject host) {
jobject holder;
init(env);
holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
(*env)->SetObjectField(env, holder, iac_hostNameID, host);
}
int getInetAddress_addr(JNIEnv *env, jobject iaObj) {
jobject holder;
init(env);
holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
return (*env)->GetIntField(env, holder, iac_addressID);
}
int getInetAddress_family(JNIEnv *env, jobject iaObj) {
jobject holder;
init(env);
holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
return (*env)->GetIntField(env, holder, iac_familyID);
}
jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj) {
jobject holder;
init(env);
holder = (*env)->GetObjectField(env, iaObj, ia_holderID);
return (*env)->GetObjectField(env, holder, iac_hostNameID);
}
JNIEXPORT jobject JNICALL JNIEXPORT jobject JNICALL
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
jobject iaObj; jobject iaObj;
...@@ -110,8 +162,8 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { ...@@ -110,8 +162,8 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
CHECK_NULL_RETURN(iaObj, NULL); CHECK_NULL_RETURN(iaObj, NULL);
address = NET_IPv4MappedToIPv4(caddr); address = NET_IPv4MappedToIPv4(caddr);
(*env)->SetIntField(env, iaObj, ia_addressID, address); setInetAddress_addr(env, iaObj, address);
(*env)->SetIntField(env, iaObj, ia_familyID, IPv4); setInetAddress_family(env, iaObj, IPv4);
} else { } else {
static jclass inet6Cls = 0; static jclass inet6Cls = 0;
jint scope; jint scope;
...@@ -131,7 +183,7 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { ...@@ -131,7 +183,7 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
(*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress); (*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
(*env)->SetIntField(env, iaObj, ia_familyID, IPv6); setInetAddress_family(env, iaObj, IPv6);
scope = getScopeID(him); scope = getScopeID(him);
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
if (scope > 0) if (scope > 0)
...@@ -153,9 +205,8 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) { ...@@ -153,9 +205,8 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
} }
iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID); iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
CHECK_NULL_RETURN(iaObj, NULL); CHECK_NULL_RETURN(iaObj, NULL);
(*env)->SetIntField(env, iaObj, ia_familyID, IPv4); setInetAddress_family(env, iaObj, IPv4);
(*env)->SetIntField(env, iaObj, ia_addressID, setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
ntohl(him4->sin_addr.s_addr));
*port = ntohs(him4->sin_port); *port = ntohs(him4->sin_port);
} }
return iaObj; return iaObj;
...@@ -167,8 +218,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) ...@@ -167,8 +218,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
jint family = AF_INET; jint family = AF_INET;
#ifdef AF_INET6 #ifdef AF_INET6
family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4? family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
AF_INET : AF_INET6;
if (him->sa_family == AF_INET6) { if (him->sa_family == AF_INET6) {
#ifdef WIN32 #ifdef WIN32
struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him; struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
...@@ -183,7 +233,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) ...@@ -183,7 +233,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
return JNI_FALSE; return JNI_FALSE;
} }
addrNew = NET_IPv4MappedToIPv4(caddrNew); addrNew = NET_IPv4MappedToIPv4(caddrNew);
addrCur = (*env)->GetIntField(env, iaObj, ia_addressID); addrCur = getInetAddress_addr(env, iaObj);
if (addrNew == addrCur) { if (addrNew == addrCur) {
return JNI_TRUE; return JNI_TRUE;
} else { } else {
...@@ -215,7 +265,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj) ...@@ -215,7 +265,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
return JNI_FALSE; return JNI_FALSE;
} }
addrNew = ntohl(him4->sin_addr.s_addr); addrNew = ntohl(him4->sin_addr.s_addr);
addrCur = (*env)->GetIntField(env, iaObj, ia_addressID); addrCur = getInetAddress_addr(env, iaObj);
if (addrNew == addrCur) { if (addrNew == addrCur) {
return JNI_TRUE; return JNI_TRUE;
} else { } else {
......
...@@ -53,10 +53,18 @@ ...@@ -53,10 +53,18 @@
* i.e. psi_timeoutID is PlainSocketImpl's timeout field's ID. * i.e. psi_timeoutID is PlainSocketImpl's timeout field's ID.
*/ */
extern jclass ia_class; extern jclass ia_class;
extern jfieldID ia_addressID; extern jfieldID iac_addressID;
extern jfieldID ia_familyID; extern jfieldID iac_familyID;
extern jfieldID iac_hostNameID;
extern jfieldID ia_preferIPv6AddressID; extern jfieldID ia_preferIPv6AddressID;
extern void setInetAddress_addr(JNIEnv *env, jobject iaObj, int address);
extern void setInetAddress_family(JNIEnv *env, jobject iaObj, int family);
extern void setInetAddress_hostName(JNIEnv *env, jobject iaObj, jobject h);
extern int getInetAddress_addr(JNIEnv *env, jobject iaObj);
extern int getInetAddress_family(JNIEnv *env, jobject iaObj);
extern jobject getInetAddress_hostName(JNIEnv *env, jobject iaObj);
extern jclass ia4_class; extern jclass ia4_class;
extern jmethodID ia4_ctrID; extern jmethodID ia4_ctrID;
......
...@@ -45,6 +45,53 @@ static int findIdx(unsigned int rgb, unsigned int *lut, int numLut1); ...@@ -45,6 +45,53 @@ static int findIdx(unsigned int rgb, unsigned int *lut, int numLut1);
# define TRUE 1 # define TRUE 1
#endif #endif
#define CHECK_STRIDE(yy, hh, ss) \
if ((ss) != 0) { \
int limit = 0x7fffffff / ((ss) > 0 ? (ss) : -(ss)); \
if (limit < (yy) || limit < ((yy) + (hh) - 1)) { \
/* integer oveflow */ \
return JNI_FALSE; \
} \
} \
#define CHECK_SRC() \
do { \
int pixeloffset; \
if (off < 0 || off >= srcDataLength) { \
return JNI_FALSE; \
} \
CHECK_STRIDE(0, h, scansize); \
\
/* check scansize */ \
pixeloffset = scansize * (h - 1); \
if ((w - 1) > (0x7fffffff - pixeloffset)) { \
return JNI_FALSE; \
} \
pixeloffset += (w - 1); \
\
if (off > (0x7fffffff - pixeloffset)) { \
return JNI_FALSE; \
} \
} while (0) \
#define CHECK_DST(xx, yy) \
do { \
int soffset = (yy) * sStride; \
int poffset = (xx) * pixelStride; \
if (poffset > (0x7fffffff - soffset)) { \
return JNI_FALSE; \
} \
poffset += soffset; \
if (dstDataOff > (0x7fffffff - poffset)) { \
return JNI_FALSE; \
} \
poffset += dstDataOff; \
\
if (poffset < 0 || poffset >= dstDataLength) { \
return JNI_FALSE; \
} \
} while (0) \
static jfieldID s_JnumSrcLUTID; static jfieldID s_JnumSrcLUTID;
static jfieldID s_JsrcLUTtransIndexID; static jfieldID s_JsrcLUTtransIndexID;
...@@ -58,7 +105,7 @@ Java_sun_awt_image_ImageRepresentation_initIDs(JNIEnv *env, jclass cls) { ...@@ -58,7 +105,7 @@ Java_sun_awt_image_ImageRepresentation_initIDs(JNIEnv *env, jclass cls) {
/* /*
* This routine is used to draw ICM pixels into a default color model * This routine is used to draw ICM pixels into a default color model
*/ */
JNIEXPORT void JNICALL JNIEXPORT jboolean JNICALL
Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls, Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
jint x, jint y, jint w, jint x, jint y, jint w,
jint h, jintArray jlut, jint h, jintArray jlut,
...@@ -67,7 +114,10 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls, ...@@ -67,7 +114,10 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
jobject jict) jobject jict)
{ {
unsigned char *srcData = NULL; unsigned char *srcData = NULL;
jint srcDataLength;
int *dstData; int *dstData;
jint dstDataLength;
jint dstDataOff;
int *dstP, *dstyP; int *dstP, *dstyP;
unsigned char *srcyP, *srcP; unsigned char *srcyP, *srcP;
int *srcLUT = NULL; int *srcLUT = NULL;
...@@ -80,12 +130,20 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls, ...@@ -80,12 +130,20 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
if (JNU_IsNull(env, jlut)) { if (JNU_IsNull(env, jlut)) {
JNU_ThrowNullPointerException(env, "NullPointerException"); JNU_ThrowNullPointerException(env, "NullPointerException");
return; return JNI_FALSE;
} }
if (JNU_IsNull(env, jpix)) { if (JNU_IsNull(env, jpix)) {
JNU_ThrowNullPointerException(env, "NullPointerException"); JNU_ThrowNullPointerException(env, "NullPointerException");
return; return JNI_FALSE;
}
if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
return JNI_FALSE;
}
if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
return JNI_FALSE;
} }
sStride = (*env)->GetIntField(env, jict, g_ICRscanstrID); sStride = (*env)->GetIntField(env, jict, g_ICRscanstrID);
...@@ -93,10 +151,47 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls, ...@@ -93,10 +151,47 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
joffs = (*env)->GetObjectField(env, jict, g_ICRdataOffsetsID); joffs = (*env)->GetObjectField(env, jict, g_ICRdataOffsetsID);
jdata = (*env)->GetObjectField(env, jict, g_ICRdataID); jdata = (*env)->GetObjectField(env, jict, g_ICRdataID);
if (JNU_IsNull(env, jdata)) {
/* no destination buffer */
return JNI_FALSE;
}
if (JNU_IsNull(env, joffs) || (*env)->GetArrayLength(env, joffs) < 1) {
/* invalid data offstes in raster */
return JNI_FALSE;
}
srcDataLength = (*env)->GetArrayLength(env, jpix);
dstDataLength = (*env)->GetArrayLength(env, jdata);
cOffs = (int *) (*env)->GetPrimitiveArrayCritical(env, joffs, NULL);
if (cOffs == NULL) {
JNU_ThrowNullPointerException(env, "Null channel offset array");
return JNI_FALSE;
}
dstDataOff = cOffs[0];
/* the offset array is not needed anymore and can be released */
(*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
joffs = NULL;
cOffs = NULL;
/* do basic validation: make sure that offsets for
* first pixel and for last pixel are safe to calculate and use */
CHECK_STRIDE(y, h, sStride);
CHECK_STRIDE(x, w, pixelStride);
CHECK_DST(x, y);
CHECK_DST(x + w -1, y + h - 1);
/* check source array */
CHECK_SRC();
srcLUT = (int *) (*env)->GetPrimitiveArrayCritical(env, jlut, NULL); srcLUT = (int *) (*env)->GetPrimitiveArrayCritical(env, jlut, NULL);
if (srcLUT == NULL) { if (srcLUT == NULL) {
JNU_ThrowNullPointerException(env, "Null IndexColorModel LUT"); JNU_ThrowNullPointerException(env, "Null IndexColorModel LUT");
return; return JNI_FALSE;
} }
srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix, srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
...@@ -104,27 +199,18 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls, ...@@ -104,27 +199,18 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
if (srcData == NULL) { if (srcData == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
JNU_ThrowNullPointerException(env, "Null data array"); JNU_ThrowNullPointerException(env, "Null data array");
return; return JNI_FALSE;
}
cOffs = (int *) (*env)->GetPrimitiveArrayCritical(env, joffs, NULL);
if (cOffs == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
JNU_ThrowNullPointerException(env, "Null channel offset array");
return;
} }
dstData = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL); dstData = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
if (dstData == NULL) { if (dstData == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
JNU_ThrowNullPointerException(env, "Null tile data array"); JNU_ThrowNullPointerException(env, "Null tile data array");
return; return JNI_FALSE;
} }
dstyP = dstData + cOffs[0] + y*sStride + x*pixelStride; dstyP = dstData + dstDataOff + y*sStride + x*pixelStride;
srcyP = srcData + off; srcyP = srcData + off;
for (yIdx = 0; yIdx < h; yIdx++, srcyP += scansize, dstyP+=sStride) { for (yIdx = 0; yIdx < h; yIdx++, srcyP += scansize, dstyP+=sStride) {
srcP = srcyP; srcP = srcyP;
...@@ -137,12 +223,12 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls, ...@@ -137,12 +223,12 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
/* Release the locked arrays */ /* Release the locked arrays */
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
return JNI_TRUE;
} }
JNIEXPORT jint JNICALL JNIEXPORT jboolean JNICALL
Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
jint x, jint y, jint w, jint x, jint y, jint w,
jint h, jintArray jlut, jint h, jintArray jlut,
...@@ -150,7 +236,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -150,7 +236,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
jobject jicm, jobject jicm,
jbyteArray jpix, jint off, jbyteArray jpix, jint off,
jint scansize, jint scansize,
jobject jbct, jint chanOff) jobject jbct, jint dstDataOff)
{ {
unsigned int *srcLUT = NULL; unsigned int *srcLUT = NULL;
unsigned int *newLUT = NULL; unsigned int *newLUT = NULL;
...@@ -159,6 +245,8 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -159,6 +245,8 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
int mapSize; int mapSize;
jobject jdata = NULL; jobject jdata = NULL;
jobject jnewlut = NULL; jobject jnewlut = NULL;
jint srcDataLength;
jint dstDataLength;
unsigned char *srcData; unsigned char *srcData;
unsigned char *dstData; unsigned char *dstData;
unsigned char *dataP; unsigned char *dataP;
...@@ -174,14 +262,23 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -174,14 +262,23 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
if (JNU_IsNull(env, jlut)) { if (JNU_IsNull(env, jlut)) {
JNU_ThrowNullPointerException(env, "NullPointerException"); JNU_ThrowNullPointerException(env, "NullPointerException");
return 0; return JNI_FALSE;
} }
if (JNU_IsNull(env, jpix)) { if (JNU_IsNull(env, jpix)) {
JNU_ThrowNullPointerException(env, "NullPointerException"); JNU_ThrowNullPointerException(env, "NullPointerException");
return 0; return JNI_FALSE;
}
if (x < 0 || w < 1 || (0x7fffffff - x) < w) {
return JNI_FALSE;
} }
if (y < 0 || h < 1 || (0x7fffffff - y) < h) {
return JNI_FALSE;
}
sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID); sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID);
pixelStride =(*env)->GetIntField(env, jbct, g_BCRpixstrID); pixelStride =(*env)->GetIntField(env, jbct, g_BCRpixstrID);
jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID); jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
...@@ -193,13 +290,31 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -193,13 +290,31 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
of byte data type, so we have to convert the image data of byte data type, so we have to convert the image data
to default representation. to default representation.
*/ */
return 0; return JNI_FALSE;
}
if (JNU_IsNull(env, jdata)) {
/* no destination buffer */
return JNI_FALSE;
} }
srcDataLength = (*env)->GetArrayLength(env, jpix);
dstDataLength = (*env)->GetArrayLength(env, jdata);
CHECK_STRIDE(y, h, sStride);
CHECK_STRIDE(x, w, pixelStride);
CHECK_DST(x, y);
CHECK_DST(x + w -1, y + h - 1);
/* check source array */
CHECK_SRC();
srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut, srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut,
NULL); NULL);
if (srcLUT == NULL) { if (srcLUT == NULL) {
/* out of memory error already thrown */ /* out of memory error already thrown */
return 0; return JNI_FALSE;
} }
newLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jnewlut, newLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jnewlut,
...@@ -208,7 +323,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -208,7 +323,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
JNI_ABORT); JNI_ABORT);
/* out of memory error already thrown */ /* out of memory error already thrown */
return 0; return JNI_FALSE;
} }
newNumLut = numLut; newNumLut = numLut;
...@@ -219,7 +334,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -219,7 +334,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, (*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
JNI_ABORT); JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
return 0; return JNI_FALSE;
} }
/* Don't need these any more */ /* Don't need these any more */
...@@ -239,7 +354,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -239,7 +354,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
NULL); NULL);
if (srcData == NULL) { if (srcData == NULL) {
/* out of memory error already thrown */ /* out of memory error already thrown */
return 0; return JNI_FALSE;
} }
dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata, dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
...@@ -247,10 +362,10 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -247,10 +362,10 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
if (dstData == NULL) { if (dstData == NULL) {
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
/* out of memory error already thrown */ /* out of memory error already thrown */
return 0; return JNI_FALSE;
} }
ydataP = dstData + chanOff + y*sStride + x*pixelStride; ydataP = dstData + dstDataOff + y*sStride + x*pixelStride;
ypixP = srcData + off; ypixP = srcData + off;
for (i=0; i < h; i++) { for (i=0; i < h; i++) {
...@@ -268,7 +383,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls, ...@@ -268,7 +383,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
return 1; return JNI_TRUE;
} }
static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx, static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "java_awt_color_ColorSpace.h" #include "java_awt_color_ColorSpace.h"
#include "awt_Mlib.h" #include "awt_Mlib.h"
#include "safe_alloc.h" #include "safe_alloc.h"
#include "safe_math.h"
static int setHints(JNIEnv *env, BufImageS_t *imageP); static int setHints(JNIEnv *env, BufImageS_t *imageP);
......
...@@ -57,8 +57,8 @@ ...@@ -57,8 +57,8 @@
#define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b))
/* Cached Java method ids */ /* Cached Java method ids */
static jmethodID ImageInputStream_readID; static jmethodID JPEGImageReader_readInputDataID;
static jmethodID ImageInputStream_skipBytesID; static jmethodID JPEGImageReader_skipInputBytesID;
static jmethodID JPEGImageReader_warningOccurredID; static jmethodID JPEGImageReader_warningOccurredID;
static jmethodID JPEGImageReader_warningWithMessageID; static jmethodID JPEGImageReader_warningWithMessageID;
static jmethodID JPEGImageReader_setImageDataID; static jmethodID JPEGImageReader_setImageDataID;
...@@ -66,7 +66,7 @@ static jmethodID JPEGImageReader_acceptPixelsID; ...@@ -66,7 +66,7 @@ static jmethodID JPEGImageReader_acceptPixelsID;
static jmethodID JPEGImageReader_pushBackID; static jmethodID JPEGImageReader_pushBackID;
static jmethodID JPEGImageReader_passStartedID; static jmethodID JPEGImageReader_passStartedID;
static jmethodID JPEGImageReader_passCompleteID; static jmethodID JPEGImageReader_passCompleteID;
static jmethodID ImageOutputStream_writeID; static jmethodID JPEGImageWriter_writeOutputDataID;
static jmethodID JPEGImageWriter_warningOccurredID; static jmethodID JPEGImageWriter_warningOccurredID;
static jmethodID JPEGImageWriter_warningWithMessageID; static jmethodID JPEGImageWriter_warningWithMessageID;
static jmethodID JPEGImageWriter_writeMetadataID; static jmethodID JPEGImageWriter_writeMetadataID;
...@@ -923,7 +923,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo) ...@@ -923,7 +923,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo)
RELEASE_ARRAYS(env, data, src->next_input_byte); RELEASE_ARRAYS(env, data, src->next_input_byte);
ret = (*env)->CallIntMethod(env, ret = (*env)->CallIntMethod(env,
sb->stream, sb->stream,
ImageInputStream_readID, JPEGImageReader_readInputDataID,
sb->hstreamBuffer, 0, sb->hstreamBuffer, 0,
sb->bufferLength); sb->bufferLength);
if ((*env)->ExceptionOccurred(env) if ((*env)->ExceptionOccurred(env)
...@@ -1013,7 +1013,7 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo) ...@@ -1013,7 +1013,7 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo)
} }
ret = (*env)->CallIntMethod(env, sb->stream, ret = (*env)->CallIntMethod(env, sb->stream,
ImageInputStream_readID, JPEGImageReader_readInputDataID,
sb->hstreamBuffer, sb->hstreamBuffer,
offset, buflen); offset, buflen);
if ((*env)->ExceptionOccurred(env) if ((*env)->ExceptionOccurred(env)
...@@ -1107,7 +1107,7 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes) ...@@ -1107,7 +1107,7 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
RELEASE_ARRAYS(env, data, src->next_input_byte); RELEASE_ARRAYS(env, data, src->next_input_byte);
ret = (*env)->CallLongMethod(env, ret = (*env)->CallLongMethod(env,
sb->stream, sb->stream,
ImageInputStream_skipBytesID, JPEGImageReader_skipInputBytesID,
(jlong) num_bytes); (jlong) num_bytes);
if ((*env)->ExceptionOccurred(env) if ((*env)->ExceptionOccurred(env)
|| !GET_ARRAYS(env, data, &(src->next_input_byte))) { || !GET_ARRAYS(env, data, &(src->next_input_byte))) {
...@@ -1382,13 +1382,13 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initReaderIDs ...@@ -1382,13 +1382,13 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initReaderIDs
jclass qTableClass, jclass qTableClass,
jclass huffClass) { jclass huffClass) {
ImageInputStream_readID = (*env)->GetMethodID(env, JPEGImageReader_readInputDataID = (*env)->GetMethodID(env,
ImageInputStreamClass, cls,
"read", "readInputData",
"([BII)I"); "([BII)I");
ImageInputStream_skipBytesID = (*env)->GetMethodID(env, JPEGImageReader_skipInputBytesID = (*env)->GetMethodID(env,
ImageInputStreamClass, cls,
"skipBytes", "skipInputBytes",
"(J)J"); "(J)J");
JPEGImageReader_warningOccurredID = (*env)->GetMethodID(env, JPEGImageReader_warningOccurredID = (*env)->GetMethodID(env,
cls, cls,
...@@ -1531,8 +1531,7 @@ JNIEXPORT void JNICALL ...@@ -1531,8 +1531,7 @@ JNIEXPORT void JNICALL
Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource
(JNIEnv *env, (JNIEnv *env,
jobject this, jobject this,
jlong ptr, jlong ptr) {
jobject source) {
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_common_ptr cinfo; j_common_ptr cinfo;
...@@ -1546,7 +1545,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource ...@@ -1546,7 +1545,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource
cinfo = data->jpegObj; cinfo = data->jpegObj;
imageio_set_stream(env, cinfo, data, source); imageio_set_stream(env, cinfo, data, this);
imageio_init_source((j_decompress_ptr) cinfo); imageio_init_source((j_decompress_ptr) cinfo);
} }
...@@ -2291,7 +2290,7 @@ imageio_empty_output_buffer (j_compress_ptr cinfo) ...@@ -2291,7 +2290,7 @@ imageio_empty_output_buffer (j_compress_ptr cinfo)
(*env)->CallVoidMethod(env, (*env)->CallVoidMethod(env,
sb->stream, sb->stream,
ImageOutputStream_writeID, JPEGImageWriter_writeOutputDataID,
sb->hstreamBuffer, sb->hstreamBuffer,
0, 0,
sb->bufferLength); sb->bufferLength);
...@@ -2328,7 +2327,7 @@ imageio_term_destination (j_compress_ptr cinfo) ...@@ -2328,7 +2327,7 @@ imageio_term_destination (j_compress_ptr cinfo)
(*env)->CallVoidMethod(env, (*env)->CallVoidMethod(env,
sb->stream, sb->stream,
ImageOutputStream_writeID, JPEGImageWriter_writeOutputDataID,
sb->hstreamBuffer, sb->hstreamBuffer,
0, 0,
datacount); datacount);
...@@ -2366,13 +2365,12 @@ JNIEXPORT void JNICALL ...@@ -2366,13 +2365,12 @@ JNIEXPORT void JNICALL
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs
(JNIEnv *env, (JNIEnv *env,
jclass cls, jclass cls,
jclass IOSClass,
jclass qTableClass, jclass qTableClass,
jclass huffClass) { jclass huffClass) {
ImageOutputStream_writeID = (*env)->GetMethodID(env, JPEGImageWriter_writeOutputDataID = (*env)->GetMethodID(env,
IOSClass, cls,
"write", "writeOutputData",
"([BII)V"); "([BII)V");
JPEGImageWriter_warningOccurredID = (*env)->GetMethodID(env, JPEGImageWriter_warningOccurredID = (*env)->GetMethodID(env,
...@@ -2496,8 +2494,7 @@ JNIEXPORT void JNICALL ...@@ -2496,8 +2494,7 @@ JNIEXPORT void JNICALL
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
(JNIEnv *env, (JNIEnv *env,
jobject this, jobject this,
jlong ptr, jlong ptr) {
jobject destination) {
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr); imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
j_compress_ptr cinfo; j_compress_ptr cinfo;
...@@ -2511,7 +2508,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest ...@@ -2511,7 +2508,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
cinfo = (j_compress_ptr) data->jpegObj; cinfo = (j_compress_ptr) data->jpegObj;
imageio_set_stream(env, data->jpegObj, data, destination); imageio_set_stream(env, data->jpegObj, data, this);
// Don't call the init method, as that depends on pinned arrays // Don't call the init method, as that depends on pinned arrays
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "awt_Mlib.h" #include "awt_Mlib.h"
#include "gdefs.h" #include "gdefs.h"
#include "safe_alloc.h" #include "safe_alloc.h"
#include "safe_math.h"
/*************************************************************************** /***************************************************************************
* Definitions * * Definitions *
...@@ -1993,13 +1994,23 @@ cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component, ...@@ -1993,13 +1994,23 @@ cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,
unsigned char *dP = dataP; unsigned char *dP = dataP;
#define NUM_LINES 10 #define NUM_LINES 10
int numLines = NUM_LINES; int numLines = NUM_LINES;
int nbytes = rasterP->width*4*NUM_LINES; /* it is safe to calculate the scan length, because width has been verified
* on creation of the mlib image
*/
int scanLength = rasterP->width * 4;
int nbytes = 0;
if (!SAFE_TO_MULT(numLines, scanLength)) {
return -1;
}
nbytes = numLines * scanLength;
for (y=0; y < rasterP->height; y+=numLines) { for (y=0; y < rasterP->height; y+=numLines) {
/* getData, one scanline at a time */ /* getData, one scanline at a time */
if (y+numLines > rasterP->height) { if (y+numLines > rasterP->height) {
numLines = rasterP->height - y; numLines = rasterP->height - y;
nbytes = rasterP->width*4*numLines; nbytes = numLines * scanLength;
} }
jpixels = (*env)->CallObjectMethod(env, imageP->jimage, jpixels = (*env)->CallObjectMethod(env, imageP->jimage,
g_BImgGetRGBMID, 0, y, g_BImgGetRGBMID, 0, y,
...@@ -2129,8 +2140,14 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP, ...@@ -2129,8 +2140,14 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP,
if (cvtToDefault) { if (cvtToDefault) {
int status = 0; int status = 0;
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height); *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
if (*mlibImagePP == NULL) {
return -1;
}
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
/* Make sure the image is cleared */ /* Make sure the image is cleared.
* NB: the image dimension is already verified, so we can
* safely calculate the length of the buffer.
*/
memset(cDataP, 0, width*height*4); memset(cDataP, 0, width*height*4);
if (!isSrc) { if (!isSrc) {
...@@ -2380,6 +2397,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, ...@@ -2380,6 +2397,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES: case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
width, height); width, height);
if (*mlibImagePP == NULL) {
return -1;
}
if (!isSrc) return 0; if (!isSrc) return 0;
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
return expandPackedBCR(env, rasterP, -1, cDataP); return expandPackedBCR(env, rasterP, -1, cDataP);
...@@ -2388,6 +2408,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, ...@@ -2388,6 +2408,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
if (rasterP->sppsm.maxBitSize <= 8) { if (rasterP->sppsm.maxBitSize <= 8) {
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
width, height); width, height);
if (*mlibImagePP == NULL) {
return -1;
}
if (!isSrc) return 0; if (!isSrc) return 0;
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
return expandPackedSCR(env, rasterP, -1, cDataP); return expandPackedSCR(env, rasterP, -1, cDataP);
...@@ -2397,6 +2420,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP, ...@@ -2397,6 +2420,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
if (rasterP->sppsm.maxBitSize <= 8) { if (rasterP->sppsm.maxBitSize <= 8) {
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands, *mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
width, height); width, height);
if (*mlibImagePP == NULL) {
return -1;
}
if (!isSrc) return 0; if (!isSrc) return 0;
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP); cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
return expandPackedICR(env, rasterP, -1, cDataP); return expandPackedICR(env, rasterP, -1, cDataP);
......
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
#include "mlib_image.h" #include "mlib_image.h"
#include "mlib_ImageRowTable.h" #include "mlib_ImageRowTable.h"
#include "mlib_ImageCreate.h" #include "mlib_ImageCreate.h"
#include "safe_math.h"
/***************************************************************/ /***************************************************************/
mlib_image* mlib_ImageSet(mlib_image *image, mlib_image* mlib_ImageSet(mlib_image *image,
...@@ -247,28 +248,50 @@ mlib_image *mlib_ImageCreate(mlib_type type, ...@@ -247,28 +248,50 @@ mlib_image *mlib_ImageCreate(mlib_type type,
return NULL; return NULL;
}; };
if (!SAFE_TO_MULT(width, channels)) {
return NULL;
}
wb = width * channels;
switch (type) { switch (type) {
case MLIB_DOUBLE: case MLIB_DOUBLE:
wb = width * channels * 8; if (!SAFE_TO_MULT(wb, 8)) {
return NULL;
}
wb *= 8;
break; break;
case MLIB_FLOAT: case MLIB_FLOAT:
case MLIB_INT: case MLIB_INT:
wb = width * channels * 4; if (!SAFE_TO_MULT(wb, 4)) {
return NULL;
}
wb *= 4;
break; break;
case MLIB_USHORT: case MLIB_USHORT:
case MLIB_SHORT: case MLIB_SHORT:
wb = width * channels * 2; if (!SAFE_TO_MULT(wb, 4)) {
return NULL;
}
wb *= 2;
break; break;
case MLIB_BYTE: case MLIB_BYTE:
wb = width * channels; // wb is ready
break; break;
case MLIB_BIT: case MLIB_BIT:
wb = (width * channels + 7) / 8; if (!SAFE_TO_ADD(7, wb)) {
return NULL;
}
wb = (wb + 7) / 8;
break; break;
default: default:
return NULL; return NULL;
} }
if (!SAFE_TO_MULT(wb, height)) {
return NULL;
}
data = mlib_malloc(wb * height); data = mlib_malloc(wb * height);
if (data == NULL) { if (data == NULL) {
return NULL; return NULL;
......
...@@ -41,10 +41,4 @@ ...@@ -41,10 +41,4 @@
(((w) > 0) && ((h) > 0) && ((sz) > 0) && \ (((w) > 0) && ((h) > 0) && ((sz) > 0) && \
(((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz)))) (((0xffffffffu / ((juint)(w))) / ((juint)(h))) > ((juint)(sz))))
#define SAFE_TO_MULT(a, b) \
(((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
#define SAFE_TO_ADD(a, b) \
(((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b)))
#endif // __SAFE_ALLOC_H__ #endif // __SAFE_ALLOC_H__
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
#ifndef __SAFE_MATH_H__
#define __SAFE_MATH_H__
#define SAFE_TO_MULT(a, b) \
(((a) > 0) && ((b) >= 0) && ((0x7fffffff / (a)) > (b)))
#define SAFE_TO_ADD(a, b) \
(((a) >= 0) && ((b) >= 0) && ((0x7fffffff - (a)) > (b)))
#endif // __SAFE_MATH_H__
...@@ -66,8 +66,21 @@ FontInstanceAdapter::FontInstanceAdapter(JNIEnv *theEnv, ...@@ -66,8 +66,21 @@ FontInstanceAdapter::FontInstanceAdapter(JNIEnv *theEnv,
yScalePixelsToUnits = upem / yppem; yScalePixelsToUnits = upem / yppem;
}; };
const void *FontInstanceAdapter::getFontTable(LETag tableTag) const const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
{ {
size_t ignored = 0;
return getFontTable(tableTag, ignored);
}
static const LETag cacheMap[LAYOUTCACHE_ENTRIES] = {
GPOS_TAG, GDEF_TAG, GSUB_TAG, MORT_TAG, MORX_TAG, KERN_TAG
};
const void *FontInstanceAdapter::getFontTable(LETag tableTag, size_t &length) const
{
length = 0;
if (!layoutTables) { // t1 font if (!layoutTables) { // t1 font
return 0; return 0;
} }
...@@ -75,14 +88,19 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const ...@@ -75,14 +88,19 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
// cache in font's pscaler object // cache in font's pscaler object
// font disposer will handle for us // font disposer will handle for us
switch(tableTag) { int cacheIdx;
case GSUB_TAG: if (layoutTables->gsub_len != -1) return (void*)layoutTables->gsub; break; for (cacheIdx=0;cacheIdx<LAYOUTCACHE_ENTRIES;cacheIdx++) {
case GPOS_TAG: if (layoutTables->gpos_len != -1) return (void*)layoutTables->gpos; break; if (tableTag==cacheMap[cacheIdx]) break;
case GDEF_TAG: if (layoutTables->gdef_len != -1) return (void*)layoutTables->gdef; break; }
case MORT_TAG: if (layoutTables->mort_len != -1) return (void*)layoutTables->mort; break;
case KERN_TAG: if (layoutTables->kern_len != -1) return (void*)layoutTables->kern; break; if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if found
default: if (layoutTables->entries[cacheIdx].len != -1) {
//fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag); length = layoutTables->entries[cacheIdx].len;
return layoutTables->entries[cacheIdx].ptr;
}
} else {
//fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag);
// (don't load any other tables)
return 0; return 0;
} }
...@@ -96,16 +114,13 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const ...@@ -96,16 +114,13 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
env->GetByteArrayRegion(tableBytes, 0, len, result); env->GetByteArrayRegion(tableBytes, 0, len, result);
} }
switch(tableTag) { if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if cacheable table
case GSUB_TAG: layoutTables->gsub = (void*)result; layoutTables->gsub_len = len; break; layoutTables->entries[cacheIdx].len = len;
case GPOS_TAG: layoutTables->gpos = (void*)result; layoutTables->gpos_len = len; break; layoutTables->entries[cacheIdx].ptr = (const void*)result;
case GDEF_TAG: layoutTables->gdef = (void*)result; layoutTables->gdef_len = len; break;
case MORT_TAG: layoutTables->mort = (void*)result; layoutTables->mort_len = len; break;
case KERN_TAG: layoutTables->kern = (void*)result; layoutTables->kern_len = len; break;
default: break;
} }
return (void*)result; length = len;
return (const void*)result;
}; };
LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
......
...@@ -86,6 +86,7 @@ public: ...@@ -86,6 +86,7 @@ public:
// tables are cached with the native font scaler data // tables are cached with the native font scaler data
// only supports gsub, gpos, gdef, mort tables at present // only supports gsub, gpos, gdef, mort tables at present
virtual const void *getFontTable(LETag tableTag) const; virtual const void *getFontTable(LETag tableTag) const;
virtual const void *getFontTable(LETag tableTag, size_t &len) const;
virtual void *getKernPairs() const { virtual void *getKernPairs() const {
return layoutTables->kernPairs; return layoutTables->kernPairs;
......
...@@ -120,20 +120,19 @@ typedef struct GlyphInfo { ...@@ -120,20 +120,19 @@ typedef struct GlyphInfo {
#define GPOS_TAG 0x47504F53 /* 'GPOS' */ #define GPOS_TAG 0x47504F53 /* 'GPOS' */
#define GDEF_TAG 0x47444546 /* 'GDEF' */ #define GDEF_TAG 0x47444546 /* 'GDEF' */
#define MORT_TAG 0x6D6F7274 /* 'mort' */ #define MORT_TAG 0x6D6F7274 /* 'mort' */
#define MORX_TAG 0x6D6F7278 /* 'morx' */
#define KERN_TAG 0x6B65726E /* 'kern' */ #define KERN_TAG 0x6B65726E /* 'kern' */
typedef struct TTLayoutTableCacheEntry {
const void* ptr;
int len;
} TTLayoutTableCacheEntry;
#define LAYOUTCACHE_ENTRIES 6
typedef struct TTLayoutTableCache { typedef struct TTLayoutTableCache {
void* gsub; TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES];
void* gpos; void* kernPairs;
void* gdef;
void* mort;
void* kern;
void* kernPairs;
int gsub_len;
int gpos_len;
int gdef_len;
int mort_len;
int kern_len;
} TTLayoutTableCache; } TTLayoutTableCache;
#include "sunfontids.h" #include "sunfontids.h"
......
...@@ -39,19 +39,20 @@ ...@@ -39,19 +39,20 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
le_uint32 AlternateSubstitutionSubtable::process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter) const le_uint32 AlternateSubstitutionSubtable::process(const LEReferenceTo<AlternateSubstitutionSubtable> &base,
GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter) const
{ {
// NOTE: For now, we'll just pick the first alternative... // NOTE: For now, we'll just pick the first alternative...
LEGlyphID glyph = glyphIterator->getCurrGlyphID(); LEGlyphID glyph = glyphIterator->getCurrGlyphID();
le_int32 coverageIndex = getGlyphCoverage(glyph); le_int32 coverageIndex = getGlyphCoverage(base, glyph, success);
if (coverageIndex >= 0) { if (coverageIndex >= 0 && LE_SUCCESS(success)) {
le_uint16 altSetCount = SWAPW(alternateSetCount); le_uint16 altSetCount = SWAPW(alternateSetCount);
if (coverageIndex < altSetCount) { if (coverageIndex < altSetCount) {
Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]); Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]);
const AlternateSetTable *alternateSetTable = const LEReferenceTo<AlternateSetTable> alternateSetTable(base, success,
(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))) {
......
...@@ -51,13 +51,17 @@ struct AlternateSetTable ...@@ -51,13 +51,17 @@ struct AlternateSetTable
TTGlyphID alternateArray[ANY_NUMBER]; TTGlyphID alternateArray[ANY_NUMBER];
}; };
LE_VAR_ARRAY(AlternateSetTable, alternateArray)
struct AlternateSubstitutionSubtable : GlyphSubstitutionSubtable struct AlternateSubstitutionSubtable : GlyphSubstitutionSubtable
{ {
le_uint16 alternateSetCount; le_uint16 alternateSetCount;
Offset alternateSetTableOffsetArray[ANY_NUMBER]; Offset alternateSetTableOffsetArray[ANY_NUMBER];
le_uint32 process(GlyphIterator *glyphIterator, const LEGlyphFilter *filter = NULL) const; le_uint32 process(const LEReferenceTo<AlternateSubstitutionSubtable> &base, GlyphIterator *glyphIterator, LEErrorCode &success, const LEGlyphFilter *filter = NULL) const;
}; };
LE_VAR_ARRAY(AlternateSubstitutionSubtable, alternateSetTableOffsetArray)
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2005 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
* *
*/ */
...@@ -58,15 +58,18 @@ le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const ...@@ -58,15 +58,18 @@ le_bool CharSubstitutionFilter::accept(LEGlyphID glyph) const
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine) UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success) le_int32 languageCode, le_int32 typoFlags,
const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable,
LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success) : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
{ {
fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount); fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
fFeatureOrder = TRUE; fFeatureOrder = TRUE;
} }
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
le_int32 languageCode,
le_int32 typoFlags, LEErrorCode &success) le_int32 typoFlags, LEErrorCode &success)
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success) : OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
{ {
...@@ -88,8 +91,9 @@ ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine() ...@@ -88,8 +91,9 @@ ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
// Input: characters // Input: characters
// Output: characters, char indices, tags // Output: characters, char indices, tags
// Returns: output character count // Returns: output character count
le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count,
LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success) le_int32 max, le_bool rightToLeft, LEUnicode *&outChars,
LEGlyphStorage &glyphStorage, LEErrorCode &success)
{ {
if (LE_FAILURE(success)) { if (LE_FAILURE(success)) {
return 0; return 0;
...@@ -137,32 +141,30 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l ...@@ -137,32 +141,30 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l
return; return;
} }
if (fGPOSTable != NULL) { if (!fGPOSTable.isEmpty()) {
OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success); OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
} else if (fGDEFTable != NULL) { } else if (!fGDEFTable.isEmpty()) {
GDEFMarkFilter filter(fGDEFTable); GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(glyphStorage, &filter, success); adjustMarkGlyphs(glyphStorage, &filter, success);
} else { } else {
GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable; LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
GDEFMarkFilter filter(gdefTable); GDEFMarkFilter filter(gdefTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success); adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
} }
} }
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, success) : ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success)
{ {
fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable; fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable; fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
/* OpenTypeLayoutEngine will allocate a substitution filter */
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
} }
UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine() UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
{ {
delete fSubstitutionFilter; /* OpenTypeLayoutEngine will cleanup the substitution filter */
} }
// "glyphs", "indices" -> glyphs, indices // "glyphs", "indices" -> glyphs, indices
...@@ -233,7 +235,7 @@ void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode cha ...@@ -233,7 +235,7 @@ void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode cha
return; return;
} }
GDEFMarkFilter filter(fGDEFTable); GDEFMarkFilter filter(fGDEFTable, success);
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success); adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
} }
......
...@@ -75,7 +75,7 @@ public: ...@@ -75,7 +75,7 @@ public:
* @internal * @internal
*/ */
ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success); le_int32 typoFlags, const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable, LEErrorCode &success);
/** /**
* This constructor is used when the font requires a "canned" GSUB table which can't be known * This constructor is used when the font requires a "canned" GSUB table which can't be known
......
...@@ -58,14 +58,16 @@ const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] = ...@@ -58,14 +58,16 @@ const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
*/ */
ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c) ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
{ {
const ClassDefinitionTable *joiningTypes = (const ClassDefinitionTable *) ArabicShaping::shapingTypeTable; LEErrorCode success = LE_NO_ERROR;
le_int32 joiningType = joiningTypes->getGlyphClass(c); const LEReferenceTo<ClassDefinitionTable> joiningTypes((const ClassDefinitionTable *) ArabicShaping::shapingTypeTable,
ArabicShaping::shapingTypeTableLen);
le_int32 joiningType = joiningTypes->getGlyphClass(joiningTypes, c, success);
if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT) { if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT && LE_SUCCESS(success)) {
return ArabicShaping::shapeTypes[joiningType]; return ArabicShaping::shapeTypes[joiningType];
} }
return ArabicShaping::ST_NOSHAPE_NONE; return ArabicShaping::ST_NOSHAPE_NONE;
} }
#define isolFeatureTag LE_ISOL_FEATURE_TAG #define isolFeatureTag LE_ISOL_FEATURE_TAG
......
...@@ -93,6 +93,8 @@ private: ...@@ -93,6 +93,8 @@ private:
static ShapeType getShapeType(LEUnicode c); static ShapeType getShapeType(LEUnicode c);
static const le_uint8 shapingTypeTable[]; static const le_uint8 shapingTypeTable[];
static const size_t shapingTypeTableLen;
static const ShapeType shapeTypes[]; static const ShapeType shapeTypes[];
static void adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage); static void adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage);
......
...@@ -52,14 +52,14 @@ struct AttachmentPositioningSubtable : GlyphPositioningSubtable ...@@ -52,14 +52,14 @@ struct AttachmentPositioningSubtable : GlyphPositioningSubtable
Offset markArrayOffset; Offset markArrayOffset;
Offset baseArrayOffset; Offset baseArrayOffset;
inline le_int32 getBaseCoverage(LEGlyphID baseGlyphId) const; inline le_int32 getBaseCoverage(const LETableReference &base, LEGlyphID baseGlyphId, LEErrorCode &success) const;
le_uint32 process(GlyphIterator *glyphIterator) const; le_uint32 process(GlyphIterator *glyphIterator) const;
}; };
inline le_int32 AttachmentPositioningSubtable::getBaseCoverage(LEGlyphID baseGlyphID) const inline le_int32 AttachmentPositioningSubtable::getBaseCoverage(const LETableReference &base, LEGlyphID baseGlyphID, LEErrorCode &success) const
{ {
return getGlyphCoverage(baseCoverageTableOffset, baseGlyphID); return getGlyphCoverage(base, baseCoverageTableOffset, baseGlyphID, success);
} }
U_NAMESPACE_END U_NAMESPACE_END
......
...@@ -3641,4 +3641,9 @@ const le_uint8 CanonShaping::glyphDefinitionTable[] = { ...@@ -3641,4 +3641,9 @@ const le_uint8 CanonShaping::glyphDefinitionTable[] = {
0x00, 0xE6, 0xD2, 0x42, 0xD2, 0x44, 0x00, 0xE6 0x00, 0xE6, 0xD2, 0x42, 0xD2, 0x44, 0x00, 0xE6
}; };
const size_t CanonShaping::glyphSubstitutionTableLen = sizeof(glyphSubstitutionTable)/sizeof(glyphSubstitutionTable[0]);
const size_t CanonShaping::glyphDefinitionTableLen = sizeof(glyphDefinitionTable)/sizeof(glyphDefinitionTable[0]);
U_NAMESPACE_END U_NAMESPACE_END
...@@ -59,15 +59,15 @@ void CanonShaping::sortMarks(le_int32 *indices, const le_int32 *combiningClasses ...@@ -59,15 +59,15 @@ void CanonShaping::sortMarks(le_int32 *indices, const le_int32 *combiningClasses
void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft, void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
LEUnicode *outChars, LEGlyphStorage &glyphStorage) LEUnicode *outChars, LEGlyphStorage &glyphStorage)
{ {
const GlyphDefinitionTableHeader *gdefTable = (const GlyphDefinitionTableHeader *) glyphDefinitionTable; LEErrorCode success = LE_NO_ERROR;
const ClassDefinitionTable *classTable = gdefTable->getMarkAttachClassDefinitionTable(); LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
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);
LEErrorCode status = LE_NO_ERROR;
le_int32 i; le_int32 i;
for (i = 0; i < charCount; i += 1) { for (i = 0; i < charCount; i += 1) {
combiningClasses[i] = classTable->getGlyphClass((LEGlyphID) inChars[i]); combiningClasses[i] = classTable->getGlyphClass(classTable, (LEGlyphID) inChars[i], success);
indices[i] = i; indices[i] = i;
} }
...@@ -96,7 +96,7 @@ void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le ...@@ -96,7 +96,7 @@ void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le
le_int32 index = indices[i]; le_int32 index = indices[i];
outChars[i] = inChars[index]; outChars[i] = inChars[index];
glyphStorage.setCharIndex(out, index, status); glyphStorage.setCharIndex(out, index, success);
} }
LE_DELETE_ARRAY(indices); LE_DELETE_ARRAY(indices);
......
...@@ -42,7 +42,9 @@ class U_LAYOUT_API CanonShaping /* not : public UObject because all members are ...@@ -42,7 +42,9 @@ class U_LAYOUT_API CanonShaping /* not : public UObject because all members are
{ {
public: public:
static const le_uint8 glyphSubstitutionTable[]; static const le_uint8 glyphSubstitutionTable[];
static const size_t glyphSubstitutionTableLen;
static const le_uint8 glyphDefinitionTable[]; static const le_uint8 glyphDefinitionTable[];
static const size_t glyphDefinitionTableLen;
static void reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft, static void reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
LEUnicode *outChars, LEGlyphStorage &glyphStorage); LEUnicode *outChars, LEGlyphStorage &glyphStorage);
......
...@@ -37,49 +37,51 @@ ...@@ -37,49 +37,51 @@
U_NAMESPACE_BEGIN U_NAMESPACE_BEGIN
le_int32 ClassDefinitionTable::getGlyphClass(LEGlyphID glyphID) const le_int32 ClassDefinitionTable::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{ {
switch(SWAPW(classFormat)) { LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
if (LE_FAILURE(success)) return 0;
switch(SWAPW(classFormat)) {
case 0: case 0:
return 0; return 0;
case 1: case 1:
{ {
const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this; const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
return f1Table->getGlyphClass(f1Table, glyphID, success);
return f1Table->getGlyphClass(glyphID);
} }
case 2: case 2:
{ {
const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this; const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
return f2Table->getGlyphClass(f2Table, glyphID, success);
return f2Table->getGlyphClass(glyphID);
} }
default: default:
return 0; return 0;
} }
} }
le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const le_bool ClassDefinitionTable::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{ {
LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
if (LE_FAILURE(success)) return 0;
switch(SWAPW(classFormat)) { switch(SWAPW(classFormat)) {
case 0: case 0:
return 0; return 0;
case 1: case 1:
{ {
const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this; const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
return f1Table->hasGlyphClass(f1Table, glyphClass, success);
return f1Table->hasGlyphClass(glyphClass);
} }
case 2: case 2:
{ {
const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this; const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
return f2Table->hasGlyphClass(f2Table, glyphClass, success);
return f2Table->hasGlyphClass(glyphClass);
} }
default: default:
...@@ -87,26 +89,32 @@ le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const ...@@ -87,26 +89,32 @@ le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const
} }
} }
le_int32 ClassDefFormat1Table::getGlyphClass(LEGlyphID glyphID) const le_int32 ClassDefFormat1Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{ {
if(LE_FAILURE(success)) return 0;
le_uint16 count = SWAPW(glyphCount);
LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID); TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID);
TTGlyphID firstGlyph = SWAPW(startGlyph); TTGlyphID firstGlyph = SWAPW(startGlyph);
TTGlyphID lastGlyph = firstGlyph + SWAPW(glyphCount); TTGlyphID lastGlyph = firstGlyph + count;
if (ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) { if (LE_SUCCESS(success) && ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
return SWAPW(classValueArray[ttGlyphID - firstGlyph]); return SWAPW( classValueArrayRef(ttGlyphID - firstGlyph, success) );
} }
return 0; return 0;
} }
le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const le_bool ClassDefFormat1Table::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{ {
le_uint16 count = SWAPW(glyphCount); if(LE_FAILURE(success)) return 0;
le_uint16 count = SWAPW(glyphCount);
LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
int i; int i;
for (i = 0; i < count; i += 1) { for (i = 0; LE_SUCCESS(success)&& (i < count); i += 1) {
if (SWAPW(classValueArray[i]) == glyphClass) { if (SWAPW(classValueArrayRef(i,success)) == glyphClass) {
return TRUE; return TRUE;
} }
} }
...@@ -114,27 +122,31 @@ le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const ...@@ -114,27 +122,31 @@ le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const
return FALSE; return FALSE;
} }
le_int32 ClassDefFormat2Table::getGlyphClass(LEGlyphID glyphID) const le_int32 ClassDefFormat2Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
{ {
if(LE_FAILURE(success)) return 0;
TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyphID); TTGlyphID ttGlyph = (TTGlyphID) LE_GET_GLYPH(glyphID);
le_uint16 rangeCount = SWAPW(classRangeCount); le_uint16 rangeCount = SWAPW(classRangeCount);
LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
le_int32 rangeIndex = le_int32 rangeIndex =
OpenTypeUtilities::getGlyphRangeIndex(ttGlyph, classRangeRecordArray, rangeCount); OpenTypeUtilities::getGlyphRangeIndex(ttGlyph, classRangeRecordArrayRef, success);
if (rangeIndex < 0) { if (rangeIndex < 0 || LE_FAILURE(success)) {
return 0; return 0;
} }
return SWAPW(classRangeRecordArray[rangeIndex].rangeValue); return SWAPW(classRangeRecordArrayRef(rangeIndex, success).rangeValue);
} }
le_bool ClassDefFormat2Table::hasGlyphClass(le_int32 glyphClass) const le_bool ClassDefFormat2Table::hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const
{ {
if(LE_FAILURE(success)) return 0;
le_uint16 rangeCount = SWAPW(classRangeCount); le_uint16 rangeCount = SWAPW(classRangeCount);
LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
int i; int i;
for (i = 0; i < rangeCount; i += 1) { for (i = 0; i < rangeCount && LE_SUCCESS(success); i += 1) {
if (SWAPW(classRangeRecordArray[i].rangeValue) == glyphClass) { if (SWAPW(classRangeRecordArrayRef(i,success).rangeValue) == glyphClass) {
return TRUE; return TRUE;
} }
} }
......
...@@ -46,8 +46,20 @@ struct ClassDefinitionTable ...@@ -46,8 +46,20 @@ struct ClassDefinitionTable
{ {
le_uint16 classFormat; le_uint16 classFormat;
le_int32 getGlyphClass(LEGlyphID glyphID) const; le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(le_int32 glyphClass) const; le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
le_int32 getGlyphClass(LEGlyphID glyphID) const {
LETableReference base((const le_uint8*)this);
LEErrorCode ignored = LE_NO_ERROR;
return getGlyphClass(base,glyphID,ignored);
}
le_bool hasGlyphClass(le_int32 glyphClass) const {
LETableReference base((const le_uint8*)this);
LEErrorCode ignored = LE_NO_ERROR;
return hasGlyphClass(base,glyphClass,ignored);
}
}; };
struct ClassDefFormat1Table : ClassDefinitionTable struct ClassDefFormat1Table : ClassDefinitionTable
...@@ -56,9 +68,11 @@ struct ClassDefFormat1Table : ClassDefinitionTable ...@@ -56,9 +68,11 @@ struct ClassDefFormat1Table : ClassDefinitionTable
le_uint16 glyphCount; le_uint16 glyphCount;
le_uint16 classValueArray[ANY_NUMBER]; le_uint16 classValueArray[ANY_NUMBER];
le_int32 getGlyphClass(LEGlyphID glyphID) const; le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(le_int32 glyphClass) const; le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
}; };
LE_VAR_ARRAY(ClassDefFormat1Table, classValueArray)
struct ClassRangeRecord struct ClassRangeRecord
{ {
...@@ -72,9 +86,10 @@ struct ClassDefFormat2Table : ClassDefinitionTable ...@@ -72,9 +86,10 @@ struct ClassDefFormat2Table : ClassDefinitionTable
le_uint16 classRangeCount; le_uint16 classRangeCount;
GlyphRangeRecord classRangeRecordArray[ANY_NUMBER]; GlyphRangeRecord classRangeRecordArray[ANY_NUMBER];
le_int32 getGlyphClass(LEGlyphID glyphID) const; le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
le_bool hasGlyphClass(le_int32 glyphClass) const; le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
}; };
LE_VAR_ARRAY(ClassDefFormat2Table, classRangeRecordArray)
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
* *
*/ */
...@@ -49,6 +49,11 @@ struct ContextualGlyphInsertionHeader : MorphStateTableHeader ...@@ -49,6 +49,11 @@ struct ContextualGlyphInsertionHeader : MorphStateTableHeader
{ {
}; };
struct ContextualGlyphInsertionHeader2 : MorphStateTableHeader2
{
le_uint32 insertionTableOffset;
};
enum ContextualGlyphInsertionFlags enum ContextualGlyphInsertionFlags
{ {
cgiSetMark = 0x8000, cgiSetMark = 0x8000,
...@@ -61,11 +66,17 @@ enum ContextualGlyphInsertionFlags ...@@ -61,11 +66,17 @@ enum ContextualGlyphInsertionFlags
cgiMarkedInsertCountMask = 0x001F cgiMarkedInsertCountMask = 0x001F
}; };
struct LigatureSubstitutionStateEntry : StateEntry struct ContextualGlyphInsertionStateEntry : StateEntry
{ {
ByteOffset currentInsertionListOffset; ByteOffset currentInsertionListOffset;
ByteOffset markedInsertionListOffset; ByteOffset markedInsertionListOffset;
}; };
struct ContextualGlyphInsertionStateEntry2 : StateEntry2
{
le_uint16 currentInsertionListIndex;
le_uint16 markedInsertionListIndex;
};
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*
*/
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphInsertionProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphInsertionProcessor2)
ContextualGlyphInsertionProcessor2::ContextualGlyphInsertionProcessor2(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor2(morphSubtableHeader, success)
{
contextualGlyphHeader = LEReferenceTo<ContextualGlyphInsertionHeader2>(morphSubtableHeader, success);
if(LE_FAILURE(success) || !contextualGlyphHeader.isValid()) return;
le_uint32 insertionTableOffset = SWAPL(contextualGlyphHeader->insertionTableOffset);
insertionTable = LEReferenceToArrayOf<le_uint16>(stHeader, success, insertionTableOffset, LE_UNBOUNDED_ARRAY);
entryTable = LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
ContextualGlyphInsertionProcessor2::~ContextualGlyphInsertionProcessor2()
{
}
void ContextualGlyphInsertionProcessor2::beginStateTable()
{
markGlyph = 0;
}
void ContextualGlyphInsertionProcessor2::doInsertion(LEGlyphStorage &glyphStorage,
le_int16 atGlyph,
le_int16 &index,
le_int16 count,
le_bool /* isKashidaLike */,
le_bool isBefore,
LEErrorCode &success) {
LEGlyphID *insertGlyphs = glyphStorage.insertGlyphs(atGlyph, count + 1, success);
if(LE_FAILURE(success) || insertGlyphs==NULL) {
return;
}
// Note: Kashida vs Split Vowel seems to only affect selection and highlighting.
// We note the flag, but do not layout different.
// https://developer.apple.com/fonts/TTRefMan/RM06/Chap6mort.html
le_int16 targetIndex = 0;
if(isBefore) {
// insert at beginning
insertGlyphs[targetIndex++] = glyphStorage[atGlyph];
} else {
// insert at end
insertGlyphs[count] = glyphStorage[atGlyph];
}
while(count--) {
insertGlyphs[targetIndex++] = insertionTable.getObject(index++, success);
}
glyphStorage.applyInsertions();
}
le_uint16 ContextualGlyphInsertionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
EntryTableIndex2 index, LEErrorCode &success)
{
const ContextualGlyphInsertionStateEntry2 *entry = entryTable.getAlias(index, success);
if(LE_FAILURE(success)) return 0; // TODO- which state?
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 markIndex = SWAPW(entry->markedInsertionListIndex);
if (markIndex > 0) {
le_int16 count = (flags & cgiMarkedInsertCountMask) >> 5;
le_bool isKashidaLike = (flags & cgiMarkedIsKashidaLike);
le_bool isBefore = (flags & cgiMarkInsertBefore);
doInsertion(glyphStorage, markGlyph, markIndex, count, isKashidaLike, isBefore, success);
}
le_int16 currIndex = SWAPW(entry->currentInsertionListIndex);
if (currIndex > 0) {
le_int16 count = flags & cgiCurrentInsertCountMask;
le_bool isKashidaLike = (flags & cgiCurrentIsKashidaLike);
le_bool isBefore = (flags & cgiCurrentInsertBefore);
doInsertion(glyphStorage, currGlyph, currIndex, count, isKashidaLike, isBefore, success);
}
if (flags & cgiSetMark) {
markGlyph = currGlyph;
}
if (!(flags & cgiDontAdvance)) {
currGlyph += dir;
}
return newState;
}
void ContextualGlyphInsertionProcessor2::endStateTable()
{
}
U_NAMESPACE_END
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*
*/
/*
*
* (C) Copyright IBM Corp. and others 2013 - All Rights Reserved
*
*/
#ifndef __CONTEXTUALGLYPHINSERTIONPROCESSOR2_H
#define __CONTEXTUALGLYPHINSERTIONPROCESSOR2_H
/**
* \file
* \internal
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphInsertionProc2.h"
#include "ContextualGlyphInsertion.h"
U_NAMESPACE_BEGIN
class LEGlyphStorage;
class ContextualGlyphInsertionProcessor2 : public StateTableProcessor2
{
public:
virtual void beginStateTable();
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage,
le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
virtual void endStateTable();
ContextualGlyphInsertionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
virtual ~ContextualGlyphInsertionProcessor2();
/**
* ICU "poor man's RTTI", returns a UClassID for the actual class.
*
* @stable ICU 2.8
*/
virtual UClassID getDynamicClassID() const;
/**
* ICU "poor man's RTTI", returns a UClassID for this class.
*
* @stable ICU 2.8
*/
static UClassID getStaticClassID();
private:
ContextualGlyphInsertionProcessor2();
/**
* Perform the actual insertion
* @param atGlyph index of glyph to insert at
* @param index index into the insertionTable (in/out)
* @param count number of insertions
* @param isKashidaLike Kashida like (vs Split Vowel like). No effect currently.
* @param isBefore if true, insert extra glyphs before the marked glyph
*/
void doInsertion(LEGlyphStorage &glyphStorage,
le_int16 atGlyph,
le_int16 &index,
le_int16 count,
le_bool isKashidaLike,
le_bool isBefore,
LEErrorCode &success);
protected:
le_int32 markGlyph;
LEReferenceToArrayOf<le_uint16> insertionTable;
LEReferenceToArrayOf<ContextualGlyphInsertionStateEntry2> entryTable;
LEReferenceTo<ContextualGlyphInsertionHeader2> contextualGlyphHeader;
};
U_NAMESPACE_END
#endif
...@@ -43,13 +43,18 @@ U_NAMESPACE_BEGIN ...@@ -43,13 +43,18 @@ U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor) UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor)
ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader) ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor(morphSubtableHeader) : StateTableProcessor(morphSubtableHeader, success), entryTable(), contextualGlyphSubstitutionHeader(morphSubtableHeader, success)
{ {
contextualGlyphSubstitutionHeader = (const ContextualGlyphSubstitutionHeader *) morphSubtableHeader; contextualGlyphSubstitutionHeader.orphan();
substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset); substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset);
entryTable = (const ContextualGlyphSubstitutionStateEntry *) ((char *) &stateTableHeader->stHeader + entryTableOffset);
entryTable = LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry>(stateTableHeader, success,
(const ContextualGlyphSubstitutionStateEntry*)(&stateTableHeader->stHeader),
entryTableOffset, LE_UNBOUNDED_ARRAY);
int16Table = LEReferenceToArrayOf<le_int16>(stateTableHeader, success, (const le_int16*)(&stateTableHeader->stHeader),
0, LE_UNBOUNDED_ARRAY); // rest of the table as le_int16s
} }
ContextualGlyphSubstitutionProcessor::~ContextualGlyphSubstitutionProcessor() ContextualGlyphSubstitutionProcessor::~ContextualGlyphSubstitutionProcessor()
...@@ -63,27 +68,26 @@ void ContextualGlyphSubstitutionProcessor::beginStateTable() ...@@ -63,27 +68,26 @@ void ContextualGlyphSubstitutionProcessor::beginStateTable()
ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index) ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
{ {
const ContextualGlyphSubstitutionStateEntry *entry = &entryTable[index]; LEErrorCode success = LE_NO_ERROR;
ByteOffset newState = SWAPW(entry->newStateOffset); const ContextualGlyphSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
le_int16 flags = SWAPW(entry->flags); ByteOffset newState = SWAPW(entry->newStateOffset);
WordOffset markOffset = SWAPW(entry->markOffset); le_int16 flags = SWAPW(entry->flags);
WordOffset currOffset = SWAPW(entry->currOffset); WordOffset markOffset = SWAPW(entry->markOffset);
WordOffset currOffset = SWAPW(entry->currOffset);
if (markOffset != 0) {
const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + markOffset * 2); if (markOffset != 0 && LE_SUCCESS(success)) {
LEGlyphID mGlyph = glyphStorage[markGlyph]; LEGlyphID mGlyph = glyphStorage[markGlyph];
TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(mGlyph)]); TTGlyphID newGlyph = SWAPW(int16Table.getObject(markOffset + LE_GET_GLYPH(mGlyph), success)); // whew.
glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph); glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
} }
if (currOffset != 0) { if (currOffset != 0) {
const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + currOffset * 2); LEGlyphID thisGlyph = glyphStorage[currGlyph];
LEGlyphID thisGlyph = glyphStorage[currGlyph]; TTGlyphID newGlyph = SWAPW(int16Table.getObject(currOffset + LE_GET_GLYPH(thisGlyph), success)); // whew.
TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(thisGlyph)]);
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph); }
}
if (flags & cgsSetMark) { if (flags & cgsSetMark) {
markGlyph = currGlyph; markGlyph = currGlyph;
......
...@@ -56,7 +56,7 @@ public: ...@@ -56,7 +56,7 @@ public:
virtual void endStateTable(); virtual void endStateTable();
ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader); ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
virtual ~ContextualGlyphSubstitutionProcessor(); virtual ~ContextualGlyphSubstitutionProcessor();
/** /**
...@@ -78,11 +78,11 @@ private: ...@@ -78,11 +78,11 @@ private:
protected: protected:
ByteOffset substitutionTableOffset; ByteOffset substitutionTableOffset;
const ContextualGlyphSubstitutionStateEntry *entryTable; LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry> entryTable;
LEReferenceToArrayOf<le_int16> int16Table;
le_int32 markGlyph; le_int32 markGlyph;
const ContextualGlyphSubstitutionHeader *contextualGlyphSubstitutionHeader; LEReferenceTo<ContextualGlyphSubstitutionHeader> contextualGlyphSubstitutionHeader;
}; };
......
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*
*/
/*
*
* (C) Copyright IBM Corp. and others 1998-2013 - All Rights Reserved
*
*/
#include "LETypes.h"
#include "MorphTables.h"
#include "StateTables.h"
#include "MorphStateTables.h"
#include "SubtableProcessor2.h"
#include "StateTableProcessor2.h"
#include "ContextualGlyphSubstProc2.h"
#include "LEGlyphStorage.h"
#include "LESwaps.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor2)
ContextualGlyphSubstitutionProcessor2::ContextualGlyphSubstitutionProcessor2(
const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success)
: StateTableProcessor2(morphSubtableHeader, success), contextualGlyphHeader(morphSubtableHeader, success)
{
if(LE_FAILURE(success)) return;
le_uint32 perGlyphTableOffset = SWAPL(contextualGlyphHeader->perGlyphTableOffset);
perGlyphTable = LEReferenceToArrayOf<le_uint32> (stHeader, success, perGlyphTableOffset, LE_UNBOUNDED_ARRAY);
entryTable = LEReferenceToArrayOf<ContextualGlyphStateEntry2>(stHeader, success, entryTableOffset, LE_UNBOUNDED_ARRAY);
}
ContextualGlyphSubstitutionProcessor2::~ContextualGlyphSubstitutionProcessor2()
{
}
void ContextualGlyphSubstitutionProcessor2::beginStateTable()
{
markGlyph = 0;
}
le_uint16 ContextualGlyphSubstitutionProcessor2::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph,
EntryTableIndex2 index, LEErrorCode &success)
{
if(LE_FAILURE(success)) return 0;
const ContextualGlyphStateEntry2 *entry = entryTable.getAlias(index, success);
if(LE_FAILURE(success)) return 0;
le_uint16 newState = SWAPW(entry->newStateIndex);
le_uint16 flags = SWAPW(entry->flags);
le_int16 markIndex = SWAPW(entry->markIndex);
le_int16 currIndex = SWAPW(entry->currIndex);
if (markIndex != -1) {
le_uint32 offset = SWAPL(perGlyphTable(markIndex, success));
LEGlyphID mGlyph = glyphStorage[markGlyph];
TTGlyphID newGlyph = lookup(offset, mGlyph, success);
glyphStorage[markGlyph] = LE_SET_GLYPH(mGlyph, newGlyph);
}
if (currIndex != -1) {
le_uint32 offset = SWAPL(perGlyphTable(currIndex, success));
LEGlyphID thisGlyph = glyphStorage[currGlyph];
TTGlyphID newGlyph = lookup(offset, thisGlyph, success);
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
}
if (flags & cgsSetMark) {
markGlyph = currGlyph;
}
if (!(flags & cgsDontAdvance)) {
currGlyph += dir;
}
return newState;
}
TTGlyphID ContextualGlyphSubstitutionProcessor2::lookup(le_uint32 offset, LEGlyphID gid, LEErrorCode &success)
{
TTGlyphID newGlyph = 0xFFFF;
if(LE_FAILURE(success)) return newGlyph;
LEReferenceTo<LookupTable> lookupTable(perGlyphTable, success, offset);
if(LE_FAILURE(success)) return newGlyph;
le_int16 format = SWAPW(lookupTable->format);
switch (format) {
case ltfSimpleArray: {
#ifdef TEST_FORMAT
// Disabled pending for design review
LEReferenceTo<SimpleArrayLookupTable> lookupTable0(lookupTable, success);
LEReferenceToArrayOf<LookupValue> valueArray(lookupTable0, success, &lookupTable0->valueArray[0], LE_UNBOUNDED_ARRAY);
if(LE_FAILURE(success)) return newGlyph;
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
newGlyph = SWAPW(lookupTable0->valueArray(glyphCode, success));
#endif
break;
}
case ltfSegmentSingle: {
#ifdef TEST_FORMAT
// Disabled pending for design review
LEReferenceTo<SegmentSingleLookupTable> lookupTable2 = (SegmentSingleLookupTable *) lookupTable;
const LookupSegment *segment = lookupTable2->lookupSegment(lookupTable2->segments, gid);
if (segment != NULL) {
newGlyph = SWAPW(segment->value);
}
#endif
break;
}
case ltfSegmentArray: {
//printf("Context Lookup Table Format4: specific interpretation needed!\n");
break;
}
case ltfSingleTable:
{
#ifdef TEST_FORMAT
// Disabled pending for design review
LEReferenceTo<SingleTableLookupTable> lookupTable6 = (SingleTableLookupTable *) lookupTable;
const LEReferenceTo<LookupSingle> segment = lookupTable6->lookupSingle(lookupTable6->entries, gid);
if (segment != NULL) {
newGlyph = SWAPW(segment->value);
}
#endif
break;
}
case ltfTrimmedArray: {
LEReferenceTo<TrimmedArrayLookupTable> lookupTable8(lookupTable, success);
if (LE_FAILURE(success)) return newGlyph;
TTGlyphID firstGlyph = SWAPW(lookupTable8->firstGlyph);
TTGlyphID glyphCount = SWAPW(lookupTable8->glyphCount);
TTGlyphID lastGlyph = firstGlyph + glyphCount;
TTGlyphID glyphCode = (TTGlyphID) LE_GET_GLYPH(gid);
if ((glyphCode >= firstGlyph) && (glyphCode < lastGlyph)) {
LEReferenceToArrayOf<LookupValue> valueArray(lookupTable8, success, &lookupTable8->valueArray[0], glyphCount);
newGlyph = SWAPW(valueArray(glyphCode - firstGlyph, success));
}
}
default:
break;
}
return newGlyph;
}
void ContextualGlyphSubstitutionProcessor2::endStateTable()
{
}
U_NAMESPACE_END
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* /*
* *
* (C) Copyright IBM Corp. 1998-2004 - All Rights Reserved * (C) Copyright IBM Corp. 1998-2013 - All Rights Reserved
* *
*/ */
...@@ -49,6 +49,11 @@ struct ContextualGlyphSubstitutionHeader : MorphStateTableHeader ...@@ -49,6 +49,11 @@ struct ContextualGlyphSubstitutionHeader : MorphStateTableHeader
ByteOffset substitutionTableOffset; ByteOffset substitutionTableOffset;
}; };
struct ContextualGlyphHeader2 : MorphStateTableHeader2
{
le_uint32 perGlyphTableOffset; // no more substitution tables
};
enum ContextualGlyphSubstitutionFlags enum ContextualGlyphSubstitutionFlags
{ {
cgsSetMark = 0x8000, cgsSetMark = 0x8000,
...@@ -62,5 +67,11 @@ struct ContextualGlyphSubstitutionStateEntry : StateEntry ...@@ -62,5 +67,11 @@ struct ContextualGlyphSubstitutionStateEntry : StateEntry
WordOffset currOffset; WordOffset currOffset;
}; };
struct ContextualGlyphStateEntry2 : StateEntry2
{
le_uint16 markIndex;
le_uint16 currIndex;
};
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
...@@ -57,6 +57,7 @@ private: ...@@ -57,6 +57,7 @@ private:
static const le_uint16 fieldSignBits[]; static const le_uint16 fieldSignBits[];
static const le_uint16 fieldBits[]; static const le_uint16 fieldBits[];
}; };
LE_VAR_ARRAY(DeviceTable, deltaValues)
U_NAMESPACE_END U_NAMESPACE_END
#endif #endif
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册