From: <ha...@us...> - 2011-02-16 14:51:10
|
Revision: 15173 http://jmol.svn.sourceforge.net/jmol/?rev=15173&view=rev Author: hansonr Date: 2011-02-16 14:51:03 +0000 (Wed, 16 Feb 2011) Log Message: ----------- version=12.1.36_dev # code: JPEG encoder stores state in APP1 (FFE1) tag set instead of comment field # bug fix: Molden reader nonfunctional # bug fix: Spartan reader fails when no MO calculation # bug fix: Spartan MO d6/f10 reader problems # bug fix: QuantumEspresso reader first-model not read as Cartesian coordinates Modified Paths: -------------- trunk/Jmol/src/org/jmol/script/ScriptCompiler.java trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java trunk/Jmol/src/org/jmol/util/JpegEncoder.java trunk/Jmol/src/org/jmol/viewer/Jmol.properties Modified: trunk/Jmol/src/org/jmol/script/ScriptCompiler.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptCompiler.java 2011-02-16 14:49:43 UTC (rev 15172) +++ trunk/Jmol/src/org/jmol/script/ScriptCompiler.java 2011-02-16 14:51:03 UTC (rev 15173) @@ -25,6 +25,7 @@ import org.jmol.util.Escape; import org.jmol.util.CommandHistory; +import org.jmol.util.JpegEncoder; import org.jmol.util.Logger; import org.jmol.util.Parser; import org.jmol.viewer.JmolConstants; @@ -213,7 +214,12 @@ int pt2 = script.indexOf((script.charAt(pt1 + 2) == '*' ? "*" : "") + "*/", pt); if (pt1 >= 0 && pt2 >= pt) - script = script.substring(pt + JmolConstants.EMBEDDED_SCRIPT_TAG.length(), pt2) + "\n"; + script = script.substring( + pt + JmolConstants.EMBEDDED_SCRIPT_TAG.length(), pt2) + + "\n"; + while ((pt1 = script.indexOf(JpegEncoder.CONTINUE_STRING)) >= 0) + script = script.substring(0, pt1) + + script.substring(pt1 + JpegEncoder.CONTINUE_STRING.length() + 4); if (Logger.debugging) Logger.info(script); return script; @@ -488,6 +494,7 @@ } private boolean isShowCommand; + private boolean inlineLoad; private int lookingAtComment() { char ch = script.charAt(ichToken); @@ -857,9 +864,11 @@ boolean isAndEquals = ("+-\\*/&|=".indexOf(ch) >= 0); char ch2 = (ichToken + 1 >= cchScript ? 0 : script.charAt(ichToken + 1)); if (Token.tokAttr(tokCommand, Token.setparam) && ch == '=' - || (isNewSet || isSetBrace) && (isAndEquals || ch == '.' || ch == '[')) { + || (isNewSet || isSetBrace) + && (isAndEquals || ch == '.' || ch == '[')) { setCommand(isAndEquals ? Token.tokenSet - : ch == '[' && !isSetBrace ? Token.tokenSetArray : Token.tokenSetProperty); + : ch == '[' && !isSetBrace ? Token.tokenSetArray + : Token.tokenSetProperty); ltoken.add(0, tokenCommand); cchToken = 1; switch (ch) { @@ -889,26 +898,30 @@ } } } - + // cd, echo, gotocmd, help, hover, javascript, label, message, and pause // all are implicitly strings. You CAN use "..." but you don't have to, // and you cannot use '...'. This way the introduction of single quotes // as an equivalent of double quotes cannot break existing scripts. -- BH 06/2009 - + if (lookingAtString(!Token.tokAttr(tokCommand, Token.implicitStringCommand))) { if (cchToken < 0) return ERROR(ERROR_endOfCommandUnexpected); String str; if ((tokCommand == Token.load || tokCommand == Token.background || tokCommand == Token.script) && !iHaveQuotedString) { - str = script.substring(ichToken + 1, ichToken + cchToken - 1); - if (str.indexOf("\\u") >= 0) - str = Escape.unescapeUnicode(str); + if (inlineLoad) { + str = getUnescapedStringLiteral(); + } else { + str = script.substring(ichToken + 1, ichToken + cchToken - 1); + if (str.indexOf("\\u") >= 0) + str = Escape.unescapeUnicode(str); + } } else { str = getUnescapedStringLiteral(); } iHaveQuotedString = true; - if (tokCommand == Token.load && lastToken.tok == Token.data + if (tokCommand == Token.load && lastToken.tok == Token.data || tokCommand == Token.data && str.indexOf("@") < 0) { if (!getData(str)) return ERROR(ERROR_missingEnd, "data"); @@ -926,16 +939,21 @@ iHaveQuotedString = true; return OK; } - if (nTokens == 1 && lookingAtLoadFormat()) { - String strFormat = script.substring(ichToken, ichToken + cchToken); - int tok = (strFormat.indexOf("=") == 0 || strFormat.indexOf("$") == 0 ? Token.string - : (strFormat = strFormat.toLowerCase()).equals("data") ? Token.data - : Parser.isOneOf(strFormat, LOAD_TYPES) ? Token.identifier : 0); - if (tok != 0) { - addTokenToPrefix(new Token(tok, strFormat)); - iHaveQuotedString = (tok == Token.string); + if (nTokens == 1) { + inlineLoad = false; + if (lookingAtLoadFormat()) { + String strFormat = script.substring(ichToken, ichToken + cchToken); + int tok = (strFormat.indexOf("=") == 0 || strFormat.indexOf("$") == 0 ? Token.string + : (strFormat = strFormat.toLowerCase()).equals("data") ? Token.data + : Parser.isOneOf(strFormat, LOAD_TYPES) ? Token.identifier + : 0); + if (tok != 0) { + inlineLoad = (strFormat.equals("inline")); + addTokenToPrefix(new Token(tok, strFormat)); + iHaveQuotedString = (tok == Token.string); + } + return CONTINUE; } - return CONTINUE; } BitSet bs; if (script.charAt(ichToken) == '{' || parenCount > 0) { @@ -980,7 +998,7 @@ && !(tokCommand == Token.script && iHaveQuotedString) && lookingAtImpliedString(true)) { String str = script.substring(ichToken, ichToken + cchToken); - if (tokCommand == Token.label + if (tokCommand == Token.label && Parser.isOneOf(str.toLowerCase(), "on;off;hide;display")) addTokenToPrefix(Token.getTokenFromName(str.toLowerCase())); else @@ -999,13 +1017,14 @@ return CONTINUE; } if (lookingAtDecimal()) { - value = + value = // can't use parseFloat with jvm 1.1 // Float.parseFloat(script.substring(ichToken, ichToken + // cchToken)); Float.valueOf(script.substring(ichToken, ichToken + cchToken)) .floatValue(); - int intValue = (JmolConstants.modelValue(script.substring(ichToken, ichToken + cchToken))); + int intValue = (JmolConstants.modelValue(script.substring(ichToken, + ichToken + cchToken))); addTokenToPrefix(new Token(Token.decimal, intValue, new Float(value))); return CONTINUE; } @@ -1046,7 +1065,8 @@ return CONTINUE; } if (!isMathExpressionCommand && parenCount == 0 - || lastToken.tok != Token.identifier && !tokenAttr(lastToken, Token.mathfunc)) { + || lastToken.tok != Token.identifier + && !tokenAttr(lastToken, Token.mathfunc)) { // here if: // structure helix ({...}) // frame align ({...}) @@ -1064,7 +1084,8 @@ if (isBondOrMatrix) { Object m = lookingAtMatrix(); if (m instanceof Matrix3f || m instanceof Matrix4f) { - addTokenToPrefix(new Token((m instanceof Matrix3f ? Token.matrix3f : Token.matrix4f), m)); + addTokenToPrefix(new Token((m instanceof Matrix3f ? Token.matrix3f + : Token.matrix4f), m)); return CONTINUE; } } Modified: trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java =================================================================== --- trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2011-02-16 14:49:43 UTC (rev 15172) +++ trunk/Jmol/src/org/jmol/script/ScriptEvaluator.java 2011-02-16 14:51:03 UTC (rev 15173) @@ -15053,6 +15053,7 @@ private boolean mo(boolean isInitOnly) throws ScriptException { int offset = Integer.MAX_VALUE; + boolean isNegOffset = false; BitSet bsModels = viewer.getVisibleFramesBitSet(); List<Object[]> propertyList = new ArrayList<Object[]>(); int i = 1; @@ -15083,12 +15084,31 @@ switch (getToken(i).tok) { case Token.integer: moNumber = intParameter(i); + linearCombination = (moNumber >= 0 ? null : new float[] {-100, -moNumber}); + break; + case Token.minus: + switch (tokAt(++i)) { + case Token.homo: + case Token.lumo: + break; + default: + error(ERROR_invalidArgument); + } + isNegOffset = true; + // fall through + case Token.homo: + case Token.lumo: linearCombination = null; + if ((offset = moOffset(i)) == Integer.MAX_VALUE) + error(ERROR_invalidArgument); + moNumber = 0; break; case Token.next: + linearCombination = null; moNumber = Token.next; break; case Token.prev: + linearCombination = null; moNumber = Token.prev; break; case Token.color: @@ -15133,12 +15153,6 @@ propertyValue = parameterAsString(i + 1); } break; - case Token.homo: - case Token.lumo: - if ((offset = moOffset(i)) == Integer.MAX_VALUE) - error(ERROR_invalidArgument); - moNumber = 0; - break; case Token.identifier: error(ERROR_invalidArgument); default: @@ -15159,7 +15173,7 @@ if (tokAt(i + 1) == Token.string) title = parameterAsString(i + 1); setCursorWait(true); - setMoData(propertyList, moNumber, linearCombination, offset, iModel, title); + setMoData(propertyList, moNumber, linearCombination, offset, isNegOffset, iModel, title); addShapeProperty(propertyList, "finalize", null); } if (propertyList.size() > 0) @@ -15224,7 +15238,7 @@ @SuppressWarnings("unchecked") private void setMoData(List<Object[]> propertyList, int moNumber, - float[] linearCombination, int offset, int modelIndex, + float[] linearCombination, int offset, boolean isNegOffset, int modelIndex, String title) throws ScriptException { if (isSyntaxCheck) return; @@ -15280,6 +15294,8 @@ } moData.put("lastMoNumber", Integer.valueOf(moNumber)); } + if (isNegOffset) + linearCombination = new float[] {-100, moNumber}; addShapeProperty(propertyList, "moData", moData); if (title != null) addShapeProperty(propertyList, "title", title); @@ -15824,6 +15840,9 @@ // mo 1-based-index int moNumber = Integer.MAX_VALUE; int offset = Integer.MAX_VALUE; + boolean isNegOffset = (tokAt(i + 1) == Token.minus); + if (isNegOffset) + i++; float[] linearCombination = null; switch (tokAt(++i)) { case Token.nada: @@ -15833,7 +15852,7 @@ offset = moOffset(i); moNumber = 0; i = iToken; - sbCommand.append(" mo HOMO "); + sbCommand.append(" mo " + (isNegOffset ? "-" : "") + "HOMO "); if (offset > 0) sbCommand.append("+"); if (offset != 0) @@ -15849,7 +15868,7 @@ i = iToken; } } - setMoData(propertyList, moNumber, linearCombination, offset, modelIndex, null); + setMoData(propertyList, moNumber, linearCombination, offset, isNegOffset, modelIndex, null); surfaceObjectSeen = true; continue; case Token.mep: @@ -16039,7 +16058,7 @@ case Token.ed: sbCommand.append(" ed"); // electron density - never documented - setMoData(propertyList, -1, null, 0, modelIndex, null); + setMoData(propertyList, -1, null, 0, false, modelIndex, null); surfaceObjectSeen = true; continue; case Token.debug: Modified: trunk/Jmol/src/org/jmol/util/JpegEncoder.java =================================================================== --- trunk/Jmol/src/org/jmol/util/JpegEncoder.java 2011-02-16 14:49:43 UTC (rev 15172) +++ trunk/Jmol/src/org/jmol/util/JpegEncoder.java 2011-02-16 14:51:03 UTC (rev 15173) @@ -47,6 +47,19 @@ public class JpegEncoder extends Frame { + // A system to allow the full Jmol state -- regardless of length -- + // to be encoded in a set of APP1 (FFE1) tags. + // But we have to be careful about line ends for backward compatibility. + // This solution is not 100% effective, because some data lines may in principle be + // Very large and may not contain new lines for more than 65500 characters, + // But that would be very unusual. Perhaps a huge data set loaded from a + // string. Introduced in Jmol 12.1.36. + + public static final String CONTINUE_STRING = " #Jmol...\0"; + // this string will GENERALLY appear at the end of lines and escape the + private static final int CONTINUE_MAX = 65500; // some room to spare here. + private static final int CONTINUE_MAX_BUFFER = CONTINUE_MAX + 10; // never break up last 10 bytes + //Thread runner; private BufferedOutputStream outStream; //Image image; @@ -217,24 +230,24 @@ } static private String WriteHeaders(BufferedOutputStream out, JpegInfo JpegObj, DCT dct) { - int i, j, index, offset, length; + int i, j, index, offset; int tempArray[]; // the SOI marker byte[] SOI = {(byte) 0xFF, (byte) 0xD8}; WriteMarker(SOI, out); - // The order of the following headers is quiet inconsequential. + // The order of the following headers is quite inconsequential. // the JFIF header byte JFIF[] = new byte[18]; JFIF[0] = (byte) 0xff; JFIF[1] = (byte) 0xe0; - JFIF[2] = (byte) 0x00; - JFIF[3] = (byte) 0x10; - JFIF[4] = (byte) 0x4a; - JFIF[5] = (byte) 0x46; - JFIF[6] = (byte) 0x49; - JFIF[7] = (byte) 0x46; + JFIF[2] = 0; + JFIF[3] = 16; + JFIF[4] = (byte) 0x4a; //'J' + JFIF[5] = (byte) 0x46; //'F' + JFIF[6] = (byte) 0x49; //'I' + JFIF[7] = (byte) 0x46; //'F' JFIF[8] = (byte) 0x00; JFIF[9] = (byte) 0x01; JFIF[10] = (byte) 0x00; @@ -245,35 +258,21 @@ JFIF[15] = (byte) 0x01; JFIF[16] = (byte) 0x00; JFIF[17] = (byte) 0x00; - WriteArray(JFIF, out); + writeArray(JFIF, out); // Comment Header - String comment = JpegObj.Comment; - if (JpegObj.Comment.length() >= 65000) { - JpegObj.Comment = "JPEG Encoder Copyright 1998, James R. Weeks and BioElectroMech.\n\n"; - } else { - JpegObj.Comment = "JPEG Encoder Copyright 1998, James R. Weeks and BioElectroMech.\n\n" + comment; - comment = null; - } - // bug fix -- ha...@st... -- 4/2010 -- Jmol 12.0.RC7 -- - // length was two short here. - length = JpegObj.Comment.length() + 2; - byte COM[] = new byte[length + 2]; - COM[0] = (byte) 0xFF; - COM[1] = (byte) 0xFE; - COM[2] = (byte) ((length >> 8) & 0xFF); - COM[3] = (byte) (length & 0xFF); - java.lang.System.arraycopy(JpegObj.Comment.getBytes(), 0, - COM, 4, JpegObj.Comment.length()); - WriteArray(COM, out); - + String comment = null; + if (JpegObj.Comment.length() > 0) + writeString(JpegObj.Comment, (byte) 0xE1, out); // App data 1 + writeString("JPEG Encoder Copyright 1998, James R. Weeks and BioElectroMech.\n\n", (byte) 0xFE, out); + // The DQT header // 0 is the luminance index and 1 is the chrominance index byte DQT[] = new byte[134]; DQT[0] = (byte) 0xFF; DQT[1] = (byte) 0xDB; - DQT[2] = (byte) 0x00; - DQT[3] = (byte) 0x84; + DQT[2] = 0; + DQT[3] = (byte) 132; offset = 4; for (i = 0; i < 2; i++) { DQT[offset++] = (byte) ((0 << 4) + i); @@ -282,14 +281,14 @@ DQT[offset++] = (byte) tempArray[Huffman.jpegNaturalOrder[j]]; } } - WriteArray(DQT, out); + writeArray(DQT, out); // Start of Frame Header byte SOF[] = new byte[19]; SOF[0] = (byte) 0xFF; SOF[1] = (byte) 0xC0; - SOF[2] = (byte) 0x00; - SOF[3] = (byte) 17; + SOF[2] = 0; + SOF[3] = 17; SOF[4] = (byte) JpegObj.Precision; SOF[5] = (byte) ((JpegObj.imageHeight >> 8) & 0xFF); SOF[6] = (byte) ((JpegObj.imageHeight) & 0xFF); @@ -302,7 +301,7 @@ SOF[index++] = (byte) ((JpegObj.HsampFactor[i] << 4) + JpegObj.VsampFactor[i]); SOF[index++] = (byte) JpegObj.QtableNumber[i]; } - WriteArray(SOF, out); + writeArray(SOF, out); WriteDHTHeader(Huffman.bitsDCluminance, Huffman.valDCluminance, out); WriteDHTHeader(Huffman.bitsACluminance, Huffman.valACluminance, out); @@ -313,8 +312,8 @@ byte SOS[] = new byte[14]; SOS[0] = (byte) 0xFF; SOS[1] = (byte) 0xDA; - SOS[2] = (byte) 0x00; - SOS[3] = (byte) 12; + SOS[2] = 0; + SOS[3] = 12; SOS[4] = (byte) JpegObj.NumberOfComponents; index = 5; for (i = 0; i < SOS[4]; i++) { @@ -325,10 +324,43 @@ SOS[index++] = (byte) JpegObj.Ss; SOS[index++] = (byte) JpegObj.Se; SOS[index++] = (byte) ((JpegObj.Ah << 4) + JpegObj.Al); - WriteArray(SOS, out); + writeArray(SOS, out); return comment; } + private static void writeString(String s, byte id, BufferedOutputStream out) { + int len = s.length(); + int i0 = 0; + String suffix = CONTINUE_STRING; + while (i0 < len) { + int nBytes = len - i0; + if (nBytes > CONTINUE_MAX_BUFFER) { + nBytes = CONTINUE_MAX; + // but break only at line breaks + int pt = s.lastIndexOf('\n', i0 + nBytes); + if (pt > i0 + 1) + nBytes = pt - i0; + } + if (i0 + nBytes == len) + suffix = ""; + writeTag(nBytes + suffix.length(), id, out); + writeArray(s.substring(i0, i0 + nBytes).getBytes(), out); + if (suffix.length() > 0) + writeArray(suffix.getBytes(), out); + i0 += nBytes; + } + } + + private static void writeTag(int length, byte id, BufferedOutputStream out) { + length += 2; + byte COM[] = new byte[4]; + COM[0] = (byte) 0xFF; + COM[1] = id; + COM[2] = (byte) ((length >> 8) & 0xFF); + COM[3] = (byte) (length & 0xFF); + writeArray(COM, out); + } + static void WriteDHTHeader(int[] bits, int[] val, BufferedOutputStream out) { byte DHT1[], DHT2[], DHT3[], DHT4[]; int bytes, temp, oldindex, intermediateindex; @@ -358,7 +390,7 @@ oldindex = index; DHT4[2] = (byte) (((index - 2) >> 8) & 0xFF); DHT4[3] = (byte) ((index - 2) & 0xFF); - WriteArray(DHT4, out); + writeArray(DHT4, out); } static void WriteMarker(byte[] data, BufferedOutputStream out) { @@ -369,11 +401,9 @@ } } - static void WriteArray(byte[] data, BufferedOutputStream out) { - int length; + static void writeArray(byte[] data, BufferedOutputStream out) { try { - length = ((data[2] & 0xFF) << 8) + (data[3] & 0xFF) + 2; - out.write(data, 0, length); + out.write(data); } catch (IOException e) { Logger.error("IO Error", e); } Modified: trunk/Jmol/src/org/jmol/viewer/Jmol.properties =================================================================== --- trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2011-02-16 14:49:43 UTC (rev 15172) +++ trunk/Jmol/src/org/jmol/viewer/Jmol.properties 2011-02-16 14:51:03 UTC (rev 15173) @@ -3,6 +3,13 @@ version=12.1.36_dev +# code: JPEG encoder stores state in APP1 (FFE1) tag set instead of comment field +# bug fix: Molden reader nonfunctional +# bug fix: Spartan reader fails when no MO calculation +# bug fix: Spartan MO d6/f10 reader problems +# bug fix: QuantumEspresso reader first-model not read as Cartesian coordinates +# new feature: mo -n -- switches phase of orbital +# code: MOCalculation streamlined # bug fix: load ? broken in 12.1.34 # bug fix: getProperty by itself does not return SORTED list of properties This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |