mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-04 20:18:49 +00:00
Merge
This commit is contained in:
commit
be8d5c723d
@ -106,7 +106,21 @@ FILES_cpp_shared = \
|
||||
OpenTypeLayoutEngine.cpp \
|
||||
ThaiLayoutEngine.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)
|
||||
|
||||
@ -170,7 +170,7 @@ public class LWWindowPeer
|
||||
setTitle(((Dialog) getTarget()).getTitle());
|
||||
}
|
||||
|
||||
setAlwaysOnTop(getTarget().isAlwaysOnTop());
|
||||
updateAlwaysOnTopState();
|
||||
updateMinimumSize();
|
||||
|
||||
final Shape shape = getTarget().getShape();
|
||||
@ -357,8 +357,8 @@ public class LWWindowPeer
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlwaysOnTop(boolean value) {
|
||||
platformWindow.setAlwaysOnTop(value);
|
||||
public void updateAlwaysOnTopState() {
|
||||
platformWindow.setAlwaysOnTop(getTarget().isAlwaysOnTop());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -180,7 +180,7 @@ class CFileDialog implements FileDialogPeer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlwaysOnTop(boolean alwaysOnTop) {
|
||||
public void updateAlwaysOnTopState() {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -87,7 +87,7 @@ public class CPrinterDialogPeer extends LWWindowPeer {
|
||||
}
|
||||
|
||||
// 1.6 peer method
|
||||
public void setAlwaysOnTop(boolean value) {
|
||||
public void updateAlwaysOnTopState() {
|
||||
// no-op, since we just show the native print dialog
|
||||
}
|
||||
|
||||
|
||||
@ -243,12 +243,17 @@ public class JPEGImageReader extends ImageReader {
|
||||
* sending warnings to listeners.
|
||||
*/
|
||||
protected void warningOccurred(int code) {
|
||||
if ((code < 0) || (code > MAX_WARNING)){
|
||||
throw new InternalError("Invalid warning index");
|
||||
cbLock.lock();
|
||||
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 {
|
||||
* library warnings from being printed to stderr.
|
||||
*/
|
||||
protected void warningWithMessage(String msg) {
|
||||
processWarningOccurred(msg);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processWarningOccurred(msg);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void setInput(Object input,
|
||||
@ -274,18 +284,55 @@ public class JPEGImageReader extends ImageReader {
|
||||
{
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
super.setInput(input, seekForwardOnly, ignoreMetadata);
|
||||
this.ignoreMetadata = ignoreMetadata;
|
||||
resetInternalState();
|
||||
iis = (ImageInputStream) input; // Always works
|
||||
setSource(structPointer, iis);
|
||||
setSource(structPointer);
|
||||
} finally {
|
||||
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 {
|
||||
if (debug) {
|
||||
@ -337,6 +384,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
public int getNumImages(boolean allowSearch) throws IOException {
|
||||
setThreadLock();
|
||||
try { // locked thread
|
||||
cbLock.check();
|
||||
|
||||
return getNumImagesOnThread(allowSearch);
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
@ -536,8 +585,13 @@ public class JPEGImageReader extends ImageReader {
|
||||
if (debug) {
|
||||
System.out.println("pushing back " + num + " bytes");
|
||||
}
|
||||
iis.seek(iis.getStreamPosition()-num);
|
||||
// The buffer is clear after this, so no need to set haveSeeked.
|
||||
cbLock.lock();
|
||||
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 {
|
||||
* Ignore this profile.
|
||||
*/
|
||||
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 {
|
||||
setThreadLock();
|
||||
try {
|
||||
if (currentImage != imageIndex) {
|
||||
cbLock.check();
|
||||
readHeader(imageIndex, true);
|
||||
}
|
||||
return width;
|
||||
@ -665,6 +725,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
setThreadLock();
|
||||
try {
|
||||
if (currentImage != imageIndex) {
|
||||
cbLock.check();
|
||||
readHeader(imageIndex, true);
|
||||
}
|
||||
return height;
|
||||
@ -693,6 +754,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
setThreadLock();
|
||||
try {
|
||||
if (currentImage != imageIndex) {
|
||||
cbLock.check();
|
||||
|
||||
readHeader(imageIndex, true);
|
||||
}
|
||||
|
||||
@ -716,6 +779,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
private Iterator getImageTypesOnThread(int imageIndex)
|
||||
throws IOException {
|
||||
if (currentImage != imageIndex) {
|
||||
cbLock.check();
|
||||
readHeader(imageIndex, true);
|
||||
}
|
||||
|
||||
@ -931,6 +995,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
setThreadLock();
|
||||
try {
|
||||
if (!tablesOnlyChecked) {
|
||||
cbLock.check();
|
||||
checkTablesOnly();
|
||||
}
|
||||
return streamMetadata;
|
||||
@ -951,6 +1016,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
return imageMetadata;
|
||||
}
|
||||
|
||||
cbLock.check();
|
||||
|
||||
gotoImage(imageIndex);
|
||||
|
||||
imageMetadata = new JPEGMetadata(false, false, iis, this);
|
||||
@ -967,6 +1034,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
try {
|
||||
readInternal(imageIndex, param, false);
|
||||
} catch (RuntimeException e) {
|
||||
@ -1196,58 +1264,63 @@ public class JPEGImageReader extends ImageReader {
|
||||
}
|
||||
target.setRect(destROI.x, destROI.y + y, raster);
|
||||
|
||||
processImageUpdate(image,
|
||||
destROI.x, destROI.y+y,
|
||||
raster.getWidth(), 1,
|
||||
1, 1,
|
||||
destinationBands);
|
||||
if ((y > 0) && (y%progInterval == 0)) {
|
||||
int height = target.getHeight()-1;
|
||||
float percentOfPass = ((float)y)/height;
|
||||
if (progressive) {
|
||||
if (knownPassCount != UNKNOWN) {
|
||||
processImageProgress((pass + percentOfPass)*100.0F
|
||||
/ knownPassCount);
|
||||
} else if (maxProgressivePass != Integer.MAX_VALUE) {
|
||||
// Use the range of allowed progressive passes
|
||||
processImageProgress((pass + percentOfPass)*100.0F
|
||||
/ (maxProgressivePass - minProgressivePass + 1));
|
||||
} else {
|
||||
// Assume there are a minimum of MIN_ESTIMATED_PASSES
|
||||
// and that there is always one more pass
|
||||
// Compute the percentage as the percentage at the end
|
||||
// of the previous pass, plus the percentage of this
|
||||
// pass scaled to be the percentage of the total remaining,
|
||||
// assuming a minimum of MIN_ESTIMATED_PASSES passes and
|
||||
// that there is always one more pass. This is monotonic
|
||||
// and asymptotic to 1.0, which is what we need.
|
||||
int remainingPasses = // including this one
|
||||
Math.max(2, MIN_ESTIMATED_PASSES-pass);
|
||||
int totalPasses = pass + remainingPasses-1;
|
||||
progInterval = Math.max(height/20*totalPasses,
|
||||
totalPasses);
|
||||
if (y%progInterval == 0) {
|
||||
percentToDate = previousPassPercentage +
|
||||
(1.0F - previousPassPercentage)
|
||||
* (percentOfPass)/remainingPasses;
|
||||
if (debug) {
|
||||
System.out.print("pass= " + pass);
|
||||
System.out.print(", y= " + y);
|
||||
System.out.print(", progInt= " + progInterval);
|
||||
System.out.print(", % of pass: " + percentOfPass);
|
||||
System.out.print(", rem. passes: "
|
||||
+ remainingPasses);
|
||||
System.out.print(", prev%: "
|
||||
+ previousPassPercentage);
|
||||
System.out.print(", %ToDate: " + percentToDate);
|
||||
System.out.print(" ");
|
||||
cbLock.lock();
|
||||
try {
|
||||
processImageUpdate(image,
|
||||
destROI.x, destROI.y+y,
|
||||
raster.getWidth(), 1,
|
||||
1, 1,
|
||||
destinationBands);
|
||||
if ((y > 0) && (y%progInterval == 0)) {
|
||||
int height = target.getHeight()-1;
|
||||
float percentOfPass = ((float)y)/height;
|
||||
if (progressive) {
|
||||
if (knownPassCount != UNKNOWN) {
|
||||
processImageProgress((pass + percentOfPass)*100.0F
|
||||
/ knownPassCount);
|
||||
} else if (maxProgressivePass != Integer.MAX_VALUE) {
|
||||
// Use the range of allowed progressive passes
|
||||
processImageProgress((pass + percentOfPass)*100.0F
|
||||
/ (maxProgressivePass - minProgressivePass + 1));
|
||||
} else {
|
||||
// Assume there are a minimum of MIN_ESTIMATED_PASSES
|
||||
// and that there is always one more pass
|
||||
// Compute the percentage as the percentage at the end
|
||||
// of the previous pass, plus the percentage of this
|
||||
// pass scaled to be the percentage of the total remaining,
|
||||
// assuming a minimum of MIN_ESTIMATED_PASSES passes and
|
||||
// that there is always one more pass. This is monotonic
|
||||
// and asymptotic to 1.0, which is what we need.
|
||||
int remainingPasses = // including this one
|
||||
Math.max(2, MIN_ESTIMATED_PASSES-pass);
|
||||
int totalPasses = pass + remainingPasses-1;
|
||||
progInterval = Math.max(height/20*totalPasses,
|
||||
totalPasses);
|
||||
if (y%progInterval == 0) {
|
||||
percentToDate = previousPassPercentage +
|
||||
(1.0F - previousPassPercentage)
|
||||
* (percentOfPass)/remainingPasses;
|
||||
if (debug) {
|
||||
System.out.print("pass= " + pass);
|
||||
System.out.print(", y= " + y);
|
||||
System.out.print(", progInt= " + progInterval);
|
||||
System.out.print(", % of pass: " + percentOfPass);
|
||||
System.out.print(", rem. passes: "
|
||||
+ remainingPasses);
|
||||
System.out.print(", prev%: "
|
||||
+ 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 {
|
||||
}
|
||||
|
||||
private void passStarted (int pass) {
|
||||
this.pass = pass;
|
||||
previousPassPercentage = percentToDate;
|
||||
processPassStarted(image,
|
||||
pass,
|
||||
minProgressivePass,
|
||||
maxProgressivePass,
|
||||
0, 0,
|
||||
1,1,
|
||||
destinationBands);
|
||||
cbLock.lock();
|
||||
try {
|
||||
this.pass = pass;
|
||||
previousPassPercentage = percentToDate;
|
||||
processPassStarted(image,
|
||||
pass,
|
||||
minProgressivePass,
|
||||
maxProgressivePass,
|
||||
0, 0,
|
||||
1,1,
|
||||
destinationBands);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private void passComplete () {
|
||||
processPassComplete(image);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processPassComplete(image);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void thumbnailStarted(int thumbnailIndex) {
|
||||
processThumbnailStarted(currentImage, thumbnailIndex);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processThumbnailStarted(currentImage, thumbnailIndex);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Provide access to protected superclass method
|
||||
void thumbnailProgress(float percentageDone) {
|
||||
processThumbnailProgress(percentageDone);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processThumbnailProgress(percentageDone);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Provide access to protected superclass method
|
||||
void thumbnailComplete() {
|
||||
processThumbnailComplete();
|
||||
cbLock.lock();
|
||||
try {
|
||||
processThumbnailComplete();
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1310,6 +1408,11 @@ public class JPEGImageReader extends ImageReader {
|
||||
public void abort() {
|
||||
setThreadLock();
|
||||
try {
|
||||
/**
|
||||
* NB: we do not check the call back lock here,
|
||||
* we allow to abort the reader any time.
|
||||
*/
|
||||
|
||||
super.abort();
|
||||
abortRead(structPointer);
|
||||
} finally {
|
||||
@ -1332,6 +1435,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
setThreadLock();
|
||||
Raster retval = null;
|
||||
try {
|
||||
cbLock.check();
|
||||
/*
|
||||
* This could be further optimized by not resetting the dest.
|
||||
* offset and creating a translated raster in readInternal()
|
||||
@ -1371,6 +1475,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
public int getNumThumbnails(int imageIndex) throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
getImageMetadata(imageIndex); // checks iis state for us
|
||||
// Now check the jfif segments
|
||||
JFIFMarkerSegment jfif =
|
||||
@ -1391,6 +1497,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if ((thumbnailIndex < 0)
|
||||
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) {
|
||||
throw new IndexOutOfBoundsException("No such thumbnail");
|
||||
@ -1409,6 +1517,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if ((thumbnailIndex < 0)
|
||||
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) {
|
||||
throw new IndexOutOfBoundsException("No such thumbnail");
|
||||
@ -1428,6 +1538,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if ((thumbnailIndex < 0)
|
||||
|| (thumbnailIndex >= getNumThumbnails(imageIndex))) {
|
||||
throw new IndexOutOfBoundsException("No such thumbnail");
|
||||
@ -1468,6 +1580,7 @@ public class JPEGImageReader extends ImageReader {
|
||||
public void reset() {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
super.reset();
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
@ -1479,6 +1592,8 @@ public class JPEGImageReader extends ImageReader {
|
||||
public void dispose() {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if (structPointer != 0) {
|
||||
disposerRecord.dispose();
|
||||
structPointer = 0;
|
||||
@ -1540,6 +1655,36 @@ public class JPEGImageReader extends ImageReader {
|
||||
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 {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
initWriterIDs(ImageOutputStream.class,
|
||||
JPEGQTable.class,
|
||||
initWriterIDs(JPEGQTable.class,
|
||||
JPEGHuffmanTable.class);
|
||||
}
|
||||
|
||||
@ -200,11 +199,13 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
public void setOutput(Object output) {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
super.setOutput(output); // validates output
|
||||
resetInternalState();
|
||||
ios = (ImageOutputStream) output; // so this will always work
|
||||
// Set the native destination
|
||||
setDest(structPointer, ios);
|
||||
setDest(structPointer);
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
}
|
||||
@ -359,6 +360,8 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
ImageWriteParam param) throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
writeOnThread(streamMetadata, image, param);
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
@ -1082,13 +1085,18 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
haveMetadata,
|
||||
restartInterval);
|
||||
|
||||
if (aborted) {
|
||||
processWriteAborted();
|
||||
} else {
|
||||
processImageComplete();
|
||||
}
|
||||
cbLock.lock();
|
||||
try {
|
||||
if (aborted) {
|
||||
processWriteAborted();
|
||||
} else {
|
||||
processImageComplete();
|
||||
}
|
||||
|
||||
ios.flush();
|
||||
ios.flush();
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
currentImage++; // After a successful write
|
||||
}
|
||||
|
||||
@ -1096,6 +1104,8 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
prepareWriteSequenceOnThread(streamMetadata);
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
@ -1175,6 +1185,8 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if (sequencePrepared == false) {
|
||||
throw new IllegalStateException("sequencePrepared not called!");
|
||||
}
|
||||
@ -1188,6 +1200,8 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
public void endWriteSequence() throws IOException {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if (sequencePrepared == false) {
|
||||
throw new IllegalStateException("sequencePrepared not called!");
|
||||
}
|
||||
@ -1200,6 +1214,10 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
public synchronized void abort() {
|
||||
setThreadLock();
|
||||
try {
|
||||
/**
|
||||
* NB: we do not check the call back lock here, we allow to abort
|
||||
* the reader any time.
|
||||
*/
|
||||
super.abort();
|
||||
abortWrite(structPointer);
|
||||
} finally {
|
||||
@ -1223,6 +1241,8 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
public void reset() {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
super.reset();
|
||||
} finally {
|
||||
clearThreadLock();
|
||||
@ -1232,6 +1252,8 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
public void dispose() {
|
||||
setThreadLock();
|
||||
try {
|
||||
cbLock.check();
|
||||
|
||||
if (structPointer != 0) {
|
||||
disposerRecord.dispose();
|
||||
structPointer = 0;
|
||||
@ -1251,13 +1273,18 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
* sending warnings to listeners.
|
||||
*/
|
||||
void warningOccurred(int code) {
|
||||
if ((code < 0) || (code > MAX_WARNING)){
|
||||
throw new InternalError("Invalid warning index");
|
||||
cbLock.lock();
|
||||
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 {
|
||||
* library warnings from being printed to stderr.
|
||||
*/
|
||||
void warningWithMessage(String msg) {
|
||||
processWarningOccurred(currentImage, msg);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processWarningOccurred(currentImage, msg);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void thumbnailStarted(int thumbnailIndex) {
|
||||
processThumbnailStarted(currentImage, thumbnailIndex);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processThumbnailStarted(currentImage, thumbnailIndex);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Provide access to protected superclass method
|
||||
void thumbnailProgress(float percentageDone) {
|
||||
processThumbnailProgress(percentageDone);
|
||||
cbLock.lock();
|
||||
try {
|
||||
processThumbnailProgress(percentageDone);
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
// Provide access to protected superclass method
|
||||
void thumbnailComplete() {
|
||||
processThumbnailComplete();
|
||||
cbLock.lock();
|
||||
try {
|
||||
processThumbnailComplete();
|
||||
} finally {
|
||||
cbLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
///////// End of Package-access API
|
||||
@ -1615,16 +1662,14 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
////////////// Native methods and callbacks
|
||||
|
||||
/** Sets up static native structures. */
|
||||
private static native void initWriterIDs(Class iosClass,
|
||||
Class qTableClass,
|
||||
private static native void initWriterIDs(Class qTableClass,
|
||||
Class huffClass);
|
||||
|
||||
/** Sets up per-writer native structure and returns a pointer to it. */
|
||||
private native long initJPEGImageWriter();
|
||||
|
||||
/** Sets up native structures for output stream */
|
||||
private native void setDest(long structPointer,
|
||||
ImageOutputStream ios);
|
||||
private native void setDest(long structPointer);
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if the write was aborted.
|
||||
@ -1749,7 +1794,12 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
}
|
||||
raster.setRect(sourceLine);
|
||||
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 {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 int theLockCount = 0;
|
||||
|
||||
@ -1811,4 +1880,34 @@ public class JPEGImageWriter extends ImageWriter {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,6 +32,7 @@ import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.security.Permission;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
@ -213,7 +214,6 @@ public class MBeanInstantiator {
|
||||
|
||||
Object moi;
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
Constructor<?> cons = findConstructor(theClass, null);
|
||||
@ -224,6 +224,7 @@ public class MBeanInstantiator {
|
||||
// Instantiate the new object
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(theClass);
|
||||
ensureClassAccess(theClass);
|
||||
moi= cons.newInstance();
|
||||
} catch (InvocationTargetException e) {
|
||||
// Wrap the exception.
|
||||
@ -270,7 +271,6 @@ public class MBeanInstantiator {
|
||||
checkMBeanPermission(theClass, null, null, "instantiate");
|
||||
|
||||
// Instantiate the new object
|
||||
|
||||
// ------------------------------
|
||||
// ------------------------------
|
||||
final Class<?>[] tab;
|
||||
@ -300,6 +300,7 @@ public class MBeanInstantiator {
|
||||
}
|
||||
try {
|
||||
ReflectUtil.checkPackageAccess(theClass);
|
||||
ensureClassAccess(theClass);
|
||||
moi = cons.newInstance(params);
|
||||
}
|
||||
catch (NoSuchMethodError error) {
|
||||
@ -741,4 +742,13 @@ public class MBeanInstantiator {
|
||||
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
|
||||
// from simultaneous creation and destruction
|
||||
// reduces possibility of deadlock, compared to
|
||||
// synchronizing to the class instance
|
||||
private Object traRecLock = new Object();
|
||||
private final Object traRecLock = new Object();
|
||||
|
||||
// DEVICE ATTRIBUTES
|
||||
|
||||
@ -474,7 +474,7 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
|
||||
This is necessary for Receivers retrieved via MidiSystem.getReceiver()
|
||||
(which opens the device implicitely).
|
||||
*/
|
||||
protected abstract class AbstractReceiver implements MidiDeviceReceiver {
|
||||
abstract class AbstractReceiver implements MidiDeviceReceiver {
|
||||
private boolean open = true;
|
||||
|
||||
|
||||
@ -483,24 +483,24 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
|
||||
Receiver. Therefore, subclasses should not override this method.
|
||||
Instead, they should implement implSend().
|
||||
*/
|
||||
public synchronized void send(MidiMessage message, long timeStamp) {
|
||||
if (open) {
|
||||
implSend(message, timeStamp);
|
||||
} else {
|
||||
@Override
|
||||
public final synchronized void send(final MidiMessage message,
|
||||
final long timeStamp) {
|
||||
if (!open) {
|
||||
throw new IllegalStateException("Receiver is not open");
|
||||
}
|
||||
implSend(message, timeStamp);
|
||||
}
|
||||
|
||||
|
||||
protected abstract void implSend(MidiMessage message, long timeStamp);
|
||||
|
||||
abstract void implSend(MidiMessage message, long timeStamp);
|
||||
|
||||
/** Close the Receiver.
|
||||
* Here, the call to the magic method closeInternal() takes place.
|
||||
* Therefore, subclasses that override this method must call
|
||||
* 'super.close()'.
|
||||
*/
|
||||
public void close() {
|
||||
@Override
|
||||
public final void close() {
|
||||
open = false;
|
||||
synchronized (AbstractMidiDevice.this.traRecLock) {
|
||||
AbstractMidiDevice.this.getReceiverList().remove(this);
|
||||
@ -508,11 +508,12 @@ abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice
|
||||
AbstractMidiDevice.this.closeInternal(this);
|
||||
}
|
||||
|
||||
public MidiDevice getMidiDevice() {
|
||||
@Override
|
||||
public final MidiDevice getMidiDevice() {
|
||||
return AbstractMidiDevice.this;
|
||||
}
|
||||
|
||||
protected boolean isOpen() {
|
||||
final boolean isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
|
||||
@ -32,7 +32,7 @@ import javax.sound.midi.*;
|
||||
*
|
||||
* @author Florian Bomers
|
||||
*/
|
||||
class FastShortMessage extends ShortMessage {
|
||||
final class FastShortMessage extends ShortMessage {
|
||||
private int packedMsg;
|
||||
|
||||
public FastShortMessage(int packedMsg) throws InvalidMidiDataException {
|
||||
|
||||
@ -32,7 +32,7 @@ import javax.sound.midi.*;
|
||||
*
|
||||
* @author Florian Bomers
|
||||
*/
|
||||
class FastSysexMessage extends SysexMessage {
|
||||
final class FastSysexMessage extends SysexMessage {
|
||||
|
||||
FastSysexMessage(byte[] data) throws InvalidMidiDataException {
|
||||
super(data);
|
||||
|
||||
@ -103,9 +103,9 @@ class MidiOutDevice extends AbstractMidiDevice {
|
||||
|
||||
class MidiOutReceiver extends AbstractReceiver {
|
||||
|
||||
protected void implSend(MidiMessage message, long timeStamp) {
|
||||
int length = message.getLength();
|
||||
int status = message.getStatus();
|
||||
void implSend(final MidiMessage message, final long timeStamp) {
|
||||
final int length = message.getLength();
|
||||
final int status = message.getStatus();
|
||||
if (length <= 3 && status != 0xF0 && status != 0xF7) {
|
||||
int packedMsg;
|
||||
if (message instanceof ShortMessage) {
|
||||
@ -140,11 +140,15 @@ class MidiOutDevice extends AbstractMidiDevice {
|
||||
}
|
||||
nSendShortMessage(id, packedMsg, timeStamp);
|
||||
} else {
|
||||
final byte[] data;
|
||||
if (message instanceof FastSysexMessage) {
|
||||
nSendLongMessage(id, ((FastSysexMessage) message).getReadOnlyMessage(),
|
||||
length, timeStamp);
|
||||
data = ((FastSysexMessage) message).getReadOnlyMessage();
|
||||
} 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
|
||||
|
||||
class SequencerReceiver extends AbstractReceiver {
|
||||
|
||||
protected void implSend(MidiMessage message, long timeStamp) {
|
||||
void implSend(MidiMessage message, long timeStamp) {
|
||||
if (recording) {
|
||||
long tickPos = 0;
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -2234,7 +2234,7 @@ public class Window extends Container implements Accessible {
|
||||
WindowPeer peer = (WindowPeer)this.peer;
|
||||
synchronized(getTreeLock()) {
|
||||
if (peer != null) {
|
||||
peer.setAlwaysOnTop(alwaysOnTop);
|
||||
peer.updateAlwaysOnTopState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -53,15 +53,14 @@ public interface WindowPeer extends ContainerPeer {
|
||||
void toBack();
|
||||
|
||||
/**
|
||||
* 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
|
||||
* Updates the window's always-on-top state.
|
||||
* Sets if the window should always stay
|
||||
* on top of all other windows or not.
|
||||
*
|
||||
* @see Window#getAlwaysOnTop()
|
||||
* @see Window#setAlwaysOnTop(boolean)
|
||||
*/
|
||||
void setAlwaysOnTop(boolean alwaysOnTop);
|
||||
void updateAlwaysOnTopState();
|
||||
|
||||
/**
|
||||
* Updates the window's focusable state.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -29,7 +29,6 @@ import com.sun.beans.finder.BeanInfoFinder;
|
||||
import com.sun.beans.finder.PropertyEditorFinder;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
@ -42,7 +41,7 @@ import java.util.WeakHashMap;
|
||||
*/
|
||||
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,
|
||||
@ -69,6 +68,8 @@ final class ThreadGroupContext {
|
||||
private BeanInfoFinder beanInfoFinder;
|
||||
private PropertyEditorFinder propertyEditorFinder;
|
||||
|
||||
private ThreadGroupContext() {
|
||||
}
|
||||
|
||||
boolean isDesignTime() {
|
||||
return this.isDesignTime;
|
||||
|
||||
181
jdk/src/share/classes/java/beans/WeakIdentityMap.java
Normal file
181
jdk/src/share/classes/java/beans/WeakIdentityMap.java
Normal file
@ -0,0 +1,181 @@
|
||||
/*
|
||||
* 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;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import static java.io.ObjectStreamClass.processQueue;
|
||||
import sun.reflect.misc.ReflectUtil;
|
||||
|
||||
/**
|
||||
* An ObjectInputStream deserializes primitive data and objects previously
|
||||
@ -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
|
||||
* passHandle to proxy class descriptor's assigned handle. If proxy class
|
||||
@ -1548,6 +1555,15 @@ public class ObjectInputStream
|
||||
try {
|
||||
if ((cl = resolveProxyClass(ifaces)) == null) {
|
||||
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) {
|
||||
resolveEx = ex;
|
||||
@ -1589,9 +1605,12 @@ public class ObjectInputStream
|
||||
Class<?> cl = null;
|
||||
ClassNotFoundException resolveEx = null;
|
||||
bin.setBlockDataMode(true);
|
||||
final boolean checksRequired = isCustomSubclass();
|
||||
try {
|
||||
if ((cl = resolveClass(readDesc)) == null) {
|
||||
resolveEx = new ClassNotFoundException("null class");
|
||||
} else if (checksRequired) {
|
||||
ReflectUtil.checkPackageAccess(cl);
|
||||
}
|
||||
} catch (ClassNotFoundException ex) {
|
||||
resolveEx = ex;
|
||||
|
||||
@ -30,6 +30,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -1024,13 +1025,24 @@ public final class ProcessBuilder
|
||||
redirects,
|
||||
redirectErrorStream);
|
||||
} 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
|
||||
// message than the low-level C code which found the problem.
|
||||
throw new IOException(
|
||||
"Cannot run program \"" + prog + "\""
|
||||
+ (dir == null ? "" : " (in directory \"" + dir + "\")")
|
||||
+ ": " + e.getMessage(),
|
||||
e);
|
||||
+ exceptionInfo,
|
||||
cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,6 +1237,30 @@ return mh1;
|
||||
checkMethod(refKind, refc, method);
|
||||
if (method.isMethodHandleInvoke())
|
||||
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);
|
||||
mh = maybeBindCaller(method, mh, callerClass);
|
||||
mh = mh.setVarargs(method);
|
||||
|
||||
@ -38,9 +38,9 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
|
||||
*/
|
||||
static native void invokeFinalizeMethod(Object o) throws Throwable;
|
||||
|
||||
static private ReferenceQueue queue = new ReferenceQueue();
|
||||
static private Finalizer unfinalized = null;
|
||||
static private Object lock = new Object();
|
||||
private static ReferenceQueue queue = new ReferenceQueue();
|
||||
private static Finalizer unfinalized = null;
|
||||
private static final Object lock = new Object();
|
||||
|
||||
private Finalizer
|
||||
next = null,
|
||||
@ -142,7 +142,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
|
||||
/* Called by Runtime.runFinalization() */
|
||||
static void runFinalization() {
|
||||
forkSecondaryFinalizer(new Runnable() {
|
||||
private volatile boolean running;
|
||||
public void run() {
|
||||
if (running)
|
||||
return;
|
||||
running = true;
|
||||
for (;;) {
|
||||
Finalizer f = (Finalizer)queue.poll();
|
||||
if (f == null) break;
|
||||
@ -155,7 +159,11 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
|
||||
/* Invoked by java.lang.Shutdown */
|
||||
static void runAllFinalizers() {
|
||||
forkSecondaryFinalizer(new Runnable() {
|
||||
private volatile boolean running;
|
||||
public void run() {
|
||||
if (running)
|
||||
return;
|
||||
running = true;
|
||||
for (;;) {
|
||||
Finalizer f;
|
||||
synchronized (lock) {
|
||||
@ -168,10 +176,14 @@ final class Finalizer extends FinalReference { /* Package-private; must be in
|
||||
}
|
||||
|
||||
private static class FinalizerThread extends Thread {
|
||||
private volatile boolean running;
|
||||
FinalizerThread(ThreadGroup g) {
|
||||
super(g, "Finalizer");
|
||||
}
|
||||
public void run() {
|
||||
if (running)
|
||||
return;
|
||||
running = true;
|
||||
for (;;) {
|
||||
try {
|
||||
Finalizer f = (Finalizer)queue.remove();
|
||||
|
||||
@ -122,7 +122,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl
|
||||
* not connected already.
|
||||
*/
|
||||
protected void disconnect() {
|
||||
disconnect0(connectedAddress.family);
|
||||
disconnect0(connectedAddress.holder().getFamily());
|
||||
connected = false;
|
||||
connectedAddress = null;
|
||||
connectedPort = -1;
|
||||
|
||||
@ -100,27 +100,28 @@ class Inet4Address extends InetAddress {
|
||||
|
||||
Inet4Address() {
|
||||
super();
|
||||
hostName = null;
|
||||
address = 0;
|
||||
family = IPv4;
|
||||
holder().hostName = null;
|
||||
holder().address = 0;
|
||||
holder().family = IPv4;
|
||||
}
|
||||
|
||||
Inet4Address(String hostName, byte addr[]) {
|
||||
this.hostName = hostName;
|
||||
this.family = IPv4;
|
||||
holder().hostName = hostName;
|
||||
holder().family = IPv4;
|
||||
if (addr != null) {
|
||||
if (addr.length == INADDRSZ) {
|
||||
address = addr[3] & 0xFF;
|
||||
int address = addr[3] & 0xFF;
|
||||
address |= ((addr[2] << 8) & 0xFF00);
|
||||
address |= ((addr[1] << 16) & 0xFF0000);
|
||||
address |= ((addr[0] << 24) & 0xFF000000);
|
||||
holder().address = address;
|
||||
}
|
||||
}
|
||||
}
|
||||
Inet4Address(String hostName, int address) {
|
||||
this.hostName = hostName;
|
||||
this.family = IPv4;
|
||||
this.address = address;
|
||||
holder().hostName = hostName;
|
||||
holder().family = IPv4;
|
||||
holder().address = address;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,8 +135,8 @@ class Inet4Address extends InetAddress {
|
||||
private Object writeReplace() throws ObjectStreamException {
|
||||
// will replace the to be serialized 'this' object
|
||||
InetAddress inet = new InetAddress();
|
||||
inet.hostName = this.hostName;
|
||||
inet.address = this.address;
|
||||
inet.holder().hostName = holder().getHostName();
|
||||
inet.holder().address = holder().getAddress();
|
||||
|
||||
/**
|
||||
* Prior to 1.4 an InetAddress was created with a family
|
||||
@ -143,7 +144,7 @@ class Inet4Address extends InetAddress {
|
||||
* For compatibility reasons we must therefore write the
|
||||
* the InetAddress with this family.
|
||||
*/
|
||||
inet.family = 2;
|
||||
inet.holder().family = 2;
|
||||
|
||||
return inet;
|
||||
}
|
||||
@ -157,7 +158,7 @@ class Inet4Address extends InetAddress {
|
||||
* @since JDK1.1
|
||||
*/
|
||||
public boolean isMulticastAddress() {
|
||||
return ((address & 0xf0000000) == 0xe0000000);
|
||||
return ((holder().getAddress() & 0xf0000000) == 0xe0000000);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,7 +168,7 @@ class Inet4Address extends InetAddress {
|
||||
* @since 1.4
|
||||
*/
|
||||
public boolean isAnyLocalAddress() {
|
||||
return address == 0;
|
||||
return holder().getAddress() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -195,6 +196,7 @@ class Inet4Address extends InetAddress {
|
||||
// defined in "Documenting Special Use IPv4 Address Blocks
|
||||
// that have been Registered with IANA" by Bill Manning
|
||||
// draft-manning-dsua-06.txt
|
||||
int address = holder().getAddress();
|
||||
return (((address >>> 24) & 0xFF) == 169)
|
||||
&& (((address >>> 16) & 0xFF) == 254);
|
||||
}
|
||||
@ -211,6 +213,7 @@ class Inet4Address extends InetAddress {
|
||||
// 10/8 prefix
|
||||
// 172.16/12 prefix
|
||||
// 192.168/16 prefix
|
||||
int address = holder().getAddress();
|
||||
return (((address >>> 24) & 0xFF) == 10)
|
||||
|| ((((address >>> 24) & 0xFF) == 172)
|
||||
&& (((address >>> 16) & 0xF0) == 16))
|
||||
@ -257,6 +260,7 @@ class Inet4Address extends InetAddress {
|
||||
*/
|
||||
public boolean isMCLinkLocal() {
|
||||
// 224.0.0/24 prefix and ttl == 1
|
||||
int address = holder().getAddress();
|
||||
return (((address >>> 24) & 0xFF) == 224)
|
||||
&& (((address >>> 16) & 0xFF) == 0)
|
||||
&& (((address >>> 8) & 0xFF) == 0);
|
||||
@ -272,6 +276,7 @@ class Inet4Address extends InetAddress {
|
||||
*/
|
||||
public boolean isMCSiteLocal() {
|
||||
// 239.255/16 prefix or ttl < 32
|
||||
int address = holder().getAddress();
|
||||
return (((address >>> 24) & 0xFF) == 239)
|
||||
&& (((address >>> 16) & 0xFF) == 255);
|
||||
}
|
||||
@ -287,6 +292,7 @@ class Inet4Address extends InetAddress {
|
||||
*/
|
||||
public boolean isMCOrgLocal() {
|
||||
// 239.192 - 239.195
|
||||
int address = holder().getAddress();
|
||||
return (((address >>> 24) & 0xFF) == 239)
|
||||
&& (((address >>> 16) & 0xFF) >= 192)
|
||||
&& (((address >>> 16) & 0xFF) <= 195);
|
||||
@ -300,6 +306,7 @@ class Inet4Address extends InetAddress {
|
||||
* @return the raw IP address of this object.
|
||||
*/
|
||||
public byte[] getAddress() {
|
||||
int address = holder().getAddress();
|
||||
byte[] addr = new byte[INADDRSZ];
|
||||
|
||||
addr[0] = (byte) ((address >>> 24) & 0xFF);
|
||||
@ -325,7 +332,7 @@ class Inet4Address extends InetAddress {
|
||||
* @return a hash code value for this IP address.
|
||||
*/
|
||||
public int hashCode() {
|
||||
return address;
|
||||
return holder().getAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -346,7 +353,7 @@ class Inet4Address extends InetAddress {
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
return (obj != null) && (obj instanceof Inet4Address) &&
|
||||
(((InetAddress)obj).address == address);
|
||||
(((InetAddress)obj).holder().getAddress() == holder().getAddress());
|
||||
}
|
||||
|
||||
// Utilities
|
||||
|
||||
@ -40,7 +40,7 @@ class Inet4AddressImpl implements InetAddressImpl {
|
||||
public synchronized InetAddress anyLocalAddress() {
|
||||
if (anyLocalAddress == null) {
|
||||
anyLocalAddress = new Inet4Address(); // {0x00,0x00,0x00,0x00}
|
||||
anyLocalAddress.hostName = "0.0.0.0";
|
||||
anyLocalAddress.holder().hostName = "0.0.0.0";
|
||||
}
|
||||
return anyLocalAddress;
|
||||
}
|
||||
|
||||
@ -210,18 +210,18 @@ class Inet6Address extends InetAddress {
|
||||
|
||||
Inet6Address() {
|
||||
super();
|
||||
hostName = null;
|
||||
holder().hostName = null;
|
||||
ipaddress = new byte[INADDRSZ];
|
||||
family = IPv6;
|
||||
holder().family = IPv6;
|
||||
}
|
||||
|
||||
/* checking of value for scope_id should be done by caller
|
||||
* scope_id must be >= 0, or -1 to indicate not being set
|
||||
*/
|
||||
Inet6Address(String hostName, byte addr[], int scope_id) {
|
||||
this.hostName = hostName;
|
||||
holder().hostName = hostName;
|
||||
if (addr.length == INADDRSZ) { // normal IPv6 address
|
||||
family = IPv6;
|
||||
holder().family = IPv6;
|
||||
ipaddress = addr.clone();
|
||||
}
|
||||
if (scope_id >= 0) {
|
||||
@ -335,9 +335,9 @@ class Inet6Address extends InetAddress {
|
||||
private void initif(String hostName, byte addr[],NetworkInterface nif)
|
||||
throws UnknownHostException
|
||||
{
|
||||
this.hostName = hostName;
|
||||
holder().hostName = hostName;
|
||||
if (addr.length == INADDRSZ) { // normal IPv6 address
|
||||
family = IPv6;
|
||||
holder().family = IPv6;
|
||||
ipaddress = addr.clone();
|
||||
}
|
||||
if (nif != null) {
|
||||
@ -420,6 +420,11 @@ class Inet6Address extends InetAddress {
|
||||
*/
|
||||
private void readObject(ObjectInputStream s)
|
||||
throws IOException, ClassNotFoundException {
|
||||
|
||||
if (getClass().getClassLoader() != null) {
|
||||
throw new SecurityException ("invalid address type");
|
||||
}
|
||||
|
||||
s.defaultReadObject();
|
||||
|
||||
if (ifname != null && !ifname.equals("")) {
|
||||
@ -447,7 +452,7 @@ class Inet6Address extends InetAddress {
|
||||
ipaddress.length);
|
||||
}
|
||||
|
||||
if (family != IPv6) {
|
||||
if (holder().getFamily() != IPv6) {
|
||||
throw new InvalidObjectException("invalid address family type");
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ class Inet6AddressImpl implements InetAddressImpl {
|
||||
if (anyLocalAddress == null) {
|
||||
if (InetAddress.preferIPv6Address) {
|
||||
anyLocalAddress = new Inet6Address();
|
||||
anyLocalAddress.hostName = "::";
|
||||
anyLocalAddress.holder().hostName = "::";
|
||||
} else {
|
||||
anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
|
||||
}
|
||||
|
||||
@ -35,8 +35,12 @@ import java.util.ArrayList;
|
||||
import java.util.ServiceLoader;
|
||||
import java.security.AccessController;
|
||||
import java.io.ObjectStreamException;
|
||||
import java.io.ObjectStreamField;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectInputStream.GetField;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.ObjectOutputStream.PutField;
|
||||
import sun.security.action.*;
|
||||
import sun.net.InetAddressCachePolicy;
|
||||
import sun.net.util.IPAddressUtil;
|
||||
@ -199,25 +203,48 @@ class InetAddress implements java.io.Serializable {
|
||||
/* Specify address family preference */
|
||||
static transient boolean preferIPv6Address = false;
|
||||
|
||||
/**
|
||||
* @serial
|
||||
*/
|
||||
String hostName;
|
||||
static class InetAddressHolder {
|
||||
|
||||
/**
|
||||
* Holds a 32-bit IPv4 address.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
int address;
|
||||
InetAddressHolder() {}
|
||||
|
||||
/**
|
||||
* Specifies the address family type, for instance, '1' for IPv4
|
||||
* addresses, and '2' for IPv6 addresses.
|
||||
*
|
||||
* @serial
|
||||
*/
|
||||
int family;
|
||||
InetAddressHolder(String hostName, int address, int family) {
|
||||
this.hostName = hostName;
|
||||
this.address = address;
|
||||
this.family = 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 */
|
||||
private static List<NameService> nameServices = null;
|
||||
@ -251,6 +278,7 @@ class InetAddress implements java.io.Serializable {
|
||||
* put in the address cache, since it is not created by name.
|
||||
*/
|
||||
InetAddress() {
|
||||
holder = new InetAddressHolder();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -263,7 +291,7 @@ class InetAddress implements java.io.Serializable {
|
||||
*/
|
||||
private Object readResolve() throws ObjectStreamException {
|
||||
// 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 {
|
||||
* @see SecurityManager#checkConnect
|
||||
*/
|
||||
String getHostName(boolean check) {
|
||||
if (hostName == null) {
|
||||
hostName = InetAddress.getHostFromNameService(this, check);
|
||||
if (holder().getHostName() == null) {
|
||||
holder().hostName = InetAddress.getHostFromNameService(this, check);
|
||||
}
|
||||
return hostName;
|
||||
return holder().getHostName();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -666,6 +694,7 @@ class InetAddress implements java.io.Serializable {
|
||||
* @return a string representation of this IP address.
|
||||
*/
|
||||
public String toString() {
|
||||
String hostName = holder().getHostName();
|
||||
return ((hostName != null) ? hostName : "")
|
||||
+ "/" + getHostAddress();
|
||||
}
|
||||
@ -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
|
||||
IOException, ClassNotFoundException {
|
||||
s.defaultReadObject ();
|
||||
if (getClass().getClassLoader() != null) {
|
||||
hostName = null;
|
||||
address = 0;
|
||||
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
|
||||
if (hostname != null)
|
||||
return hostname;
|
||||
if (addr != null) {
|
||||
if (addr.hostName != null)
|
||||
return addr.hostName;
|
||||
if (addr.holder().getHostName() != null)
|
||||
return addr.holder().getHostName();
|
||||
else
|
||||
return addr.getHostAddress();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -120,6 +120,13 @@ public class LogStream extends PrintStream {
|
||||
*/
|
||||
@Deprecated
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -556,7 +556,7 @@ public class DriverManager {
|
||||
*/
|
||||
try{
|
||||
while(driversIterator.hasNext()) {
|
||||
println(" Loading done by the java.util.ServiceLoader : "+driversIterator.next());
|
||||
driversIterator.next();
|
||||
}
|
||||
} catch(Throwable t) {
|
||||
// Do nothing
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
*/
|
||||
|
||||
package java.util.concurrent;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.util.concurrent.locks.*;
|
||||
import java.util.*;
|
||||
import java.io.Serializable;
|
||||
@ -1483,7 +1484,23 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
@SuppressWarnings("unchecked")
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
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
|
||||
UNSAFE.putIntVolatile(this, HASHSEED_OFFSET,
|
||||
@ -1517,6 +1534,9 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
private static final long TBASE;
|
||||
private static final int TSHIFT;
|
||||
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 {
|
||||
int ss, ts;
|
||||
@ -1530,6 +1550,12 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
ss = UNSAFE.arrayIndexScale(sc);
|
||||
HASHSEED_OFFSET = UNSAFE.objectFieldOffset(
|
||||
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) {
|
||||
throw new Error(e);
|
||||
}
|
||||
|
||||
@ -539,7 +539,7 @@ public abstract class EmbeddedFrame extends Frame
|
||||
public void toBack() {}
|
||||
public void updateFocusableWindowState() {}
|
||||
public void updateAlwaysOnTop() {}
|
||||
public void setAlwaysOnTop(boolean alwaysOnTop) {}
|
||||
public void updateAlwaysOnTopState() {}
|
||||
public Component getGlobalHeavyweightFocusOwner() { return null; }
|
||||
public void setBoundsPrivate(int x, int y, int width, int height) {
|
||||
setBounds(x, y, width, height, SET_BOUNDS);
|
||||
|
||||
@ -102,11 +102,11 @@ public class TransferableProxy implements Transferable {
|
||||
protected final boolean isLocal;
|
||||
}
|
||||
|
||||
class ClassLoaderObjectOutputStream extends ObjectOutputStream {
|
||||
final class ClassLoaderObjectOutputStream extends ObjectOutputStream {
|
||||
private final Map<Set<String>, ClassLoader> map =
|
||||
new HashMap<Set<String>, ClassLoader>();
|
||||
|
||||
public ClassLoaderObjectOutputStream(OutputStream os) throws IOException {
|
||||
ClassLoaderObjectOutputStream(OutputStream os) throws IOException {
|
||||
super(os);
|
||||
}
|
||||
|
||||
@ -140,16 +140,16 @@ class ClassLoaderObjectOutputStream extends ObjectOutputStream {
|
||||
map.put(s, classLoader);
|
||||
}
|
||||
|
||||
public Map<Set<String>, ClassLoader> getClassLoaderMap() {
|
||||
Map<Set<String>, ClassLoader> getClassLoaderMap() {
|
||||
return new HashMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
class ClassLoaderObjectInputStream extends ObjectInputStream {
|
||||
final class ClassLoaderObjectInputStream extends ObjectInputStream {
|
||||
private final Map<Set<String>, ClassLoader> map;
|
||||
|
||||
public ClassLoaderObjectInputStream(InputStream is,
|
||||
Map<Set<String>, ClassLoader> map)
|
||||
ClassLoaderObjectInputStream(InputStream is,
|
||||
Map<Set<String>, ClassLoader> map)
|
||||
throws IOException {
|
||||
super(is);
|
||||
if (map == null) {
|
||||
@ -166,8 +166,11 @@ class ClassLoaderObjectInputStream extends ObjectInputStream {
|
||||
s.add(className);
|
||||
|
||||
ClassLoader classLoader = map.get(s);
|
||||
|
||||
return Class.forName(className, false, classLoader);
|
||||
if (classLoader != null) {
|
||||
return Class.forName(className, false, classLoader);
|
||||
} else {
|
||||
return super.resolveClass(classDesc);
|
||||
}
|
||||
}
|
||||
|
||||
protected Class<?> resolveProxyClass(String[] interfaces)
|
||||
@ -179,6 +182,9 @@ class ClassLoaderObjectInputStream extends ObjectInputStream {
|
||||
}
|
||||
|
||||
ClassLoader classLoader = map.get(s);
|
||||
if (classLoader == null) {
|
||||
return super.resolveProxyClass(interfaces);
|
||||
}
|
||||
|
||||
// The code below is mostly copied from the superclass.
|
||||
ClassLoader nonPublicLoader = null;
|
||||
|
||||
@ -868,6 +868,15 @@ public class ByteComponentRaster extends SunWritableRaster {
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
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++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band " + i
|
||||
@ -905,13 +914,14 @@ public class ByteComponentRaster extends SunWritableRaster {
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
size = lastPixelOffset + dataOffsets[i];
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
|
||||
}
|
||||
|
||||
size = lastPixelOffset + dataOffsets[i];
|
||||
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
|
||||
@ -1368,11 +1368,35 @@ public class BytePackedRaster extends SunWritableRaster {
|
||||
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
|
||||
+ (height-1) * scanlineStride * 8
|
||||
+ (width-1) * pixelBitStride
|
||||
+ pixelBitStride - 1);
|
||||
if (lastbit / 8 >= data.length) {
|
||||
if (lastbit < 0 || lastbit / 8 >= data.length) {
|
||||
throw new RasterFormatException("raster dimensions overflow " +
|
||||
"array bounds");
|
||||
}
|
||||
|
||||
@ -333,10 +333,10 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer
|
||||
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,
|
||||
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,
|
||||
byte[] pix, int off, int scansize,
|
||||
ByteComponentRaster bct, int chanOff);
|
||||
@ -426,10 +426,10 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer
|
||||
IndexColorModel icm = (IndexColorModel) model;
|
||||
ByteComponentRaster bct = (ByteComponentRaster) biRaster;
|
||||
int numlut = numSrcLUT;
|
||||
if (setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
|
||||
if (!setDiffICM(x, y, w, h, srcLUT, srcLUTtransIndex,
|
||||
numSrcLUT, icm,
|
||||
pix, off, scansize, bct,
|
||||
bct.getDataOffset(0)) == 0) {
|
||||
bct.getDataOffset(0))) {
|
||||
convertToRGB();
|
||||
}
|
||||
else {
|
||||
@ -470,9 +470,14 @@ public class ImageRepresentation extends ImageWatched implements ImageConsumer
|
||||
if (s_useNative) {
|
||||
// Note that setICMpixels modifies the raster directly
|
||||
// so we must mark it as changed afterwards
|
||||
setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
|
||||
iraster);
|
||||
iraster.markDirty();
|
||||
if (setICMpixels(x, y, w, h, srcLUT, pix, off, scansize,
|
||||
iraster))
|
||||
{
|
||||
iraster.markDirty();
|
||||
} else {
|
||||
abort();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int[] storage = new int[w*h];
|
||||
|
||||
@ -208,7 +208,7 @@ public class IntegerComponentRaster extends SunWritableRaster {
|
||||
" SinglePixelPackedSampleModel");
|
||||
}
|
||||
|
||||
verify(false);
|
||||
verify();
|
||||
}
|
||||
|
||||
|
||||
@ -629,16 +629,26 @@ public class IntegerComponentRaster extends SunWritableRaster {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Verify that the layout parameters are consistent with the data.
|
||||
*
|
||||
* The method verifies whether scanline stride and pixel stride do not
|
||||
* cause an integer overflow during calculation of a position of the pixel
|
||||
* in data buffer. It also verifies whether the data buffer has enough data
|
||||
* to correspond the raster layout attributes.
|
||||
*
|
||||
* @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) {
|
||||
throw new RasterFormatException("Data offset ("+dataOffsets[0]+
|
||||
") must be >= 0");
|
||||
@ -647,17 +657,46 @@ public class IntegerComponentRaster extends SunWritableRaster {
|
||||
int maxSize = 0;
|
||||
int size;
|
||||
|
||||
for (int i=0; i < numDataElements; i++) {
|
||||
size = (height-1)*scanlineStride + (width-1)*pixelStride +
|
||||
dataOffsets[i];
|
||||
// we can be sure that width and height are greater than 0
|
||||
if (scanlineStride < 0 ||
|
||||
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) {
|
||||
maxSize = size;
|
||||
}
|
||||
}
|
||||
if (data.length < maxSize) {
|
||||
throw new RasterFormatException("Data array too small (should be "+
|
||||
maxSize
|
||||
+" but is "+data.length+" )");
|
||||
throw new RasterFormatException("Data array too small (should be "
|
||||
+ maxSize + " )");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -151,7 +151,7 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster {
|
||||
throw new RasterFormatException("IntegerInterleavedRasters must have"+
|
||||
" SinglePixelPackedSampleModel");
|
||||
}
|
||||
verify(false);
|
||||
verify();
|
||||
}
|
||||
|
||||
|
||||
@ -540,31 +540,6 @@ public class IntegerInterleavedRaster extends IntegerComponentRaster {
|
||||
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() {
|
||||
return new String ("IntegerInterleavedRaster: width = "+width
|
||||
+" height = " + height
|
||||
|
||||
@ -802,6 +802,15 @@ public class ShortComponentRaster extends SunWritableRaster {
|
||||
* or if data buffer has not enough capacity.
|
||||
*/
|
||||
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++) {
|
||||
if (dataOffsets[i] < 0) {
|
||||
throw new RasterFormatException("Data offsets for band " + i
|
||||
@ -839,12 +848,13 @@ public class ShortComponentRaster extends SunWritableRaster {
|
||||
lastPixelOffset += lastScanOffset;
|
||||
|
||||
for (int i = 0; i < numDataElements; i++) {
|
||||
size = lastPixelOffset + dataOffsets[i];
|
||||
if (dataOffsets[i] > (Integer.MAX_VALUE - lastPixelOffset)) {
|
||||
throw new RasterFormatException("Incorrect band offset: "
|
||||
+ dataOffsets[i]);
|
||||
}
|
||||
|
||||
size = lastPixelOffset + dataOffsets[i];
|
||||
|
||||
if (size > maxSize) {
|
||||
maxSize = size;
|
||||
}
|
||||
|
||||
@ -841,7 +841,6 @@ abstract class CMap {
|
||||
|
||||
CMapFormat6(ByteBuffer bbuffer, int offset, char[] xlat) {
|
||||
|
||||
System.err.println("WARNING: CMapFormat8 is untested.");
|
||||
bbuffer.position(offset+6);
|
||||
CharBuffer buffer = bbuffer.asCharBuffer();
|
||||
firstCode = buffer.get();
|
||||
@ -884,7 +883,6 @@ abstract class CMap {
|
||||
|
||||
CMapFormat8(ByteBuffer bbuffer, int offset, char[] xlat) {
|
||||
|
||||
System.err.println("WARNING: CMapFormat8 is untested.");
|
||||
bbuffer.position(12);
|
||||
bbuffer.get(is32);
|
||||
nGroups = bbuffer.getInt();
|
||||
@ -915,7 +913,6 @@ abstract class CMap {
|
||||
|
||||
CMapFormat10(ByteBuffer bbuffer, int offset, char[] xlat) {
|
||||
|
||||
System.err.println("WARNING: CMapFormat10 is untested.");
|
||||
firstCode = bbuffer.getInt() & INTMASK;
|
||||
entryCount = bbuffer.getInt() & INTMASK;
|
||||
bbuffer.position(offset+20);
|
||||
|
||||
@ -85,45 +85,72 @@ class LCMSImageLayout {
|
||||
private boolean imageAtOnce = false;
|
||||
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;
|
||||
width = np;
|
||||
height = 1;
|
||||
nextRowOffset = np * pixelSize;
|
||||
nextRowOffset = safeMult(pixelSize, np);
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
private LCMSImageLayout(int width, int height, int pixelType,
|
||||
int pixelSize) {
|
||||
int pixelSize)
|
||||
throws ImageLayoutException
|
||||
{
|
||||
this.pixelType = pixelType;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
nextRowOffset = width * pixelSize;
|
||||
nextRowOffset = safeMult(pixelSize, width);
|
||||
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);
|
||||
dataType = DT_BYTE;
|
||||
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);
|
||||
dataType = DT_SHORT;
|
||||
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);
|
||||
dataType = DT_INT;
|
||||
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);
|
||||
dataType = DT_DOUBLE;
|
||||
dataArray = data;
|
||||
dataArrayLength = 8 * data.length;
|
||||
|
||||
verify();
|
||||
}
|
||||
|
||||
private LCMSImageLayout() {
|
||||
@ -132,7 +159,7 @@ class LCMSImageLayout {
|
||||
/* This method creates a layout object for given image.
|
||||
* 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();
|
||||
|
||||
switch (image.getType()) {
|
||||
@ -193,9 +220,10 @@ class LCMSImageLayout {
|
||||
do {
|
||||
IntegerComponentRaster intRaster = (IntegerComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = intRaster.getScanlineStride() * 4;
|
||||
l.offset = intRaster.getDataOffset(0) * 4;
|
||||
l.nextRowOffset = safeMult(4, intRaster.getScanlineStride());
|
||||
l.offset = safeMult(4, intRaster.getDataOffset(0));
|
||||
l.dataArray = intRaster.getDataStorage();
|
||||
l.dataArrayLength = 4 * intRaster.getDataStorage().length;
|
||||
l.dataType = DT_INT;
|
||||
|
||||
if (l.nextRowOffset == l.width * 4 * intRaster.getPixelStride()) {
|
||||
@ -213,6 +241,7 @@ class LCMSImageLayout {
|
||||
int firstBand = image.getSampleModel().getNumBands() - 1;
|
||||
l.offset = byteRaster.getDataOffset(firstBand);
|
||||
l.dataArray = byteRaster.getDataStorage();
|
||||
l.dataArrayLength = byteRaster.getDataStorage().length;
|
||||
l.dataType = DT_BYTE;
|
||||
if (l.nextRowOffset == l.width * byteRaster.getPixelStride()) {
|
||||
l.imageAtOnce = true;
|
||||
@ -225,6 +254,7 @@ class LCMSImageLayout {
|
||||
ByteComponentRaster byteRaster = (ByteComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = byteRaster.getScanlineStride();
|
||||
l.dataArrayLength = byteRaster.getDataStorage().length;
|
||||
l.offset = byteRaster.getDataOffset(0);
|
||||
l.dataArray = byteRaster.getDataStorage();
|
||||
l.dataType = DT_BYTE;
|
||||
@ -239,9 +269,10 @@ class LCMSImageLayout {
|
||||
do {
|
||||
ShortComponentRaster shortRaster = (ShortComponentRaster)
|
||||
image.getRaster();
|
||||
l.nextRowOffset = shortRaster.getScanlineStride() * 2;
|
||||
l.offset = shortRaster.getDataOffset(0) * 2;
|
||||
l.nextRowOffset = safeMult(2, shortRaster.getScanlineStride());
|
||||
l.offset = safeMult(2, shortRaster.getDataOffset(0));
|
||||
l.dataArray = shortRaster.getDataStorage();
|
||||
l.dataArrayLength = 2 * shortRaster.getDataStorage().length;
|
||||
l.dataType = DT_SHORT;
|
||||
|
||||
if (l.nextRowOffset == l.width * 2 * shortRaster.getPixelStride()) {
|
||||
@ -252,6 +283,7 @@ class LCMSImageLayout {
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
l.verify();
|
||||
return l;
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
LCMSImageLayout l = new LCMSImageLayout();
|
||||
if (r instanceof ByteComponentRaster) {
|
||||
|
||||
@ -51,6 +51,7 @@ import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.ComponentSampleModel;
|
||||
import sun.java2d.cmm.*;
|
||||
import sun.java2d.cmm.lcms.*;
|
||||
import static sun.java2d.cmm.lcms.LCMSImageLayout.ImageLayoutException;
|
||||
|
||||
|
||||
public class LCMSTransform implements ColorTransform {
|
||||
@ -162,15 +163,19 @@ public class LCMSTransform implements ColorTransform {
|
||||
|
||||
public void colorConvert(BufferedImage src, BufferedImage dst) {
|
||||
LCMSImageLayout srcIL, dstIL;
|
||||
try {
|
||||
|
||||
dstIL = LCMSImageLayout.createImageLayout(dst);
|
||||
dstIL = LCMSImageLayout.createImageLayout(dst);
|
||||
|
||||
if (dstIL != null) {
|
||||
srcIL = LCMSImageLayout.createImageLayout(src);
|
||||
if (srcIL != null) {
|
||||
doTransform(srcIL, dstIL);
|
||||
return;
|
||||
if (dstIL != null) {
|
||||
srcIL = LCMSImageLayout.createImageLayout(src);
|
||||
if (srcIL != null) {
|
||||
doTransform(srcIL, dstIL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert images");
|
||||
}
|
||||
|
||||
Raster srcRas = src.getRaster();
|
||||
@ -228,14 +233,18 @@ public class LCMSTransform implements ColorTransform {
|
||||
}
|
||||
int idx;
|
||||
// TODO check for src npixels = dst npixels
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert images");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++) {
|
||||
// convert src scanline
|
||||
@ -284,16 +293,19 @@ public class LCMSTransform implements ColorTransform {
|
||||
alpha = new float[w];
|
||||
}
|
||||
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 images");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++) {
|
||||
// convert src scanline
|
||||
@ -402,16 +414,19 @@ public class LCMSTransform implements ColorTransform {
|
||||
short[] srcLine = new short[w * srcNumBands];
|
||||
short[] dstLine = new short[w * dstNumBands];
|
||||
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
|
||||
for (int y = 0; y < h; y++, ys++, yd++) {
|
||||
// get src scanline
|
||||
@ -502,15 +517,18 @@ public class LCMSTransform implements ColorTransform {
|
||||
byte[] dstLine = new byte[w * dstNumBands];
|
||||
int idx;
|
||||
// TODO check for src npixels = dst npixels
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
|
||||
try {
|
||||
srcIL = new LCMSImageLayout(
|
||||
srcLine, srcLine.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
dstIL = new LCMSImageLayout(
|
||||
dstLine, dstLine.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
} catch (ImageLayoutException e) {
|
||||
throw new CMMException("Unable to convert rasters");
|
||||
}
|
||||
// process each scanline
|
||||
for (int y = 0; y < h; y++, ys++, yd++) {
|
||||
// get src scanline
|
||||
@ -542,16 +560,20 @@ public class LCMSTransform implements ColorTransform {
|
||||
short[] srcLine = new short[w * srcNumBands];
|
||||
short[] dstLine = new short[w * dstNumBands];
|
||||
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
|
||||
for (int y = 0; y < h; y++, ys++, yd++) {
|
||||
// get src scanline
|
||||
@ -592,19 +614,23 @@ public class LCMSTransform implements ColorTransform {
|
||||
dst = new short [(src.length/getNumInComponents())*getNumOutComponents()];
|
||||
}
|
||||
|
||||
LCMSImageLayout srcIL = new LCMSImageLayout(
|
||||
src, src.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
|
||||
try {
|
||||
LCMSImageLayout srcIL = new LCMSImageLayout(
|
||||
src, src.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumInComponents()*2);
|
||||
|
||||
LCMSImageLayout dstIL = new LCMSImageLayout(
|
||||
dst, dst.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(2), getNumOutComponents()*2);
|
||||
LCMSImageLayout dstIL = new LCMSImageLayout(
|
||||
dst, dst.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
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) {
|
||||
@ -612,18 +638,22 @@ public class LCMSTransform implements ColorTransform {
|
||||
dst = new byte [(src.length/getNumInComponents())*getNumOutComponents()];
|
||||
}
|
||||
|
||||
LCMSImageLayout srcIL = new LCMSImageLayout(
|
||||
src, src.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
try {
|
||||
LCMSImageLayout srcIL = new LCMSImageLayout(
|
||||
src, src.length/getNumInComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumInComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumInComponents());
|
||||
|
||||
LCMSImageLayout dstIL = new LCMSImageLayout(
|
||||
dst, dst.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(getNumOutComponents()) |
|
||||
LCMSImageLayout.BYTES_SH(1), getNumOutComponents());
|
||||
LCMSImageLayout dstIL = new LCMSImageLayout(
|
||||
dst, dst.length/getNumOutComponents(),
|
||||
LCMSImageLayout.CHANNELS_SH(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;
|
||||
|
||||
|
||||
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)
|
||||
throws InvocationTargetException, IllegalAccessException {
|
||||
throws InvocationTargetException, IllegalAccessException
|
||||
{
|
||||
ensureInvocableMethod(m);
|
||||
return m.invoke(obj, params);
|
||||
}
|
||||
}
|
||||
@ -251,16 +271,6 @@ public final class MethodUtil extends SecureClassLoader {
|
||||
*/
|
||||
public static Object invoke(Method m, Object obj, Object[] params)
|
||||
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 {
|
||||
return bounce.invoke(null, new Object[] {m, obj, params});
|
||||
} catch (InvocationTargetException ie) {
|
||||
@ -293,10 +303,10 @@ public final class MethodUtil extends SecureClassLoader {
|
||||
Method.class, Object.class, Object[].class
|
||||
};
|
||||
Method b = t.getDeclaredMethod("invoke", types);
|
||||
((AccessibleObject)b).setAccessible(true);
|
||||
return b;
|
||||
}
|
||||
});
|
||||
b.setAccessible(true);
|
||||
return b;
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new InternalError("bouncer cannot be found", e);
|
||||
}
|
||||
|
||||
@ -55,13 +55,19 @@ import java.rmi.server.RMIClassLoader;
|
||||
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.
|
||||
*
|
||||
* 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 =
|
||||
java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetBooleanAction(
|
||||
"java.rmi.server.useCodebaseOnly")).booleanValue();
|
||||
! java.security.AccessController.doPrivileged(
|
||||
new sun.security.action.GetPropertyAction(
|
||||
"java.rmi.server.useCodebaseOnly", "true"))
|
||||
.equalsIgnoreCase("false");
|
||||
|
||||
/** table to hold sun classes to which access is explicitly permitted */
|
||||
protected static Map<String, Class<?>> permittedSunClasses
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -101,7 +101,7 @@ abstract class SHA2 extends DigestBase {
|
||||
i2bBig4((int)bitsProcessed, buffer, 60);
|
||||
implCompress(buffer, 0);
|
||||
|
||||
i2bBig(state, 0, out, ofs, 32);
|
||||
i2bBig(state, 0, out, ofs, engineGetDigestLength());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -843,5 +843,52 @@ public final class UntrustedCertificates {
|
||||
"zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" +
|
||||
"-----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
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -174,22 +187,35 @@ package.access=sun.,\
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
||||
@ -147,22 +147,34 @@ keystore.type=jks
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.,\
|
||||
apple.
|
||||
|
||||
#
|
||||
@ -176,22 +188,34 @@ package.access=sun.,\
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.,\
|
||||
apple.
|
||||
|
||||
#
|
||||
|
||||
@ -148,22 +148,34 @@ keystore.type=jks
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -176,22 +188,34 @@ package.access=sun.,\
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
||||
@ -147,22 +147,35 @@ keystore.type=jks
|
||||
# corresponding RuntimePermission ("accessClassInPackage."+package) has
|
||||
# been granted.
|
||||
package.access=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.,\
|
||||
com.sun.java.accessibility.
|
||||
|
||||
#
|
||||
# List of comma-separated packages that start with or equal this string
|
||||
@ -175,22 +188,35 @@ package.access=sun.,\
|
||||
# checkPackageDefinition.
|
||||
#
|
||||
package.definition=sun.,\
|
||||
com.sun.xml.internal.bind.,\
|
||||
com.sun.xml.internal.org.jvnet.staxex.,\
|
||||
com.sun.xml.internal.ws.,\
|
||||
com.sun.xml.internal.,\
|
||||
com.sun.imageio.,\
|
||||
com.sun.istack.internal.,\
|
||||
com.sun.jmx.,\
|
||||
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.glassfish.external.,\
|
||||
com.sun.org.glassfish.gmbal.,\
|
||||
com.sun.org.apache.xalan.internal.xslt.,\
|
||||
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.webservices.internal.,\
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.
|
||||
jdk.internal.,\
|
||||
jdk.nashorn.internal.,\
|
||||
jdk.nashorn.tools.,\
|
||||
com.sun.java.accessibility.
|
||||
|
||||
#
|
||||
# Determines whether this properties file can be appended to
|
||||
|
||||
@ -33,8 +33,11 @@
|
||||
*/
|
||||
|
||||
jclass ia_class;
|
||||
jfieldID ia_addressID;
|
||||
jfieldID ia_familyID;
|
||||
jclass iac_class;
|
||||
jfieldID ia_holderID;
|
||||
jfieldID iac_addressID;
|
||||
jfieldID iac_familyID;
|
||||
jfieldID iac_hostNameID;
|
||||
jfieldID ia_preferIPv6AddressID;
|
||||
|
||||
/*
|
||||
@ -48,10 +51,18 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
|
||||
CHECK_NULL(c);
|
||||
ia_class = (*env)->NewGlobalRef(env, c);
|
||||
CHECK_NULL(ia_class);
|
||||
ia_addressID = (*env)->GetFieldID(env, ia_class, "address", "I");
|
||||
CHECK_NULL(ia_addressID);
|
||||
ia_familyID = (*env)->GetFieldID(env, ia_class, "family", "I");
|
||||
CHECK_NULL(ia_familyID);
|
||||
c = (*env)->FindClass(env,"java/net/InetAddress$InetAddressHolder");
|
||||
CHECK_NULL(c);
|
||||
iac_class = (*env)->NewGlobalRef(env, c);
|
||||
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");
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
|
||||
jobject iaObj;
|
||||
@ -110,8 +162,8 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
|
||||
iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
|
||||
CHECK_NULL_RETURN(iaObj, NULL);
|
||||
address = NET_IPv4MappedToIPv4(caddr);
|
||||
(*env)->SetIntField(env, iaObj, ia_addressID, address);
|
||||
(*env)->SetIntField(env, iaObj, ia_familyID, IPv4);
|
||||
setInetAddress_addr(env, iaObj, address);
|
||||
setInetAddress_family(env, iaObj, IPv4);
|
||||
} else {
|
||||
static jclass inet6Cls = 0;
|
||||
jint scope;
|
||||
@ -131,7 +183,7 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
|
||||
|
||||
(*env)->SetObjectField(env, iaObj, ia6_ipaddressID, ipaddress);
|
||||
|
||||
(*env)->SetIntField(env, iaObj, ia_familyID, IPv6);
|
||||
setInetAddress_family(env, iaObj, IPv6);
|
||||
scope = getScopeID(him);
|
||||
(*env)->SetIntField(env, iaObj, ia6_scopeidID, scope);
|
||||
if (scope > 0)
|
||||
@ -153,9 +205,8 @@ NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port) {
|
||||
}
|
||||
iaObj = (*env)->NewObject(env, inet4Cls, ia4_ctrID);
|
||||
CHECK_NULL_RETURN(iaObj, NULL);
|
||||
(*env)->SetIntField(env, iaObj, ia_familyID, IPv4);
|
||||
(*env)->SetIntField(env, iaObj, ia_addressID,
|
||||
ntohl(him4->sin_addr.s_addr));
|
||||
setInetAddress_family(env, iaObj, IPv4);
|
||||
setInetAddress_addr(env, iaObj, ntohl(him4->sin_addr.s_addr));
|
||||
*port = ntohs(him4->sin_port);
|
||||
}
|
||||
return iaObj;
|
||||
@ -167,8 +218,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
|
||||
jint family = AF_INET;
|
||||
|
||||
#ifdef AF_INET6
|
||||
family = (*env)->GetIntField(env, iaObj, ia_familyID) == IPv4?
|
||||
AF_INET : AF_INET6;
|
||||
family = getInetAddress_family(env, iaObj) == IPv4? AF_INET : AF_INET6;
|
||||
if (him->sa_family == AF_INET6) {
|
||||
#ifdef WIN32
|
||||
struct SOCKADDR_IN6 *him6 = (struct SOCKADDR_IN6 *)him;
|
||||
@ -183,7 +233,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
|
||||
return JNI_FALSE;
|
||||
}
|
||||
addrNew = NET_IPv4MappedToIPv4(caddrNew);
|
||||
addrCur = (*env)->GetIntField(env, iaObj, ia_addressID);
|
||||
addrCur = getInetAddress_addr(env, iaObj);
|
||||
if (addrNew == addrCur) {
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
@ -215,7 +265,7 @@ NET_SockaddrEqualsInetAddress(JNIEnv *env, struct sockaddr *him, jobject iaObj)
|
||||
return JNI_FALSE;
|
||||
}
|
||||
addrNew = ntohl(him4->sin_addr.s_addr);
|
||||
addrCur = (*env)->GetIntField(env, iaObj, ia_addressID);
|
||||
addrCur = getInetAddress_addr(env, iaObj);
|
||||
if (addrNew == addrCur) {
|
||||
return JNI_TRUE;
|
||||
} else {
|
||||
|
||||
@ -53,10 +53,18 @@
|
||||
* i.e. psi_timeoutID is PlainSocketImpl's timeout field's ID.
|
||||
*/
|
||||
extern jclass ia_class;
|
||||
extern jfieldID ia_addressID;
|
||||
extern jfieldID ia_familyID;
|
||||
extern jfieldID iac_addressID;
|
||||
extern jfieldID iac_familyID;
|
||||
extern jfieldID iac_hostNameID;
|
||||
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 jmethodID ia4_ctrID;
|
||||
|
||||
|
||||
@ -45,6 +45,53 @@ static int findIdx(unsigned int rgb, unsigned int *lut, int numLut1);
|
||||
# define TRUE 1
|
||||
#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_JsrcLUTtransIndexID;
|
||||
|
||||
@ -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
|
||||
*/
|
||||
JNIEXPORT void JNICALL
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
|
||||
jint x, jint y, jint w,
|
||||
jint h, jintArray jlut,
|
||||
@ -67,7 +114,10 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
|
||||
jobject jict)
|
||||
{
|
||||
unsigned char *srcData = NULL;
|
||||
jint srcDataLength;
|
||||
int *dstData;
|
||||
jint dstDataLength;
|
||||
jint dstDataOff;
|
||||
int *dstP, *dstyP;
|
||||
unsigned char *srcyP, *srcP;
|
||||
int *srcLUT = NULL;
|
||||
@ -80,12 +130,20 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
|
||||
|
||||
if (JNU_IsNull(env, jlut)) {
|
||||
JNU_ThrowNullPointerException(env, "NullPointerException");
|
||||
return;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (JNU_IsNull(env, jpix)) {
|
||||
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);
|
||||
@ -93,10 +151,47 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
|
||||
joffs = (*env)->GetObjectField(env, jict, g_ICRdataOffsetsID);
|
||||
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);
|
||||
if (srcLUT == NULL) {
|
||||
JNU_ThrowNullPointerException(env, "Null IndexColorModel LUT");
|
||||
return;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
|
||||
@ -104,27 +199,18 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
|
||||
if (srcData == NULL) {
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
|
||||
JNU_ThrowNullPointerException(env, "Null data array");
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
dstData = (int *) (*env)->GetPrimitiveArrayCritical(env, jdata, NULL);
|
||||
if (dstData == NULL) {
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, JNI_ABORT);
|
||||
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;
|
||||
for (yIdx = 0; yIdx < h; yIdx++, srcyP += scansize, dstyP+=sStride) {
|
||||
srcP = srcyP;
|
||||
@ -137,12 +223,12 @@ Java_sun_awt_image_ImageRepresentation_setICMpixels(JNIEnv *env, jclass cls,
|
||||
/* Release the locked arrays */
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT, JNI_ABORT);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, joffs, cOffs, 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,
|
||||
jint x, jint y, jint w,
|
||||
jint h, jintArray jlut,
|
||||
@ -150,7 +236,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
jobject jicm,
|
||||
jbyteArray jpix, jint off,
|
||||
jint scansize,
|
||||
jobject jbct, jint chanOff)
|
||||
jobject jbct, jint dstDataOff)
|
||||
{
|
||||
unsigned int *srcLUT = NULL;
|
||||
unsigned int *newLUT = NULL;
|
||||
@ -159,6 +245,8 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
int mapSize;
|
||||
jobject jdata = NULL;
|
||||
jobject jnewlut = NULL;
|
||||
jint srcDataLength;
|
||||
jint dstDataLength;
|
||||
unsigned char *srcData;
|
||||
unsigned char *dstData;
|
||||
unsigned char *dataP;
|
||||
@ -174,14 +262,23 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
|
||||
if (JNU_IsNull(env, jlut)) {
|
||||
JNU_ThrowNullPointerException(env, "NullPointerException");
|
||||
return 0;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
if (JNU_IsNull(env, jpix)) {
|
||||
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);
|
||||
pixelStride =(*env)->GetIntField(env, jbct, g_BCRpixstrID);
|
||||
jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
|
||||
@ -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
|
||||
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,
|
||||
NULL);
|
||||
if (srcLUT == NULL) {
|
||||
/* out of memory error already thrown */
|
||||
return 0;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
newLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jnewlut,
|
||||
@ -208,7 +323,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
|
||||
JNI_ABORT);
|
||||
/* out of memory error already thrown */
|
||||
return 0;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
newNumLut = numLut;
|
||||
@ -219,7 +334,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jlut, srcLUT,
|
||||
JNI_ABORT);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jnewlut, newLUT, JNI_ABORT);
|
||||
return 0;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
/* Don't need these any more */
|
||||
@ -239,7 +354,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
NULL);
|
||||
if (srcData == NULL) {
|
||||
/* out of memory error already thrown */
|
||||
return 0;
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
|
||||
@ -247,10 +362,10 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
if (dstData == NULL) {
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
|
||||
/* 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;
|
||||
|
||||
for (i=0; i < h; i++) {
|
||||
@ -268,7 +383,7 @@ Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
|
||||
(*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
|
||||
|
||||
return 1;
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static int compareLUTs(unsigned int *lut1, int numLut1, int transIdx,
|
||||
|
||||
@ -34,6 +34,7 @@
|
||||
#include "java_awt_color_ColorSpace.h"
|
||||
#include "awt_Mlib.h"
|
||||
#include "safe_alloc.h"
|
||||
#include "safe_math.h"
|
||||
|
||||
static int setHints(JNIEnv *env, BufImageS_t *imageP);
|
||||
|
||||
|
||||
@ -57,8 +57,8 @@
|
||||
#define MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
/* Cached Java method ids */
|
||||
static jmethodID ImageInputStream_readID;
|
||||
static jmethodID ImageInputStream_skipBytesID;
|
||||
static jmethodID JPEGImageReader_readInputDataID;
|
||||
static jmethodID JPEGImageReader_skipInputBytesID;
|
||||
static jmethodID JPEGImageReader_warningOccurredID;
|
||||
static jmethodID JPEGImageReader_warningWithMessageID;
|
||||
static jmethodID JPEGImageReader_setImageDataID;
|
||||
@ -66,7 +66,7 @@ static jmethodID JPEGImageReader_acceptPixelsID;
|
||||
static jmethodID JPEGImageReader_pushBackID;
|
||||
static jmethodID JPEGImageReader_passStartedID;
|
||||
static jmethodID JPEGImageReader_passCompleteID;
|
||||
static jmethodID ImageOutputStream_writeID;
|
||||
static jmethodID JPEGImageWriter_writeOutputDataID;
|
||||
static jmethodID JPEGImageWriter_warningOccurredID;
|
||||
static jmethodID JPEGImageWriter_warningWithMessageID;
|
||||
static jmethodID JPEGImageWriter_writeMetadataID;
|
||||
@ -923,7 +923,7 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo)
|
||||
RELEASE_ARRAYS(env, data, src->next_input_byte);
|
||||
ret = (*env)->CallIntMethod(env,
|
||||
sb->stream,
|
||||
ImageInputStream_readID,
|
||||
JPEGImageReader_readInputDataID,
|
||||
sb->hstreamBuffer, 0,
|
||||
sb->bufferLength);
|
||||
if ((*env)->ExceptionOccurred(env)
|
||||
@ -1013,7 +1013,7 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo)
|
||||
}
|
||||
|
||||
ret = (*env)->CallIntMethod(env, sb->stream,
|
||||
ImageInputStream_readID,
|
||||
JPEGImageReader_readInputDataID,
|
||||
sb->hstreamBuffer,
|
||||
offset, buflen);
|
||||
if ((*env)->ExceptionOccurred(env)
|
||||
@ -1107,7 +1107,7 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes)
|
||||
RELEASE_ARRAYS(env, data, src->next_input_byte);
|
||||
ret = (*env)->CallLongMethod(env,
|
||||
sb->stream,
|
||||
ImageInputStream_skipBytesID,
|
||||
JPEGImageReader_skipInputBytesID,
|
||||
(jlong) num_bytes);
|
||||
if ((*env)->ExceptionOccurred(env)
|
||||
|| !GET_ARRAYS(env, data, &(src->next_input_byte))) {
|
||||
@ -1382,13 +1382,13 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initReaderIDs
|
||||
jclass qTableClass,
|
||||
jclass huffClass) {
|
||||
|
||||
ImageInputStream_readID = (*env)->GetMethodID(env,
|
||||
ImageInputStreamClass,
|
||||
"read",
|
||||
JPEGImageReader_readInputDataID = (*env)->GetMethodID(env,
|
||||
cls,
|
||||
"readInputData",
|
||||
"([BII)I");
|
||||
ImageInputStream_skipBytesID = (*env)->GetMethodID(env,
|
||||
ImageInputStreamClass,
|
||||
"skipBytes",
|
||||
JPEGImageReader_skipInputBytesID = (*env)->GetMethodID(env,
|
||||
cls,
|
||||
"skipInputBytes",
|
||||
"(J)J");
|
||||
JPEGImageReader_warningOccurredID = (*env)->GetMethodID(env,
|
||||
cls,
|
||||
@ -1531,8 +1531,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource
|
||||
(JNIEnv *env,
|
||||
jobject this,
|
||||
jlong ptr,
|
||||
jobject source) {
|
||||
jlong ptr) {
|
||||
|
||||
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
|
||||
j_common_ptr cinfo;
|
||||
@ -1546,7 +1545,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_setSource
|
||||
|
||||
cinfo = data->jpegObj;
|
||||
|
||||
imageio_set_stream(env, cinfo, data, source);
|
||||
imageio_set_stream(env, cinfo, data, this);
|
||||
|
||||
imageio_init_source((j_decompress_ptr) cinfo);
|
||||
}
|
||||
@ -2291,7 +2290,7 @@ imageio_empty_output_buffer (j_compress_ptr cinfo)
|
||||
|
||||
(*env)->CallVoidMethod(env,
|
||||
sb->stream,
|
||||
ImageOutputStream_writeID,
|
||||
JPEGImageWriter_writeOutputDataID,
|
||||
sb->hstreamBuffer,
|
||||
0,
|
||||
sb->bufferLength);
|
||||
@ -2328,7 +2327,7 @@ imageio_term_destination (j_compress_ptr cinfo)
|
||||
|
||||
(*env)->CallVoidMethod(env,
|
||||
sb->stream,
|
||||
ImageOutputStream_writeID,
|
||||
JPEGImageWriter_writeOutputDataID,
|
||||
sb->hstreamBuffer,
|
||||
0,
|
||||
datacount);
|
||||
@ -2366,13 +2365,12 @@ JNIEXPORT void JNICALL
|
||||
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initWriterIDs
|
||||
(JNIEnv *env,
|
||||
jclass cls,
|
||||
jclass IOSClass,
|
||||
jclass qTableClass,
|
||||
jclass huffClass) {
|
||||
|
||||
ImageOutputStream_writeID = (*env)->GetMethodID(env,
|
||||
IOSClass,
|
||||
"write",
|
||||
JPEGImageWriter_writeOutputDataID = (*env)->GetMethodID(env,
|
||||
cls,
|
||||
"writeOutputData",
|
||||
"([BII)V");
|
||||
|
||||
JPEGImageWriter_warningOccurredID = (*env)->GetMethodID(env,
|
||||
@ -2496,8 +2494,7 @@ JNIEXPORT void JNICALL
|
||||
Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
|
||||
(JNIEnv *env,
|
||||
jobject this,
|
||||
jlong ptr,
|
||||
jobject destination) {
|
||||
jlong ptr) {
|
||||
|
||||
imageIODataPtr data = (imageIODataPtr)jlong_to_ptr(ptr);
|
||||
j_compress_ptr cinfo;
|
||||
@ -2511,7 +2508,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_setDest
|
||||
|
||||
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
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
#include "awt_Mlib.h"
|
||||
#include "gdefs.h"
|
||||
#include "safe_alloc.h"
|
||||
#include "safe_math.h"
|
||||
|
||||
/***************************************************************************
|
||||
* Definitions *
|
||||
@ -1993,13 +1994,23 @@ cvtCustomToDefault(JNIEnv *env, BufImageS_t *imageP, int component,
|
||||
unsigned char *dP = dataP;
|
||||
#define NUM_LINES 10
|
||||
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) {
|
||||
/* getData, one scanline at a time */
|
||||
if (y+numLines > rasterP->height) {
|
||||
numLines = rasterP->height - y;
|
||||
nbytes = rasterP->width*4*numLines;
|
||||
nbytes = numLines * scanLength;
|
||||
}
|
||||
jpixels = (*env)->CallObjectMethod(env, imageP->jimage,
|
||||
g_BImgGetRGBMID, 0, y,
|
||||
@ -2129,8 +2140,14 @@ allocateArray(JNIEnv *env, BufImageS_t *imageP,
|
||||
if (cvtToDefault) {
|
||||
int status = 0;
|
||||
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, 4, width, height);
|
||||
if (*mlibImagePP == NULL) {
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
|
||||
if (!isSrc) {
|
||||
@ -2380,6 +2397,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
|
||||
case sun_awt_image_IntegerComponentRaster_TYPE_BYTE_PACKED_SAMPLES:
|
||||
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
|
||||
width, height);
|
||||
if (*mlibImagePP == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (!isSrc) return 0;
|
||||
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
|
||||
return expandPackedBCR(env, rasterP, -1, cDataP);
|
||||
@ -2388,6 +2408,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
|
||||
if (rasterP->sppsm.maxBitSize <= 8) {
|
||||
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
|
||||
width, height);
|
||||
if (*mlibImagePP == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (!isSrc) return 0;
|
||||
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
|
||||
return expandPackedSCR(env, rasterP, -1, cDataP);
|
||||
@ -2397,6 +2420,9 @@ allocateRasterArray(JNIEnv *env, RasterS_t *rasterP,
|
||||
if (rasterP->sppsm.maxBitSize <= 8) {
|
||||
*mlibImagePP = (*sMlibSysFns.createFP)(MLIB_BYTE, rasterP->numBands,
|
||||
width, height);
|
||||
if (*mlibImagePP == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (!isSrc) return 0;
|
||||
cDataP = (unsigned char *) mlib_ImageGetData(*mlibImagePP);
|
||||
return expandPackedICR(env, rasterP, -1, cDataP);
|
||||
|
||||
@ -120,6 +120,7 @@
|
||||
#include "mlib_image.h"
|
||||
#include "mlib_ImageRowTable.h"
|
||||
#include "mlib_ImageCreate.h"
|
||||
#include "safe_math.h"
|
||||
|
||||
/***************************************************************/
|
||||
mlib_image* mlib_ImageSet(mlib_image *image,
|
||||
@ -247,28 +248,50 @@ mlib_image *mlib_ImageCreate(mlib_type type,
|
||||
return NULL;
|
||||
};
|
||||
|
||||
if (!SAFE_TO_MULT(width, channels)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wb = width * channels;
|
||||
|
||||
switch (type) {
|
||||
case MLIB_DOUBLE:
|
||||
wb = width * channels * 8;
|
||||
if (!SAFE_TO_MULT(wb, 8)) {
|
||||
return NULL;
|
||||
}
|
||||
wb *= 8;
|
||||
break;
|
||||
case MLIB_FLOAT:
|
||||
case MLIB_INT:
|
||||
wb = width * channels * 4;
|
||||
if (!SAFE_TO_MULT(wb, 4)) {
|
||||
return NULL;
|
||||
}
|
||||
wb *= 4;
|
||||
break;
|
||||
case MLIB_USHORT:
|
||||
case MLIB_SHORT:
|
||||
wb = width * channels * 2;
|
||||
if (!SAFE_TO_MULT(wb, 4)) {
|
||||
return NULL;
|
||||
}
|
||||
wb *= 2;
|
||||
break;
|
||||
case MLIB_BYTE:
|
||||
wb = width * channels;
|
||||
// wb is ready
|
||||
break;
|
||||
case MLIB_BIT:
|
||||
wb = (width * channels + 7) / 8;
|
||||
if (!SAFE_TO_ADD(7, wb)) {
|
||||
return NULL;
|
||||
}
|
||||
wb = (wb + 7) / 8;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!SAFE_TO_MULT(wb, height)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = mlib_malloc(wb * height);
|
||||
if (data == NULL) {
|
||||
return NULL;
|
||||
|
||||
@ -41,10 +41,4 @@
|
||||
(((w) > 0) && ((h) > 0) && ((sz) > 0) && \
|
||||
(((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__
|
||||
|
||||
35
jdk/src/share/native/sun/awt/medialib/safe_math.h
Normal file
35
jdk/src/share/native/sun/awt/medialib/safe_math.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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,
|
||||
yScalePixelsToUnits = upem / yppem;
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
return 0;
|
||||
}
|
||||
@ -75,14 +88,19 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
|
||||
// cache in font's pscaler object
|
||||
// font disposer will handle for us
|
||||
|
||||
switch(tableTag) {
|
||||
case GSUB_TAG: if (layoutTables->gsub_len != -1) return (void*)layoutTables->gsub; break;
|
||||
case GPOS_TAG: if (layoutTables->gpos_len != -1) return (void*)layoutTables->gpos; 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;
|
||||
default:
|
||||
//fprintf(stderr, "unexpected table request from font instance adapter: %x\n", tableTag);
|
||||
int cacheIdx;
|
||||
for (cacheIdx=0;cacheIdx<LAYOUTCACHE_ENTRIES;cacheIdx++) {
|
||||
if (tableTag==cacheMap[cacheIdx]) break;
|
||||
}
|
||||
|
||||
if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if found
|
||||
if (layoutTables->entries[cacheIdx].len != -1) {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -96,16 +114,13 @@ const void *FontInstanceAdapter::getFontTable(LETag tableTag) const
|
||||
env->GetByteArrayRegion(tableBytes, 0, len, result);
|
||||
}
|
||||
|
||||
switch(tableTag) {
|
||||
case GSUB_TAG: layoutTables->gsub = (void*)result; layoutTables->gsub_len = len; break;
|
||||
case GPOS_TAG: layoutTables->gpos = (void*)result; layoutTables->gpos_len = len; break;
|
||||
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;
|
||||
if (cacheIdx<LAYOUTCACHE_ENTRIES) { // if cacheable table
|
||||
layoutTables->entries[cacheIdx].len = len;
|
||||
layoutTables->entries[cacheIdx].ptr = (const void*)result;
|
||||
}
|
||||
|
||||
return (void*)result;
|
||||
length = len;
|
||||
return (const void*)result;
|
||||
};
|
||||
|
||||
LEGlyphID FontInstanceAdapter::mapCharToGlyph(LEUnicode32 ch, const LECharMapper *mapper) const
|
||||
|
||||
@ -86,6 +86,7 @@ public:
|
||||
// tables are cached with the native font scaler data
|
||||
// only supports gsub, gpos, gdef, mort tables at present
|
||||
virtual const void *getFontTable(LETag tableTag) const;
|
||||
virtual const void *getFontTable(LETag tableTag, size_t &len) const;
|
||||
|
||||
virtual void *getKernPairs() const {
|
||||
return layoutTables->kernPairs;
|
||||
|
||||
@ -120,20 +120,19 @@ typedef struct GlyphInfo {
|
||||
#define GPOS_TAG 0x47504F53 /* 'GPOS' */
|
||||
#define GDEF_TAG 0x47444546 /* 'GDEF' */
|
||||
#define MORT_TAG 0x6D6F7274 /* 'mort' */
|
||||
#define MORX_TAG 0x6D6F7278 /* 'morx' */
|
||||
#define KERN_TAG 0x6B65726E /* 'kern' */
|
||||
|
||||
typedef struct TTLayoutTableCacheEntry {
|
||||
const void* ptr;
|
||||
int len;
|
||||
} TTLayoutTableCacheEntry;
|
||||
|
||||
#define LAYOUTCACHE_ENTRIES 6
|
||||
|
||||
typedef struct TTLayoutTableCache {
|
||||
void* gsub;
|
||||
void* gpos;
|
||||
void* gdef;
|
||||
void* mort;
|
||||
void* kern;
|
||||
void* kernPairs;
|
||||
int gsub_len;
|
||||
int gpos_len;
|
||||
int gdef_len;
|
||||
int mort_len;
|
||||
int kern_len;
|
||||
TTLayoutTableCacheEntry entries[LAYOUTCACHE_ENTRIES];
|
||||
void* kernPairs;
|
||||
} TTLayoutTableCache;
|
||||
|
||||
#include "sunfontids.h"
|
||||
|
||||
@ -39,19 +39,20 @@
|
||||
|
||||
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...
|
||||
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);
|
||||
|
||||
if (coverageIndex < altSetCount) {
|
||||
Offset alternateSetTableOffset = SWAPW(alternateSetTableOffsetArray[coverageIndex]);
|
||||
const AlternateSetTable *alternateSetTable =
|
||||
(const AlternateSetTable *) ((char *) this + alternateSetTableOffset);
|
||||
const LEReferenceTo<AlternateSetTable> alternateSetTable(base, success,
|
||||
(const AlternateSetTable *) ((char *) this + alternateSetTableOffset));
|
||||
TTGlyphID alternate = SWAPW(alternateSetTable->alternateArray[0]);
|
||||
|
||||
if (filter == NULL || filter->accept(LE_SET_GLYPH(glyph, alternate))) {
|
||||
|
||||
@ -51,13 +51,17 @@ struct AlternateSetTable
|
||||
TTGlyphID alternateArray[ANY_NUMBER];
|
||||
};
|
||||
|
||||
LE_VAR_ARRAY(AlternateSetTable, alternateArray)
|
||||
|
||||
struct AlternateSubstitutionSubtable : GlyphSubstitutionSubtable
|
||||
{
|
||||
le_uint16 alternateSetCount;
|
||||
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
|
||||
#endif
|
||||
|
||||
@ -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
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ArabicOpenTypeLayoutEngine)
|
||||
|
||||
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode,
|
||||
le_int32 typoFlags, const GlyphSubstitutionTableHeader *gsubTable, LEErrorCode &success)
|
||||
ArabicOpenTypeLayoutEngine::ArabicOpenTypeLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode,
|
||||
le_int32 languageCode, le_int32 typoFlags,
|
||||
const LEReferenceTo<GlyphSubstitutionTableHeader> &gsubTable,
|
||||
LEErrorCode &success)
|
||||
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, gsubTable, success)
|
||||
{
|
||||
fFeatureMap = ArabicShaping::getFeatureMap(fFeatureMapCount);
|
||||
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)
|
||||
: OpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
|
||||
{
|
||||
@ -88,8 +91,9 @@ ArabicOpenTypeLayoutEngine::~ArabicOpenTypeLayoutEngine()
|
||||
// Input: characters
|
||||
// Output: characters, char indices, tags
|
||||
// Returns: output character count
|
||||
le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEUnicode *&outChars, LEGlyphStorage &glyphStorage, LEErrorCode &success)
|
||||
le_int32 ArabicOpenTypeLayoutEngine::characterProcessing(const LEUnicode chars[], le_int32 offset, le_int32 count,
|
||||
le_int32 max, le_bool rightToLeft, LEUnicode *&outChars,
|
||||
LEGlyphStorage &glyphStorage, LEErrorCode &success)
|
||||
{
|
||||
if (LE_FAILURE(success)) {
|
||||
return 0;
|
||||
@ -137,32 +141,30 @@ void ArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode chars[], l
|
||||
return;
|
||||
}
|
||||
|
||||
if (fGPOSTable != NULL) {
|
||||
if (!fGPOSTable.isEmpty()) {
|
||||
OpenTypeLayoutEngine::adjustGlyphPositions(chars, offset, count, reverse, glyphStorage, success);
|
||||
} else if (fGDEFTable != NULL) {
|
||||
GDEFMarkFilter filter(fGDEFTable);
|
||||
|
||||
} else if (!fGDEFTable.isEmpty()) {
|
||||
GDEFMarkFilter filter(fGDEFTable, success);
|
||||
adjustMarkGlyphs(glyphStorage, &filter, success);
|
||||
} else {
|
||||
GlyphDefinitionTableHeader *gdefTable = (GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
|
||||
GDEFMarkFilter filter(gdefTable);
|
||||
LEReferenceTo<GlyphDefinitionTableHeader> gdefTable(CanonShaping::glyphDefinitionTable, CanonShaping::glyphDefinitionTableLen);
|
||||
GDEFMarkFilter filter(gdefTable, 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)
|
||||
: ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success)
|
||||
: ArabicOpenTypeLayoutEngine(fontInstance, scriptCode, languageCode, typoFlags | LE_CHAR_FILTER_FEATURE_FLAG, success)
|
||||
{
|
||||
fGSUBTable = (const GlyphSubstitutionTableHeader *) CanonShaping::glyphSubstitutionTable;
|
||||
fGDEFTable = (const GlyphDefinitionTableHeader *) CanonShaping::glyphDefinitionTable;
|
||||
|
||||
fSubstitutionFilter = new CharSubstitutionFilter(fontInstance);
|
||||
/* OpenTypeLayoutEngine will allocate a substitution filter */
|
||||
}
|
||||
|
||||
UnicodeArabicOpenTypeLayoutEngine::~UnicodeArabicOpenTypeLayoutEngine()
|
||||
{
|
||||
delete fSubstitutionFilter;
|
||||
/* OpenTypeLayoutEngine will cleanup the substitution filter */
|
||||
}
|
||||
|
||||
// "glyphs", "indices" -> glyphs, indices
|
||||
@ -233,7 +235,7 @@ void UnicodeArabicOpenTypeLayoutEngine::adjustGlyphPositions(const LEUnicode cha
|
||||
return;
|
||||
}
|
||||
|
||||
GDEFMarkFilter filter(fGDEFTable);
|
||||
GDEFMarkFilter filter(fGDEFTable, success);
|
||||
|
||||
adjustMarkGlyphs(&chars[offset], count, reverse, glyphStorage, &filter, success);
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ public:
|
||||
* @internal
|
||||
*/
|
||||
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
|
||||
|
||||
@ -58,14 +58,16 @@ const ArabicShaping::ShapeType ArabicShaping::shapeTypes[] =
|
||||
*/
|
||||
ArabicShaping::ShapeType ArabicShaping::getShapeType(LEUnicode c)
|
||||
{
|
||||
const ClassDefinitionTable *joiningTypes = (const ClassDefinitionTable *) ArabicShaping::shapingTypeTable;
|
||||
le_int32 joiningType = joiningTypes->getGlyphClass(c);
|
||||
LEErrorCode success = LE_NO_ERROR;
|
||||
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) {
|
||||
return ArabicShaping::shapeTypes[joiningType];
|
||||
}
|
||||
if (joiningType >= 0 && joiningType < ArabicShaping::JT_COUNT && LE_SUCCESS(success)) {
|
||||
return ArabicShaping::shapeTypes[joiningType];
|
||||
}
|
||||
|
||||
return ArabicShaping::ST_NOSHAPE_NONE;
|
||||
return ArabicShaping::ST_NOSHAPE_NONE;
|
||||
}
|
||||
|
||||
#define isolFeatureTag LE_ISOL_FEATURE_TAG
|
||||
|
||||
@ -93,6 +93,8 @@ private:
|
||||
static ShapeType getShapeType(LEUnicode c);
|
||||
|
||||
static const le_uint8 shapingTypeTable[];
|
||||
static const size_t shapingTypeTableLen;
|
||||
|
||||
static const ShapeType shapeTypes[];
|
||||
|
||||
static void adjustTags(le_int32 outIndex, le_int32 shapeOffset, LEGlyphStorage &glyphStorage);
|
||||
|
||||
@ -52,14 +52,14 @@ struct AttachmentPositioningSubtable : GlyphPositioningSubtable
|
||||
Offset markArrayOffset;
|
||||
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;
|
||||
};
|
||||
|
||||
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
|
||||
|
||||
@ -3641,4 +3641,9 @@ const le_uint8 CanonShaping::glyphDefinitionTable[] = {
|
||||
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
|
||||
|
||||
@ -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,
|
||||
LEUnicode *outChars, LEGlyphStorage &glyphStorage)
|
||||
{
|
||||
const GlyphDefinitionTableHeader *gdefTable = (const GlyphDefinitionTableHeader *) glyphDefinitionTable;
|
||||
const ClassDefinitionTable *classTable = gdefTable->getMarkAttachClassDefinitionTable();
|
||||
LEErrorCode success = LE_NO_ERROR;
|
||||
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 *indices = LE_NEW_ARRAY(le_int32, charCount);
|
||||
LEErrorCode status = LE_NO_ERROR;
|
||||
le_int32 i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -96,7 +96,7 @@ void CanonShaping::reorderMarks(const LEUnicode *inChars, le_int32 charCount, le
|
||||
le_int32 index = indices[i];
|
||||
|
||||
outChars[i] = inChars[index];
|
||||
glyphStorage.setCharIndex(out, index, status);
|
||||
glyphStorage.setCharIndex(out, index, success);
|
||||
}
|
||||
|
||||
LE_DELETE_ARRAY(indices);
|
||||
|
||||
@ -42,7 +42,9 @@ class U_LAYOUT_API CanonShaping /* not : public UObject because all members are
|
||||
{
|
||||
public:
|
||||
static const le_uint8 glyphSubstitutionTable[];
|
||||
static const size_t glyphSubstitutionTableLen;
|
||||
static const le_uint8 glyphDefinitionTable[];
|
||||
static const size_t glyphDefinitionTableLen;
|
||||
|
||||
static void reorderMarks(const LEUnicode *inChars, le_int32 charCount, le_bool rightToLeft,
|
||||
LEUnicode *outChars, LEGlyphStorage &glyphStorage);
|
||||
|
||||
@ -37,24 +37,51 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
le_int32 ClassDefinitionTable::getGlyphClass(LEGlyphID glyphID) const
|
||||
le_int32 ClassDefinitionTable::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
|
||||
{
|
||||
LEReferenceTo<ClassDefinitionTable> thisRef(base, success);
|
||||
if (LE_FAILURE(success)) return 0;
|
||||
|
||||
switch(SWAPW(classFormat)) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
{
|
||||
const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
|
||||
return f1Table->getGlyphClass(f1Table, glyphID, success);
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
|
||||
return f2Table->getGlyphClass(f2Table, glyphID, success);
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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)) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case 1:
|
||||
{
|
||||
const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this;
|
||||
|
||||
return f1Table->getGlyphClass(glyphID);
|
||||
const LEReferenceTo<ClassDefFormat1Table> f1Table(thisRef, success);
|
||||
return f1Table->hasGlyphClass(f1Table, glyphClass, success);
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this;
|
||||
|
||||
return f2Table->getGlyphClass(glyphID);
|
||||
const LEReferenceTo<ClassDefFormat2Table> f2Table(thisRef, success);
|
||||
return f2Table->hasGlyphClass(f2Table, glyphClass, success);
|
||||
}
|
||||
|
||||
default:
|
||||
@ -62,51 +89,32 @@ le_int32 ClassDefinitionTable::getGlyphClass(LEGlyphID glyphID) const
|
||||
}
|
||||
}
|
||||
|
||||
le_bool ClassDefinitionTable::hasGlyphClass(le_int32 glyphClass) const
|
||||
le_int32 ClassDefFormat1Table::getGlyphClass(const LETableReference& base, LEGlyphID glyphID, LEErrorCode &success) const
|
||||
{
|
||||
switch(SWAPW(classFormat)) {
|
||||
case 0:
|
||||
return 0;
|
||||
if(LE_FAILURE(success)) return 0;
|
||||
|
||||
case 1:
|
||||
{
|
||||
const ClassDefFormat1Table *f1Table = (const ClassDefFormat1Table *) this;
|
||||
|
||||
return f1Table->hasGlyphClass(glyphClass);
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
const ClassDefFormat2Table *f2Table = (const ClassDefFormat2Table *) this;
|
||||
|
||||
return f2Table->hasGlyphClass(glyphClass);
|
||||
}
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
le_int32 ClassDefFormat1Table::getGlyphClass(LEGlyphID glyphID) const
|
||||
{
|
||||
le_uint16 count = SWAPW(glyphCount);
|
||||
LEReferenceToArrayOf<le_uint16> classValueArrayRef(base, success, &classValueArray[0], count);
|
||||
TTGlyphID ttGlyphID = (TTGlyphID) LE_GET_GLYPH(glyphID);
|
||||
TTGlyphID firstGlyph = SWAPW(startGlyph);
|
||||
TTGlyphID lastGlyph = firstGlyph + SWAPW(glyphCount);
|
||||
TTGlyphID lastGlyph = firstGlyph + count;
|
||||
|
||||
if (ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
|
||||
return SWAPW(classValueArray[ttGlyphID - firstGlyph]);
|
||||
if (LE_SUCCESS(success) && ttGlyphID >= firstGlyph && ttGlyphID < lastGlyph) {
|
||||
return SWAPW( classValueArrayRef(ttGlyphID - firstGlyph, success) );
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < count; i += 1) {
|
||||
if (SWAPW(classValueArray[i]) == glyphClass) {
|
||||
for (i = 0; LE_SUCCESS(success)&& (i < count); i += 1) {
|
||||
if (SWAPW(classValueArrayRef(i,success)) == glyphClass) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@ -114,27 +122,31 @@ le_bool ClassDefFormat1Table::hasGlyphClass(le_int32 glyphClass) const
|
||||
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);
|
||||
le_uint16 rangeCount = SWAPW(classRangeCount);
|
||||
LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
|
||||
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 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);
|
||||
LEReferenceToArrayOf<GlyphRangeRecord> classRangeRecordArrayRef(base, success, &classRangeRecordArray[0], rangeCount);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < rangeCount; i += 1) {
|
||||
if (SWAPW(classRangeRecordArray[i].rangeValue) == glyphClass) {
|
||||
for (i = 0; i < rangeCount && LE_SUCCESS(success); i += 1) {
|
||||
if (SWAPW(classRangeRecordArrayRef(i,success).rangeValue) == glyphClass) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +46,20 @@ struct ClassDefinitionTable
|
||||
{
|
||||
le_uint16 classFormat;
|
||||
|
||||
le_int32 getGlyphClass(LEGlyphID glyphID) const;
|
||||
le_bool hasGlyphClass(le_int32 glyphClass) const;
|
||||
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
|
||||
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
|
||||
|
||||
le_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
|
||||
@ -56,9 +68,11 @@ struct ClassDefFormat1Table : ClassDefinitionTable
|
||||
le_uint16 glyphCount;
|
||||
le_uint16 classValueArray[ANY_NUMBER];
|
||||
|
||||
le_int32 getGlyphClass(LEGlyphID glyphID) const;
|
||||
le_bool hasGlyphClass(le_int32 glyphClass) const;
|
||||
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
|
||||
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ClassDefFormat1Table, classValueArray)
|
||||
|
||||
|
||||
struct ClassRangeRecord
|
||||
{
|
||||
@ -72,9 +86,10 @@ struct ClassDefFormat2Table : ClassDefinitionTable
|
||||
le_uint16 classRangeCount;
|
||||
GlyphRangeRecord classRangeRecordArray[ANY_NUMBER];
|
||||
|
||||
le_int32 getGlyphClass(LEGlyphID glyphID) const;
|
||||
le_bool hasGlyphClass(le_int32 glyphClass) const;
|
||||
le_int32 getGlyphClass(const LETableReference &base, LEGlyphID glyphID, LEErrorCode &success) const;
|
||||
le_bool hasGlyphClass(const LETableReference &base, le_int32 glyphClass, LEErrorCode &success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ClassDefFormat2Table, classRangeRecordArray)
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -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
|
||||
{
|
||||
};
|
||||
|
||||
struct ContextualGlyphInsertionHeader2 : MorphStateTableHeader2
|
||||
{
|
||||
le_uint32 insertionTableOffset;
|
||||
};
|
||||
|
||||
enum ContextualGlyphInsertionFlags
|
||||
{
|
||||
cgiSetMark = 0x8000,
|
||||
@ -61,11 +66,17 @@ enum ContextualGlyphInsertionFlags
|
||||
cgiMarkedInsertCountMask = 0x001F
|
||||
};
|
||||
|
||||
struct LigatureSubstitutionStateEntry : StateEntry
|
||||
struct ContextualGlyphInsertionStateEntry : StateEntry
|
||||
{
|
||||
ByteOffset currentInsertionListOffset;
|
||||
ByteOffset markedInsertionListOffset;
|
||||
};
|
||||
|
||||
struct ContextualGlyphInsertionStateEntry2 : StateEntry2
|
||||
{
|
||||
le_uint16 currentInsertionListIndex;
|
||||
le_uint16 markedInsertionListIndex;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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
|
||||
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(ContextualGlyphSubstitutionProcessor)
|
||||
|
||||
ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader)
|
||||
: StateTableProcessor(morphSubtableHeader)
|
||||
ContextualGlyphSubstitutionProcessor::ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success)
|
||||
: StateTableProcessor(morphSubtableHeader, success), entryTable(), contextualGlyphSubstitutionHeader(morphSubtableHeader, success)
|
||||
{
|
||||
contextualGlyphSubstitutionHeader = (const ContextualGlyphSubstitutionHeader *) morphSubtableHeader;
|
||||
substitutionTableOffset = SWAPW(contextualGlyphSubstitutionHeader->substitutionTableOffset);
|
||||
contextualGlyphSubstitutionHeader.orphan();
|
||||
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()
|
||||
@ -63,27 +68,26 @@ void ContextualGlyphSubstitutionProcessor::beginStateTable()
|
||||
|
||||
ByteOffset ContextualGlyphSubstitutionProcessor::processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex index)
|
||||
{
|
||||
const ContextualGlyphSubstitutionStateEntry *entry = &entryTable[index];
|
||||
ByteOffset newState = SWAPW(entry->newStateOffset);
|
||||
le_int16 flags = SWAPW(entry->flags);
|
||||
WordOffset markOffset = SWAPW(entry->markOffset);
|
||||
WordOffset currOffset = SWAPW(entry->currOffset);
|
||||
LEErrorCode success = LE_NO_ERROR;
|
||||
const ContextualGlyphSubstitutionStateEntry *entry = entryTable.getAlias(index, success);
|
||||
ByteOffset newState = SWAPW(entry->newStateOffset);
|
||||
le_int16 flags = SWAPW(entry->flags);
|
||||
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);
|
||||
LEGlyphID mGlyph = glyphStorage[markGlyph];
|
||||
TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(mGlyph)]);
|
||||
if (markOffset != 0 && LE_SUCCESS(success)) {
|
||||
LEGlyphID mGlyph = glyphStorage[markGlyph];
|
||||
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) {
|
||||
const le_int16 *table = (const le_int16 *) ((char *) &stateTableHeader->stHeader + currOffset * 2);
|
||||
LEGlyphID thisGlyph = glyphStorage[currGlyph];
|
||||
TTGlyphID newGlyph = SWAPW(table[LE_GET_GLYPH(thisGlyph)]);
|
||||
if (currOffset != 0) {
|
||||
LEGlyphID thisGlyph = glyphStorage[currGlyph];
|
||||
TTGlyphID newGlyph = SWAPW(int16Table.getObject(currOffset + LE_GET_GLYPH(thisGlyph), success)); // whew.
|
||||
|
||||
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
|
||||
}
|
||||
glyphStorage[currGlyph] = LE_SET_GLYPH(thisGlyph, newGlyph);
|
||||
}
|
||||
|
||||
if (flags & cgsSetMark) {
|
||||
markGlyph = currGlyph;
|
||||
|
||||
@ -56,7 +56,7 @@ public:
|
||||
|
||||
virtual void endStateTable();
|
||||
|
||||
ContextualGlyphSubstitutionProcessor(const MorphSubtableHeader *morphSubtableHeader);
|
||||
ContextualGlyphSubstitutionProcessor(const LEReferenceTo<MorphSubtableHeader> &morphSubtableHeader, LEErrorCode &success);
|
||||
virtual ~ContextualGlyphSubstitutionProcessor();
|
||||
|
||||
/**
|
||||
@ -78,11 +78,11 @@ private:
|
||||
|
||||
protected:
|
||||
ByteOffset substitutionTableOffset;
|
||||
const ContextualGlyphSubstitutionStateEntry *entryTable;
|
||||
|
||||
LEReferenceToArrayOf<ContextualGlyphSubstitutionStateEntry> entryTable;
|
||||
LEReferenceToArrayOf<le_int16> int16Table;
|
||||
le_int32 markGlyph;
|
||||
|
||||
const ContextualGlyphSubstitutionHeader *contextualGlyphSubstitutionHeader;
|
||||
LEReferenceTo<ContextualGlyphSubstitutionHeader> contextualGlyphSubstitutionHeader;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* 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
|
||||
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __CONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
|
||||
#define __CONTEXTUALGLYPHSUBSTITUTIONPROCESSOR2_H
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \internal
|
||||
*/
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "MorphTables.h"
|
||||
#include "SubtableProcessor2.h"
|
||||
#include "StateTableProcessor2.h"
|
||||
#include "ContextualGlyphSubstitution.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class LEGlyphStorage;
|
||||
|
||||
class ContextualGlyphSubstitutionProcessor2 : public StateTableProcessor2
|
||||
{
|
||||
public:
|
||||
virtual void beginStateTable();
|
||||
|
||||
virtual le_uint16 processStateEntry(LEGlyphStorage &glyphStorage, le_int32 &currGlyph, EntryTableIndex2 index, LEErrorCode &success);
|
||||
|
||||
virtual void endStateTable();
|
||||
|
||||
ContextualGlyphSubstitutionProcessor2(const LEReferenceTo<MorphSubtableHeader2> &morphSubtableHeader, LEErrorCode &success);
|
||||
virtual ~ContextualGlyphSubstitutionProcessor2();
|
||||
|
||||
/**
|
||||
* 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:
|
||||
ContextualGlyphSubstitutionProcessor2();
|
||||
TTGlyphID lookup(le_uint32 offset, LEGlyphID gid, LEErrorCode &success);
|
||||
|
||||
protected:
|
||||
LEReferenceToArrayOf<le_uint32> perGlyphTable;
|
||||
LEReferenceToArrayOf<ContextualGlyphStateEntry2> entryTable;
|
||||
|
||||
le_int16 perGlyphTableFormat;
|
||||
le_int32 markGlyph;
|
||||
|
||||
LEReferenceTo<ContextualGlyphHeader2> contextualGlyphHeader;
|
||||
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
@ -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
|
||||
ByteOffset substitutionTableOffset;
|
||||
};
|
||||
|
||||
struct ContextualGlyphHeader2 : MorphStateTableHeader2
|
||||
{
|
||||
le_uint32 perGlyphTableOffset; // no more substitution tables
|
||||
};
|
||||
|
||||
enum ContextualGlyphSubstitutionFlags
|
||||
{
|
||||
cgsSetMark = 0x8000,
|
||||
@ -62,5 +67,11 @@ struct ContextualGlyphSubstitutionStateEntry : StateEntry
|
||||
WordOffset currOffset;
|
||||
};
|
||||
|
||||
struct ContextualGlyphStateEntry2 : StateEntry2
|
||||
{
|
||||
le_uint16 markIndex;
|
||||
le_uint16 currIndex;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -217,7 +217,7 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LookupProcessor *
|
||||
}
|
||||
|
||||
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
|
||||
le_int32 coverageIndex = getGlyphCoverage(glyph);
|
||||
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
|
||||
|
||||
if (coverageIndex >= 0) {
|
||||
le_uint16 srSetCount = SWAPW(subRuleSetCount);
|
||||
@ -266,7 +266,7 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LookupProcessor *
|
||||
}
|
||||
|
||||
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
|
||||
le_int32 coverageIndex = getGlyphCoverage(glyph);
|
||||
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
|
||||
|
||||
if (coverageIndex >= 0) {
|
||||
const ClassDefinitionTable *classDefinitionTable =
|
||||
@ -394,7 +394,7 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LookupPro
|
||||
}
|
||||
|
||||
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
|
||||
le_int32 coverageIndex = getGlyphCoverage(glyph);
|
||||
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
|
||||
|
||||
if (coverageIndex >= 0) {
|
||||
le_uint16 srSetCount = SWAPW(chainSubRuleSetCount);
|
||||
@ -465,7 +465,7 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LookupPro
|
||||
}
|
||||
|
||||
LEGlyphID glyph = glyphIterator->getCurrGlyphID();
|
||||
le_int32 coverageIndex = getGlyphCoverage(glyph);
|
||||
le_int32 coverageIndex = getGlyphCoverage(lookupProcessor->getReference(), glyph, success);
|
||||
|
||||
if (coverageIndex >= 0) {
|
||||
const ClassDefinitionTable *backtrackClassDefinitionTable =
|
||||
|
||||
@ -43,6 +43,7 @@
|
||||
#include "GlyphSubstitutionTables.h"
|
||||
#include "GlyphIterator.h"
|
||||
#include "LookupProcessor.h"
|
||||
#include "LETableReference.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
@ -88,6 +89,8 @@ struct ContextualSubstitutionFormat1Subtable : ContextualSubstitutionSubtable
|
||||
|
||||
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ContextualSubstitutionFormat1Subtable, subRuleSetTableOffsetArray)
|
||||
|
||||
|
||||
struct SubRuleSetTable
|
||||
{
|
||||
@ -95,6 +98,7 @@ struct SubRuleSetTable
|
||||
Offset subRuleTableOffsetArray[ANY_NUMBER];
|
||||
|
||||
};
|
||||
LE_VAR_ARRAY(SubRuleSetTable, subRuleTableOffsetArray)
|
||||
|
||||
// NOTE: Multiple variable size arrays!!
|
||||
struct SubRuleTable
|
||||
@ -104,6 +108,7 @@ struct SubRuleTable
|
||||
TTGlyphID inputGlyphArray[ANY_NUMBER];
|
||||
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(SubRuleTable, inputGlyphArray)
|
||||
|
||||
struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable
|
||||
{
|
||||
@ -113,12 +118,16 @@ struct ContextualSubstitutionFormat2Subtable : ContextualSubstitutionSubtable
|
||||
|
||||
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ContextualSubstitutionFormat2Subtable, subClassSetTableOffsetArray)
|
||||
|
||||
|
||||
struct SubClassSetTable
|
||||
{
|
||||
le_uint16 subClassRuleCount;
|
||||
Offset subClassRuleTableOffsetArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(SubClassSetTable, subClassRuleTableOffsetArray)
|
||||
|
||||
|
||||
// NOTE: Multiple variable size arrays!!
|
||||
struct SubClassRuleTable
|
||||
@ -128,6 +137,8 @@ struct SubClassRuleTable
|
||||
le_uint16 classArray[ANY_NUMBER];
|
||||
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(SubClassRuleTable, classArray)
|
||||
|
||||
|
||||
// NOTE: This isn't a subclass of GlyphSubstitutionSubtable 'cause
|
||||
// it has an array of coverage tables instead of a single coverage table...
|
||||
@ -143,6 +154,7 @@ struct ContextualSubstitutionFormat3Subtable
|
||||
|
||||
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ContextualSubstitutionFormat3Subtable, coverageTableOffsetArray)
|
||||
|
||||
struct ChainingContextualSubstitutionSubtable : ContextualSubstitutionBase
|
||||
{
|
||||
@ -156,6 +168,8 @@ struct ChainingContextualSubstitutionFormat1Subtable : ChainingContextualSubstit
|
||||
|
||||
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat1Subtable, chainSubRuleSetTableOffsetArray)
|
||||
|
||||
|
||||
struct ChainSubRuleSetTable
|
||||
{
|
||||
@ -163,6 +177,7 @@ struct ChainSubRuleSetTable
|
||||
Offset chainSubRuleTableOffsetArray[ANY_NUMBER];
|
||||
|
||||
};
|
||||
LE_VAR_ARRAY(ChainSubRuleSetTable, chainSubRuleTableOffsetArray)
|
||||
|
||||
// NOTE: Multiple variable size arrays!!
|
||||
struct ChainSubRuleTable
|
||||
@ -176,6 +191,7 @@ struct ChainSubRuleTable
|
||||
//le_uint16 substCount;
|
||||
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(ChainSubRuleTable, backtrackGlyphArray)
|
||||
|
||||
struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstitutionSubtable
|
||||
{
|
||||
@ -187,12 +203,15 @@ struct ChainingContextualSubstitutionFormat2Subtable : ChainingContextualSubstit
|
||||
|
||||
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat2Subtable, chainSubClassSetTableOffsetArray)
|
||||
|
||||
struct ChainSubClassSetTable
|
||||
{
|
||||
le_uint16 chainSubClassRuleCount;
|
||||
Offset chainSubClassRuleTableOffsetArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(ChainSubClassSetTable, chainSubClassRuleTableOffsetArray)
|
||||
|
||||
|
||||
// NOTE: Multiple variable size arrays!!
|
||||
struct ChainSubClassRuleTable
|
||||
@ -206,6 +225,7 @@ struct ChainSubClassRuleTable
|
||||
//le_uint16 substCount;
|
||||
//SubstitutionLookupRecord substLookupRecordArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(ChainSubClassRuleTable, backtrackClassArray)
|
||||
|
||||
// NOTE: This isn't a subclass of GlyphSubstitutionSubtable 'cause
|
||||
// it has arrays of coverage tables instead of a single coverage table...
|
||||
@ -225,6 +245,8 @@ struct ChainingContextualSubstitutionFormat3Subtable
|
||||
|
||||
le_uint32 process(const LookupProcessor *lookupProcessor, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(ChainingContextualSubstitutionFormat3Subtable, backtrackCoverageTableOffsetArray)
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -56,6 +56,8 @@ struct CoverageFormat1Table : CoverageTable
|
||||
|
||||
le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
|
||||
};
|
||||
LE_VAR_ARRAY(CoverageFormat1Table, glyphArray)
|
||||
|
||||
|
||||
struct CoverageFormat2Table : CoverageTable
|
||||
{
|
||||
@ -64,6 +66,7 @@ struct CoverageFormat2Table : CoverageTable
|
||||
|
||||
le_int32 getGlyphCoverage(LEGlyphID glyphID) const;
|
||||
};
|
||||
LE_VAR_ARRAY(CoverageFormat2Table, rangeRecordArray)
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -39,10 +39,10 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const
|
||||
le_uint32 CursiveAttachmentSubtable::process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const
|
||||
{
|
||||
LEGlyphID glyphID = glyphIterator->getCurrGlyphID();
|
||||
le_int32 coverageIndex = getGlyphCoverage(glyphID);
|
||||
le_int32 coverageIndex = getGlyphCoverage(base, glyphID, success);
|
||||
le_uint16 eeCount = SWAPW(entryExitCount);
|
||||
|
||||
if (coverageIndex < 0 || coverageIndex >= eeCount) {
|
||||
@ -51,7 +51,7 @@ le_uint32 CursiveAttachmentSubtable::process(GlyphIterator *glyphIterator, const
|
||||
}
|
||||
|
||||
LEPoint entryAnchor, exitAnchor;
|
||||
Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor);
|
||||
Offset entryOffset = SWAPW(entryExitRecords[coverageIndex].entryAnchor); // TODO
|
||||
Offset exitOffset = SWAPW(entryExitRecords[coverageIndex].exitAnchor);
|
||||
|
||||
if (entryOffset != 0) {
|
||||
|
||||
@ -57,8 +57,9 @@ struct CursiveAttachmentSubtable : GlyphPositioningSubtable
|
||||
le_uint16 entryExitCount;
|
||||
EntryExitRecord entryExitRecords[ANY_NUMBER];
|
||||
|
||||
le_uint32 process(GlyphIterator *glyphIterator, const LEFontInstance *fontInstance) const;
|
||||
le_uint32 process(const LEReferenceTo<CursiveAttachmentSubtable> &base, GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode &success) const;
|
||||
};
|
||||
LE_VAR_ARRAY(CursiveAttachmentSubtable, entryExitRecords)
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -57,6 +57,7 @@ private:
|
||||
static const le_uint16 fieldSignBits[];
|
||||
static const le_uint16 fieldBits[];
|
||||
};
|
||||
LE_VAR_ARRAY(DeviceTable, deltaValues)
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
|
||||
@ -47,6 +47,8 @@ U_NAMESPACE_BEGIN
|
||||
le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_uint16 lookupType,
|
||||
GlyphIterator *glyphIterator, const LEFontInstance *fontInstance, LEErrorCode& success) const
|
||||
{
|
||||
const LEReferenceTo<ExtensionSubtable> thisRef(lookupProcessor->getReference(), success); // create a reference to this
|
||||
|
||||
if (LE_FAILURE(success)) {
|
||||
return 0;
|
||||
}
|
||||
@ -55,9 +57,11 @@ le_uint32 ExtensionSubtable::process(const LookupProcessor *lookupProcessor, le_
|
||||
|
||||
if (elt != lookupType) {
|
||||
le_uint32 extOffset = READ_LONG(extensionOffset);
|
||||
LookupSubtable *subtable = (LookupSubtable *) ((char *) this + extOffset);
|
||||
LEReferenceTo<LookupSubtable> subtable(thisRef, success, extOffset);
|
||||
|
||||
return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success);
|
||||
if(LE_SUCCESS(success)) {
|
||||
return lookupProcessor->applySubtable(subtable, elt, glyphIterator, fontInstance, success);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -38,19 +38,20 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
const FeatureTable *FeatureListTable::getFeatureTable(le_uint16 featureIndex, LETag *featureTag) const
|
||||
LEReferenceTo<FeatureTable> FeatureListTable::getFeatureTable(const LETableReference &base, le_uint16 featureIndex, LETag *featureTag, LEErrorCode &success) const
|
||||
{
|
||||
if (featureIndex >= SWAPW(featureCount)) {
|
||||
return 0;
|
||||
}
|
||||
if (featureIndex >= SWAPW(featureCount) || LE_FAILURE(success)) {
|
||||
return LEReferenceTo<FeatureTable>();
|
||||
}
|
||||
|
||||
Offset featureTableOffset = featureRecordArray[featureIndex].featureTableOffset;
|
||||
|
||||
*featureTag = SWAPT(featureRecordArray[featureIndex].featureTag);
|
||||
|
||||
return (const FeatureTable *) ((char *) this + SWAPW(featureTableOffset));
|
||||
return LEReferenceTo<FeatureTable>(base, success, SWAPW(featureTableOffset));
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Note: according to the OpenType Spec. v 1.4, the entries in the Feature
|
||||
* List Table are sorted alphabetically by feature tag; however, there seem
|
||||
@ -82,5 +83,6 @@ const FeatureTable *FeatureListTable::getFeatureTable(LETag featureTag) const
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
@ -36,9 +36,12 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
GDEFMarkFilter::GDEFMarkFilter(const GlyphDefinitionTableHeader *gdefTable)
|
||||
GDEFMarkFilter::GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success)
|
||||
: classDefTable(gdefTable->getGlyphClassDefinitionTable(gdefTable, success))
|
||||
{
|
||||
classDefTable = gdefTable->getGlyphClassDefinitionTable();
|
||||
if(!classDefTable.isValid()) {
|
||||
success = LE_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
GDEFMarkFilter::~GDEFMarkFilter()
|
||||
|
||||
@ -46,13 +46,13 @@ U_NAMESPACE_BEGIN
|
||||
class GDEFMarkFilter : public UMemory, public LEGlyphFilter
|
||||
{
|
||||
private:
|
||||
const GlyphClassDefinitionTable *classDefTable;
|
||||
const LEReferenceTo<GlyphClassDefinitionTable> classDefTable;
|
||||
|
||||
GDEFMarkFilter(const GDEFMarkFilter &other); // forbid copying of this class
|
||||
GDEFMarkFilter &operator=(const GDEFMarkFilter &other); // forbid copying of this class
|
||||
|
||||
public:
|
||||
GDEFMarkFilter(const GlyphDefinitionTableHeader *gdefTable);
|
||||
GDEFMarkFilter(const LEReferenceTo<GlyphDefinitionTableHeader> &gdefTable, LEErrorCode &success);
|
||||
virtual ~GDEFMarkFilter();
|
||||
|
||||
virtual le_bool accept(LEGlyphID glyph) const;
|
||||
|
||||
@ -41,9 +41,10 @@ U_NAMESPACE_BEGIN
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine)
|
||||
|
||||
GXLayoutEngine::GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader *morphTable, LEErrorCode &success)
|
||||
GXLayoutEngine::GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader> &morphTable, LEErrorCode &success)
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode, 0, success), fMorphTable(morphTable)
|
||||
{
|
||||
fMorphTable.orphan();
|
||||
// nothing else to do?
|
||||
}
|
||||
|
||||
@ -70,7 +71,7 @@ le_int32 GXLayoutEngine::computeGlyphs(const LEUnicode chars[], le_int32 offset,
|
||||
return 0;
|
||||
}
|
||||
|
||||
fMorphTable->process(glyphStorage);
|
||||
fMorphTable->process(fMorphTable, glyphStorage, success);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -74,7 +74,7 @@ public:
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const MorphTableHeader *morphTable, LEErrorCode &success);
|
||||
GXLayoutEngine(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader> &morphTable, LEErrorCode &success);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
@ -104,7 +104,7 @@ protected:
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const MorphTableHeader *fMorphTable;
|
||||
LEReferenceTo<MorphTableHeader> fMorphTable;
|
||||
|
||||
/**
|
||||
* This method does GX layout using the font's 'mort' table. It converts the
|
||||
|
||||
91
jdk/src/share/native/sun/font/layout/GXLayoutEngine2.cpp
Normal file
91
jdk/src/share/native/sun/font/layout/GXLayoutEngine2.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 "LayoutEngine.h"
|
||||
#include "GXLayoutEngine2.h"
|
||||
#include "LEGlyphStorage.h"
|
||||
#include "MorphTables.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(GXLayoutEngine2)
|
||||
|
||||
GXLayoutEngine2::GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader2> &morphTable, le_int32 typoFlags, LEErrorCode &success)
|
||||
: LayoutEngine(fontInstance, scriptCode, languageCode, typoFlags, success), fMorphTable(morphTable)
|
||||
{
|
||||
// nothing else to do?
|
||||
}
|
||||
|
||||
GXLayoutEngine2::~GXLayoutEngine2()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
// apply 'morx' table
|
||||
le_int32 GXLayoutEngine2::computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft, LEGlyphStorage &glyphStorage, LEErrorCode &success)
|
||||
{
|
||||
if (LE_FAILURE(success)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (chars == NULL || offset < 0 || count < 0 || max < 0 || offset >= max || offset + count > max) {
|
||||
success = LE_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mapCharsToGlyphs(chars, offset, count, rightToLeft, rightToLeft, glyphStorage, success);
|
||||
|
||||
if (LE_FAILURE(success)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
fMorphTable->process(fMorphTable, glyphStorage, fTypoFlags, success);
|
||||
return count;
|
||||
}
|
||||
|
||||
// apply positional tables
|
||||
void GXLayoutEngine2::adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool /*reverse*/,
|
||||
LEGlyphStorage &/*glyphStorage*/, LEErrorCode &success)
|
||||
{
|
||||
if (LE_FAILURE(success)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chars == NULL || offset < 0 || count < 0) {
|
||||
success = LE_ILLEGAL_ARGUMENT_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME: no positional processing yet...
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
149
jdk/src/share/native/sun/font/layout/GXLayoutEngine2.h
Normal file
149
jdk/src/share/native/sun/font/layout/GXLayoutEngine2.h
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GXLAYOUTENGINE2_H
|
||||
#define __GXLAYOUTENGINE2_H
|
||||
|
||||
#include "LETypes.h"
|
||||
#include "LayoutEngine.h"
|
||||
|
||||
#include "MorphTables.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class LEFontInstance;
|
||||
class LEGlyphStorage;
|
||||
|
||||
/**
|
||||
* This class implements layout for QuickDraw GX or Apple Advanced Typograyph (AAT)
|
||||
* fonts. A font is a GX or AAT font if it contains a 'mort' table. See Apple's
|
||||
* TrueType Reference Manual (http://fonts.apple.com/TTRefMan/index.html) for details.
|
||||
* Information about 'mort' tables is in the chapter titled "Font Files."
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class GXLayoutEngine2 : public LayoutEngine
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This is the main constructor. It constructs an instance of GXLayoutEngine for
|
||||
* a particular font, script and language. It takes the 'mort' table as a parameter since
|
||||
* LayoutEngine::layoutEngineFactory has to read the 'mort' table to know that it has a
|
||||
* GX font.
|
||||
*
|
||||
* Note: GX and AAT fonts don't contain any script and language specific tables, so
|
||||
* the script and language are ignored.
|
||||
*
|
||||
* @param fontInstance - the font
|
||||
* @param scriptCode - the script
|
||||
* @param langaugeCode - the language
|
||||
* @param morphTable - the 'mort' table
|
||||
* @param success - set to an error code if the operation fails
|
||||
*
|
||||
* @see LayoutEngine::layoutEngineFactory
|
||||
* @see ScriptAndLangaugeTags.h for script and language codes
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
GXLayoutEngine2(const LEFontInstance *fontInstance, le_int32 scriptCode, le_int32 languageCode, const LEReferenceTo<MorphTableHeader2> &morphTable, le_int32 typoFlags, LEErrorCode &success);
|
||||
|
||||
/**
|
||||
* The destructor, virtual for correct polymorphic invocation.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
virtual ~GXLayoutEngine2();
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The address of the 'mort' table
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
const LEReferenceTo<MorphTableHeader2> fMorphTable;
|
||||
|
||||
/**
|
||||
* This method does GX layout using the font's 'mort' table. It converts the
|
||||
* input character codes to glyph indices using mapCharsToGlyphs, and then
|
||||
* applies the 'mort' table.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param chars - the input character context
|
||||
* @param offset - the index of the first character to process
|
||||
* @param count - the number of characters to process
|
||||
* @param max - the number of characters in the input context
|
||||
* @param rightToLeft - <code>TRUE</code> if the text is in a right to left directional run
|
||||
* @param glyphStorage - the glyph storage object. The glyph and char index arrays will be set.
|
||||
*
|
||||
* Output parameters:
|
||||
* @param success - set to an error code if the operation fails
|
||||
*
|
||||
* @return the number of glyphs in the glyph index array
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
virtual le_int32 computeGlyphs(const LEUnicode chars[], le_int32 offset, le_int32 count, le_int32 max, le_bool rightToLeft,
|
||||
LEGlyphStorage &glyphStorage, LEErrorCode &success);
|
||||
|
||||
/**
|
||||
* This method adjusts the glyph positions using the font's
|
||||
* 'kern', 'trak', 'bsln', 'opbd' and 'just' tables.
|
||||
*
|
||||
* Input parameters:
|
||||
* @param glyphStorage - the object holding the glyph storage. The positions will be updated as needed.
|
||||
*
|
||||
* Output parameters:
|
||||
* @param success - set to an error code if the operation fails
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
virtual void adjustGlyphPositions(const LEUnicode chars[], le_int32 offset, le_int32 count, le_bool reverse,
|
||||
LEGlyphStorage &glyphStorage, LEErrorCode &success);
|
||||
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
#endif
|
||||
@ -36,24 +36,36 @@
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
const GlyphClassDefinitionTable *GlyphDefinitionTableHeader::getGlyphClassDefinitionTable() const
|
||||
const LEReferenceTo<GlyphClassDefinitionTable>
|
||||
GlyphDefinitionTableHeader::getGlyphClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const
|
||||
{
|
||||
return (const GlyphClassDefinitionTable *) ((char *) this + SWAPW(glyphClassDefOffset));
|
||||
if(LE_FAILURE(success)) return LEReferenceTo<GlyphClassDefinitionTable>();
|
||||
return LEReferenceTo<GlyphClassDefinitionTable>(base, success, SWAPW(glyphClassDefOffset));
|
||||
}
|
||||
|
||||
const AttachmentListTable *GlyphDefinitionTableHeader::getAttachmentListTable() const
|
||||
const LEReferenceTo<AttachmentListTable>
|
||||
GlyphDefinitionTableHeader::getAttachmentListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const
|
||||
{
|
||||
return (const AttachmentListTable *) ((char *) this + SWAPW(attachListOffset));
|
||||
if(LE_FAILURE(success)) return LEReferenceTo<AttachmentListTable>();
|
||||
return LEReferenceTo<AttachmentListTable>(base, success, SWAPW(attachListOffset));
|
||||
}
|
||||
|
||||
const LigatureCaretListTable *GlyphDefinitionTableHeader::getLigatureCaretListTable() const
|
||||
const LEReferenceTo<LigatureCaretListTable>
|
||||
GlyphDefinitionTableHeader::getLigatureCaretListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const
|
||||
{
|
||||
return (const LigatureCaretListTable *) ((char *) this + SWAPW(ligCaretListOffset));
|
||||
if(LE_FAILURE(success)) return LEReferenceTo<LigatureCaretListTable>();
|
||||
return LEReferenceTo<LigatureCaretListTable>(base, success, SWAPW(ligCaretListOffset));
|
||||
}
|
||||
|
||||
const MarkAttachClassDefinitionTable *GlyphDefinitionTableHeader::getMarkAttachClassDefinitionTable() const
|
||||
const LEReferenceTo<MarkAttachClassDefinitionTable>
|
||||
GlyphDefinitionTableHeader::getMarkAttachClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const
|
||||
{
|
||||
return (const MarkAttachClassDefinitionTable *) ((char *) this + SWAPW(MarkAttachClassDefOffset));
|
||||
if(LE_FAILURE(success)) return LEReferenceTo<MarkAttachClassDefinitionTable>();
|
||||
return LEReferenceTo<MarkAttachClassDefinitionTable>(base, success, SWAPW(MarkAttachClassDefOffset));
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
@ -60,12 +60,14 @@ struct AttachmentListTable
|
||||
le_uint16 glyphCount;
|
||||
Offset attachPointTableOffsetArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(AttachmentListTable, attachPointTableOffsetArray)
|
||||
|
||||
struct AttachPointTable
|
||||
{
|
||||
le_uint16 pointCount;
|
||||
le_uint16 pointIndexArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(AttachPointTable, pointIndexArray)
|
||||
|
||||
struct LigatureCaretListTable
|
||||
{
|
||||
@ -73,12 +75,14 @@ struct LigatureCaretListTable
|
||||
le_uint16 ligGlyphCount;
|
||||
Offset ligGlyphTableOffsetArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(LigatureCaretListTable, ligGlyphTableOffsetArray)
|
||||
|
||||
struct LigatureGlyphTable
|
||||
{
|
||||
le_uint16 caretCount;
|
||||
Offset caretValueTableOffsetArray[ANY_NUMBER];
|
||||
};
|
||||
LE_VAR_ARRAY(LigatureGlyphTable, caretValueTableOffsetArray)
|
||||
|
||||
struct CaretValueTable
|
||||
{
|
||||
@ -111,10 +115,18 @@ struct GlyphDefinitionTableHeader
|
||||
Offset ligCaretListOffset;
|
||||
Offset MarkAttachClassDefOffset;
|
||||
|
||||
const GlyphClassDefinitionTable *getGlyphClassDefinitionTable() const;
|
||||
const AttachmentListTable *getAttachmentListTable()const ;
|
||||
const LigatureCaretListTable *getLigatureCaretListTable() const;
|
||||
const MarkAttachClassDefinitionTable *getMarkAttachClassDefinitionTable() const;
|
||||
const LEReferenceTo<GlyphClassDefinitionTable>
|
||||
getGlyphClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const;
|
||||
const LEReferenceTo<AttachmentListTable>
|
||||
getAttachmentListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success)const ;
|
||||
const LEReferenceTo<LigatureCaretListTable>
|
||||
getLigatureCaretListTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const;
|
||||
const LEReferenceTo<MarkAttachClassDefinitionTable>
|
||||
getMarkAttachClassDefinitionTable(const LEReferenceTo<GlyphDefinitionTableHeader>& base,
|
||||
LEErrorCode &success) const;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
@ -41,18 +41,21 @@
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
GlyphIterator::GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
|
||||
FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader)
|
||||
FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader)
|
||||
: direction(1), position(-1), nextLimit(-1), prevLimit(-1),
|
||||
glyphStorage(theGlyphStorage), glyphPositionAdjustments(theGlyphPositionAdjustments),
|
||||
srcIndex(-1), destIndex(-1), lookupFlags(theLookupFlags), featureMask(theFeatureMask), glyphGroup(0),
|
||||
glyphClassDefinitionTable(NULL), markAttachClassDefinitionTable(NULL)
|
||||
glyphClassDefinitionTable(), markAttachClassDefinitionTable()
|
||||
|
||||
{
|
||||
LEErrorCode success = LE_NO_ERROR; // TODO
|
||||
le_int32 glyphCount = glyphStorage.getGlyphCount();
|
||||
|
||||
if (theGlyphDefinitionTableHeader != NULL) {
|
||||
glyphClassDefinitionTable = theGlyphDefinitionTableHeader->getGlyphClassDefinitionTable();
|
||||
markAttachClassDefinitionTable = theGlyphDefinitionTableHeader->getMarkAttachClassDefinitionTable();
|
||||
if (theGlyphDefinitionTableHeader.isValid()) {
|
||||
glyphClassDefinitionTable = theGlyphDefinitionTableHeader
|
||||
-> getGlyphClassDefinitionTable(theGlyphDefinitionTableHeader, success);
|
||||
markAttachClassDefinitionTable = theGlyphDefinitionTableHeader
|
||||
->getMarkAttachClassDefinitionTable(theGlyphDefinitionTableHeader, success);
|
||||
}
|
||||
|
||||
nextLimit = glyphCount;
|
||||
@ -380,6 +383,7 @@ void GlyphIterator::setCursiveGlyph()
|
||||
|
||||
le_bool GlyphIterator::filterGlyph(le_uint32 index) const
|
||||
{
|
||||
LEErrorCode success = LE_NO_ERROR;
|
||||
LEGlyphID glyphID = glyphStorage[index];
|
||||
le_int32 glyphClass = gcdNoGlyphClass;
|
||||
|
||||
@ -387,8 +391,8 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index) const
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (glyphClassDefinitionTable != NULL) {
|
||||
glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphID);
|
||||
if (glyphClassDefinitionTable.isValid()) {
|
||||
glyphClass = glyphClassDefinitionTable->getGlyphClass(glyphClassDefinitionTable, glyphID, success);
|
||||
}
|
||||
|
||||
switch (glyphClass)
|
||||
@ -410,8 +414,9 @@ le_bool GlyphIterator::filterGlyph(le_uint32 index) const
|
||||
|
||||
le_uint16 markAttachType = (lookupFlags & lfMarkAttachTypeMask) >> lfMarkAttachTypeShift;
|
||||
|
||||
if ((markAttachType != 0) && (markAttachClassDefinitionTable != NULL)) {
|
||||
return markAttachClassDefinitionTable->getGlyphClass(glyphID) != markAttachType;
|
||||
if ((markAttachType != 0) && (markAttachClassDefinitionTable.isValid())) {
|
||||
return markAttachClassDefinitionTable
|
||||
-> getGlyphClass(markAttachClassDefinitionTable, glyphID, success) != markAttachType;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
@ -461,6 +466,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
|
||||
while (newPosition != nextLimit && delta > 0) {
|
||||
do {
|
||||
newPosition += direction;
|
||||
//fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
|
||||
} while (newPosition != nextLimit && filterGlyph(newPosition));
|
||||
|
||||
delta -= 1;
|
||||
@ -468,6 +474,7 @@ le_bool GlyphIterator::nextInternal(le_uint32 delta)
|
||||
|
||||
position = newPosition;
|
||||
|
||||
//fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
|
||||
return position != nextLimit;
|
||||
}
|
||||
|
||||
@ -483,6 +490,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
|
||||
while (newPosition != prevLimit && delta > 0) {
|
||||
do {
|
||||
newPosition -= direction;
|
||||
//fprintf(stderr,"%s:%d:%s: newPosition = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, newPosition, delta);
|
||||
} while (newPosition != prevLimit && filterGlyph(newPosition));
|
||||
|
||||
delta -= 1;
|
||||
@ -490,6 +498,7 @@ le_bool GlyphIterator::prevInternal(le_uint32 delta)
|
||||
|
||||
position = newPosition;
|
||||
|
||||
//fprintf(stderr,"%s:%d:%s: exit position = %d, delta = %d\n", __FILE__, __LINE__, __FUNCTION__, position, delta);
|
||||
return position != prevLimit;
|
||||
}
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ class GlyphPositionAdjustments;
|
||||
class GlyphIterator : public UMemory {
|
||||
public:
|
||||
GlyphIterator(LEGlyphStorage &theGlyphStorage, GlyphPositionAdjustments *theGlyphPositionAdjustments, le_bool rightToLeft, le_uint16 theLookupFlags,
|
||||
FeatureMask theFeatureMask, const GlyphDefinitionTableHeader *theGlyphDefinitionTableHeader);
|
||||
FeatureMask theFeatureMask, const LEReferenceTo<GlyphDefinitionTableHeader> &theGlyphDefinitionTableHeader);
|
||||
|
||||
GlyphIterator(GlyphIterator &that);
|
||||
|
||||
@ -117,8 +117,8 @@ private:
|
||||
FeatureMask featureMask;
|
||||
le_int32 glyphGroup;
|
||||
|
||||
const GlyphClassDefinitionTable *glyphClassDefinitionTable;
|
||||
const MarkAttachClassDefinitionTable *markAttachClassDefinitionTable;
|
||||
LEReferenceTo<GlyphClassDefinitionTable> glyphClassDefinitionTable;
|
||||
LEReferenceTo<MarkAttachClassDefinitionTable> markAttachClassDefinitionTable;
|
||||
|
||||
GlyphIterator &operator=(const GlyphIterator &other); // forbid copying of this class
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user