Merge
authorlana
Tue, 17 Sep 2013 08:07:14 -0700
changeset 19789 130346400f59
parent 19777 20bcd9ce8d62 (current diff)
parent 19788 2899c95495a9 (diff)
child 19869 ee6d24d1ba22
Merge
--- a/jdk/make/sun/cmm/lcms/mapfile-vers	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/make/sun/cmm/lcms/mapfile-vers	Tue Sep 17 08:07:14 2013 -0700
@@ -28,9 +28,8 @@
 SUNWprivate_1.1 {
 	global:
         Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
-        Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative;
-        Java_sun_java2d_cmm_lcms_LCMS_getProfileSize;
-        Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
+        Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative;
+        Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative;
         Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
         Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
         Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
--- a/jdk/makefiles/mapfiles/liblcms/mapfile-vers	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/makefiles/mapfiles/liblcms/mapfile-vers	Tue Sep 17 08:07:14 2013 -0700
@@ -28,9 +28,8 @@
 SUNWprivate_1.1 {
 	global:
         Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative;
-        Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative;
-        Java_sun_java2d_cmm_lcms_LCMS_getProfileSize;
-        Java_sun_java2d_cmm_lcms_LCMS_getProfileData;
+        Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative;
+        Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative;
         Java_sun_java2d_cmm_lcms_LCMS_getTagNative;
         Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative;
         Java_sun_java2d_cmm_lcms_LCMS_colorConvert;
--- a/jdk/src/macosx/native/sun/awt/CTextPipe.m	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/macosx/native/sun/awt/CTextPipe.m	Tue Sep 17 08:07:14 2013 -0700
@@ -145,11 +145,6 @@
 
     BOOL saved = false;
 
-    /* Save and restore of graphics context is done before the iteration.  
-       This seems to work using our test case (see bug ID 7158350) so we are restoring it at
-       the end of the for loop.  If we find out that save/restore outside the loop
-       doesn't work on all cases then we will move the Save/Restore inside the loop.*/
-    CGContextSaveGState(cgRef);
     CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx);
 
     NSUInteger i;
@@ -226,7 +221,9 @@
 
     }
     // reset the font on the context after striking a unicode with CoreText
-    CGContextRestoreGState(cgRef);
+    if (saved) {
+        CGContextRestoreGState(cgRef);
+    }
 }
 
 // Using the Quartz Surface Data context, draw a hot-substituted character run
--- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java	Tue Sep 17 08:07:14 2013 -0700
@@ -37,6 +37,7 @@
 
 import sun.java2d.cmm.PCMM;
 import sun.java2d.cmm.CMSManager;
+import sun.java2d.cmm.Profile;
 import sun.java2d.cmm.ProfileDataVerifier;
 import sun.java2d.cmm.ProfileDeferralMgr;
 import sun.java2d.cmm.ProfileDeferralInfo;
@@ -94,7 +95,7 @@
 
     private static final long serialVersionUID = -3938515861990936766L;
 
-    transient long ID;
+    private transient Profile cmmProfile;
 
     private transient ProfileDeferralInfo deferralInfo;
     private transient ProfileActivator profileActivator;
@@ -727,8 +728,8 @@
     /**
      * Constructs an ICC_Profile object with a given ID.
      */
-    ICC_Profile(long ID) {
-        this.ID = ID;
+    ICC_Profile(Profile p) {
+        this.cmmProfile = p;
     }
 
 
@@ -751,8 +752,8 @@
      * Frees the resources associated with an ICC_Profile object.
      */
     protected void finalize () {
-        if (ID != 0) {
-            CMSManager.getModule().freeProfile(ID);
+        if (cmmProfile != null) {
+            CMSManager.getModule().freeProfile(cmmProfile);
         } else if (profileActivator != null) {
             ProfileDeferralMgr.unregisterDeferral(profileActivator);
         }
@@ -770,7 +771,7 @@
     public static ICC_Profile getInstance(byte[] data) {
     ICC_Profile thisProfile;
 
-        long theID;
+        Profile p = null;
 
         if (ProfileDeferralMgr.deferring) {
             ProfileDeferralMgr.activateProfiles();
@@ -779,32 +780,32 @@
         ProfileDataVerifier.verify(data);
 
         try {
-            theID = CMSManager.getModule().loadProfile(data);
+            p = CMSManager.getModule().loadProfile(data);
         } catch (CMMException c) {
             throw new IllegalArgumentException("Invalid ICC Profile Data");
         }
 
         try {
-            if ((getColorSpaceType (theID) == ColorSpace.TYPE_GRAY) &&
-                (getData (theID, icSigMediaWhitePointTag) != null) &&
-                (getData (theID, icSigGrayTRCTag) != null)) {
-                thisProfile = new ICC_ProfileGray (theID);
+            if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) &&
+                (getData (p, icSigMediaWhitePointTag) != null) &&
+                (getData (p, icSigGrayTRCTag) != null)) {
+                thisProfile = new ICC_ProfileGray (p);
             }
-            else if ((getColorSpaceType (theID) == ColorSpace.TYPE_RGB) &&
-                (getData (theID, icSigMediaWhitePointTag) != null) &&
-                (getData (theID, icSigRedColorantTag) != null) &&
-                (getData (theID, icSigGreenColorantTag) != null) &&
-                (getData (theID, icSigBlueColorantTag) != null) &&
-                (getData (theID, icSigRedTRCTag) != null) &&
-                (getData (theID, icSigGreenTRCTag) != null) &&
-                (getData (theID, icSigBlueTRCTag) != null)) {
-                thisProfile = new ICC_ProfileRGB (theID);
+            else if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) &&
+                (getData (p, icSigMediaWhitePointTag) != null) &&
+                (getData (p, icSigRedColorantTag) != null) &&
+                (getData (p, icSigGreenColorantTag) != null) &&
+                (getData (p, icSigBlueColorantTag) != null) &&
+                (getData (p, icSigRedTRCTag) != null) &&
+                (getData (p, icSigGreenTRCTag) != null) &&
+                (getData (p, icSigBlueTRCTag) != null)) {
+                thisProfile = new ICC_ProfileRGB (p);
             }
             else {
-                thisProfile = new ICC_Profile (theID);
+                thisProfile = new ICC_Profile (p);
             }
         } catch (CMMException c) {
-            thisProfile = new ICC_Profile (theID);
+            thisProfile = new ICC_Profile (p);
         }
         return thisProfile;
     }
@@ -1119,7 +1120,7 @@
                 fileName);
         }
         try {
-            ID = CMSManager.getModule().loadProfile(profileData);
+            cmmProfile = CMSManager.getModule().loadProfile(profileData);
         } catch (CMMException c) {
             ProfileDataException pde = new
                 ProfileDataException("Invalid ICC Profile Data" + fileName);
@@ -1229,14 +1230,14 @@
                                                    causing a deferred profile
                                                    to be loaded */
         }
-        return    getColorSpaceType(ID);
+        return    getColorSpaceType(cmmProfile);
     }
 
-    static int getColorSpaceType(long profileID) {
+    static int getColorSpaceType(Profile p) {
     byte[] theHeader;
     int theColorSpaceSig, theColorSpace;
 
-        theHeader = getData(profileID, icSigHead);
+        theHeader = getData(p, icSigHead);
         theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace);
         theColorSpace = iccCStoJCS (theColorSpaceSig);
         return theColorSpace;
@@ -1258,15 +1259,15 @@
         if (ProfileDeferralMgr.deferring) {
             ProfileDeferralMgr.activateProfiles();
         }
-        return getPCSType(ID);
+        return getPCSType(cmmProfile);
     }
 
 
-    static int getPCSType(long profileID) {
+    static int getPCSType(Profile p) {
     byte[] theHeader;
     int thePCSSig, thePCS;
 
-        theHeader = getData(profileID, icSigHead);
+        theHeader = getData(p, icSigHead);
         thePCSSig = intFromBigEndian(theHeader, icHdrPcs);
         thePCS = iccCStoJCS(thePCSSig);
         return thePCS;
@@ -1326,12 +1327,12 @@
         PCMM mdl = CMSManager.getModule();
 
         /* get the number of bytes needed for this profile */
-        profileSize = mdl.getProfileSize(ID);
+        profileSize = mdl.getProfileSize(cmmProfile);
 
         profileData = new byte [profileSize];
 
         /* get the data for the profile */
-        mdl.getProfileData(ID, profileData);
+        mdl.getProfileData(cmmProfile, profileData);
 
         return profileData;
     }
@@ -1358,11 +1359,11 @@
             ProfileDeferralMgr.activateProfiles();
         }
 
-        return getData(ID, tagSignature);
+        return getData(cmmProfile, tagSignature);
     }
 
 
-    static byte[] getData(long profileID, int tagSignature) {
+    static byte[] getData(Profile p, int tagSignature) {
     int tagSize;
     byte[] tagData;
 
@@ -1370,12 +1371,12 @@
             PCMM mdl = CMSManager.getModule();
 
             /* get the number of bytes needed for this tag */
-            tagSize = mdl.getTagSize(profileID, tagSignature);
+            tagSize = mdl.getTagSize(p, tagSignature);
 
             tagData = new byte[tagSize]; /* get an array for the tag */
 
             /* get the tag's data */
-            mdl.getTagData(profileID, tagSignature, tagData);
+            mdl.getTagData(p, tagSignature, tagData);
         } catch(CMMException c) {
             tagData = null;
         }
@@ -1406,7 +1407,7 @@
             ProfileDeferralMgr.activateProfiles();
         }
 
-        CMSManager.getModule().setTagData(ID, tagSignature, tagData);
+        CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData);
     }
 
     /**
--- a/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java	Tue Sep 17 08:07:14 2013 -0700
@@ -35,7 +35,7 @@
 
 package java.awt.color;
 
-import java.awt.image.LookupTable;
+import sun.java2d.cmm.Profile;
 import sun.java2d.cmm.ProfileDeferralInfo;
 
 /**
@@ -76,8 +76,8 @@
     /**
      * Constructs a new ICC_ProfileGray from a CMM ID.
      */
-    ICC_ProfileGray(long ID) {
-        super(ID);
+    ICC_ProfileGray(Profile p) {
+        super(p);
     }
 
     /**
--- a/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java	Tue Sep 17 08:07:14 2013 -0700
@@ -35,7 +35,7 @@
 
 package java.awt.color;
 
-import java.awt.image.LookupTable;
+import sun.java2d.cmm.Profile;
 import sun.java2d.cmm.ProfileDeferralInfo;
 
 /**
@@ -114,8 +114,8 @@
      * @param ID The CMM ID for the profile.
      *
      */
-    ICC_ProfileRGB(long ID) {
-        super(ID);
+    ICC_ProfileRGB(Profile p) {
+        super(p);
     }
 
     /**
--- a/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java	Tue Sep 17 08:07:14 2013 -0700
@@ -104,53 +104,53 @@
             cName = tcmm.getClass().getName();
         }
 
-        public long loadProfile(byte[] data) {
+        public Profile loadProfile(byte[] data) {
             System.err.print(cName + ".loadProfile");
-            long profileID = tcmm.loadProfile(data);
-            System.err.printf("(ID=%x)\n", profileID);
-            return profileID;
+            Profile p = tcmm.loadProfile(data);
+            System.err.printf("(ID=%s)\n", p.toString());
+            return p;
         }
 
-        public void freeProfile(long profileID) {
-            System.err.printf(cName + ".freeProfile(ID=%x)\n", profileID);
-            tcmm.freeProfile(profileID);
+        public void freeProfile(Profile p) {
+            System.err.printf(cName + ".freeProfile(ID=%s)\n", p.toString());
+            tcmm.freeProfile(p);
         }
 
-        public int getProfileSize(long profileID) {
-            System.err.print(cName + ".getProfileSize(ID=" + profileID + ")");
-            int size = tcmm.getProfileSize(profileID);
+        public int getProfileSize(Profile p) {
+            System.err.print(cName + ".getProfileSize(ID=" + p + ")");
+            int size = tcmm.getProfileSize(p);
             System.err.println("=" + size);
             return size;
         }
 
-        public void getProfileData(long profileID, byte[] data) {
-            System.err.print(cName + ".getProfileData(ID=" + profileID + ") ");
+        public void getProfileData(Profile p, byte[] data) {
+            System.err.print(cName + ".getProfileData(ID=" + p + ") ");
             System.err.println("requested " + data.length + " byte(s)");
-            tcmm.getProfileData(profileID, data);
+            tcmm.getProfileData(p, data);
         }
 
-        public int getTagSize(long profileID, int tagSignature) {
+        public int getTagSize(Profile p, int tagSignature) {
             System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)",
-                              profileID, signatureToString(tagSignature));
-            int size = tcmm.getTagSize(profileID, tagSignature);
+                              p, signatureToString(tagSignature));
+            int size = tcmm.getTagSize(p, tagSignature);
             System.err.println("=" + size);
             return size;
         }
 
-        public void getTagData(long profileID, int tagSignature,
+        public void getTagData(Profile p, int tagSignature,
                                byte[] data) {
             System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)",
-                              profileID, signatureToString(tagSignature));
+                              p, signatureToString(tagSignature));
             System.err.println(" requested " + data.length + " byte(s)");
-            tcmm.getTagData(profileID, tagSignature, data);
+            tcmm.getTagData(p, tagSignature, data);
         }
 
-        public void setTagData(long profileID, int tagSignature,
+        public void setTagData(Profile p, int tagSignature,
                                byte[] data) {
-            System.err.print(cName + ".setTagData(ID=" + profileID +
+            System.err.print(cName + ".setTagData(ID=" + p +
                              ", TagSig=" + tagSignature + ")");
             System.err.println(" sending " + data.length + " byte(s)");
-            tcmm.setTagData(profileID, tagSignature, data);
+            tcmm.setTagData(p, tagSignature, data);
         }
 
         /* methods for creating ColorTransforms */
--- a/jdk/src/share/classes/sun/java2d/cmm/PCMM.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/PCMM.java	Tue Sep 17 08:07:14 2013 -0700
@@ -32,13 +32,13 @@
 public interface PCMM {
 
     /* methods invoked from ICC_Profile */
-    public long loadProfile(byte[] data);
-    public void freeProfile(long profileID);
-    public int  getProfileSize(long profileID);
-    public void getProfileData(long profileID, byte[] data);
-    public void getTagData(long profileID, int tagSignature, byte[] data);
-    public int getTagSize(long profileID, int tagSignature);
-    public void setTagData(long profileID, int tagSignature, byte[] data);
+    public Profile loadProfile(byte[] data);
+    public void freeProfile(Profile p);
+    public int  getProfileSize(Profile p);
+    public void getProfileData(Profile p, byte[] data);
+    public void getTagData(Profile p, int tagSignature, byte[] data);
+    public int getTagSize(Profile p, int tagSignature);
+    public void setTagData(Profile p, int tagSignature, byte[] data);
 
     /* methods for creating ColorTransforms */
     public ColorTransform createTransform(ICC_Profile profile, int renderType,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/cmm/Profile.java	Tue Sep 17 08:07:14 2013 -0700
@@ -0,0 +1,43 @@
+/*
+ * 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 sun.java2d.cmm;
+
+import java.awt.color.CMMException;
+
+public class Profile {
+    private final long nativePtr;
+
+    protected Profile(long ptr) {
+        nativePtr = ptr;
+    }
+
+    protected final long getNativePtr() {
+        if (nativePtr == 0L) {
+            throw new CMMException("Invalid profile: ptr is null");
+        }
+        return nativePtr;
+    }
+}
--- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java	Tue Sep 17 08:07:14 2013 -0700
@@ -25,96 +25,139 @@
 
 package sun.java2d.cmm.lcms;
 
+import java.awt.color.CMMException;
 import java.awt.color.ICC_Profile;
-import java.util.Arrays;
-import java.util.HashMap;
 import sun.java2d.cmm.ColorTransform;
 import sun.java2d.cmm.PCMM;
+import sun.java2d.cmm.Profile;
+import sun.java2d.cmm.lcms.LCMSProfile.TagData;
 
 public class LCMS implements PCMM {
 
     /* methods invoked from ICC_Profile */
     @Override
-    public long loadProfile(byte[] data) {
-        long id = loadProfileNative(data);
+    public Profile loadProfile(byte[] data) {
+        final Object disposerRef = new Object();
+
+        final long ptr = loadProfileNative(data, disposerRef);
 
-        if (id != 0L) {
-            if (profiles == null) {
-                profiles = new HashMap<>();
-            }
-            profiles.put(id, new TagCache(id));
+        if (ptr != 0L) {
+            return new LCMSProfile(ptr, disposerRef);
         }
-        return id;
+        return null;
     }
 
-    private native long loadProfileNative(byte[] data);
+    private native long loadProfileNative(byte[] data, Object ref);
+
+    private LCMSProfile getLcmsProfile(Profile p) {
+        if (p instanceof LCMSProfile) {
+            return (LCMSProfile)p;
+        }
+        throw new CMMException("Invalid profile: " + p);
+    }
+
 
     @Override
-    public void freeProfile(long profileID) {
-        TagCache c = profiles.remove(profileID);
-        if (c != null) {
-            c.clear();
+    public void freeProfile(Profile p) {
+        // we use disposer, so this method does nothing
+    }
+
+    @Override
+    public int getProfileSize(final Profile p) {
+        synchronized (p) {
+            return getProfileSizeNative(getLcmsProfile(p).getLcmsPtr());
         }
-        if (profiles.isEmpty()) {
-            profiles = null;
-        }
-        freeProfileNative(profileID);
     }
 
-    private native void freeProfileNative(long profileID);
+    private native int getProfileSizeNative(long ptr);
 
-    public native synchronized int getProfileSize(long profileID);
+    @Override
+    public void getProfileData(final Profile p, byte[] data) {
+        synchronized (p) {
+            getProfileDataNative(getLcmsProfile(p).getLcmsPtr(), data);
+        }
+    }
 
-    public native synchronized void getProfileData(long profileID, byte[] data);
+    private native void getProfileDataNative(long ptr, byte[] data);
 
     @Override
-    public synchronized int getTagSize(long profileID, int tagSignature) {
-        TagCache cache = profiles.get(profileID);
+    public int getTagSize(Profile p, int tagSignature) {
+        final LCMSProfile profile = getLcmsProfile(p);
 
-        if (cache ==  null) {
-            cache = new TagCache(profileID);
-            profiles.put(profileID, cache);
+        synchronized (profile) {
+            TagData t = profile.getTag(tagSignature);
+            return t == null ? 0 : t.getSize();
         }
-
-        TagData t = cache.getTag(tagSignature);
-        return t == null ? 0 : t.getSize();
     }
 
-    private static native byte[] getTagNative(long profileID, int signature);
+    static native byte[] getTagNative(long profileID, int signature);
 
     @Override
-    public synchronized void getTagData(long profileID, int tagSignature,
-                                               byte[] data)
+    public void getTagData(Profile p, int tagSignature, byte[] data)
     {
-        TagCache cache = profiles.get(profileID);
+        final LCMSProfile profile = getLcmsProfile(p);
 
-        if (cache ==  null) {
-            cache = new TagCache(profileID);
-            profiles.put(profileID, cache);
-        }
-
-        TagData t = cache.getTag(tagSignature);
-        if (t != null) {
-            t.copyDataTo(data);
+        synchronized (profile) {
+            TagData t = profile.getTag(tagSignature);
+            if (t != null) {
+                t.copyDataTo(data);
+            }
         }
     }
 
     @Override
-    public synchronized void setTagData(long profileID, int tagSignature, byte[] data) {
-        TagCache cache = profiles.get(profileID);
+    public synchronized void setTagData(Profile p, int tagSignature, byte[] data) {
+        final LCMSProfile profile = getLcmsProfile(p);
+
+        synchronized (profile) {
+            profile.clearTagCache();
 
-        if (cache != null) {
-            cache.clear();
+            // Now we are going to update the profile with new tag data
+            // In some cases, we may change the pointer to the native
+            // profile.
+            //
+            // If we fail to write tag data for any reason, the old pointer
+            // should be used.
+            setTagDataNative(profile.getLcmsPtr(),
+                    tagSignature, data);
         }
-        setTagDataNative(profileID, tagSignature, data);
     }
 
-    private native synchronized void setTagDataNative(long profileID, int tagSignature,
+    /**
+     * Writes supplied data as a tag into the profile.
+     * Destroys old profile, if new one was successfully
+     * created.
+     *
+     * Returns valid pointer to new profile.
+     *
+     * Throws CMMException if operation fails, preserve old profile from
+     * destruction.
+     */
+    private native void setTagDataNative(long ptr, int tagSignature,
                                                byte[] data);
 
-    public static native long getProfileID(ICC_Profile profile);
+    public synchronized static native LCMSProfile getProfileID(ICC_Profile profile);
+
+    /* Helper method used from LCMSColorTransfrom */
+    static long createTransform(
+        LCMSProfile[] profiles, int renderType,
+        int inFormatter, boolean isInIntPacked,
+        int outFormatter, boolean isOutIntPacked,
+        Object disposerRef)
+    {
+        long[] ptrs = new long[profiles.length];
 
-    public static native long createNativeTransform(
+        for (int i = 0; i < profiles.length; i++) {
+            if (profiles[i] == null) throw new CMMException("Unknown profile ID");
+
+            ptrs[i] = profiles[i].getLcmsPtr();
+        }
+
+        return createNativeTransform(ptrs, renderType, inFormatter,
+                isInIntPacked, outFormatter, isOutIntPacked, disposerRef);
+    }
+
+    private static native long createNativeTransform(
         long[] profileIDs, int renderType,
         int inFormatter, boolean isInIntPacked,
         int outFormatter, boolean isOutIntPacked,
@@ -175,59 +218,4 @@
 
         return theLcms;
     }
-
-    private static class TagData {
-        private int signature;
-        private byte[] data;
-
-        TagData(int sig, byte[] data) {
-            this.signature = sig;
-            this.data = data;
-        }
-
-        int getSize() {
-            return data.length;
-        }
-
-        byte[] getData() {
-            return Arrays.copyOf(data, data.length);
-        }
-
-        void copyDataTo(byte[] dst) {
-            System.arraycopy(data, 0, dst, 0, data.length);
-        }
-
-        int getSignature() {
-            return signature;
-        }
-    }
-
-    private static class TagCache  {
-        private long profileID;
-        private HashMap<Integer, TagData> tags;
-
-        TagCache(long id) {
-            profileID = id;
-
-            tags = new HashMap<>();
-        }
-
-        TagData getTag(int sig) {
-            TagData t = tags.get(sig);
-            if (t == null) {
-                byte[] tagData = getTagNative(profileID, sig);
-                if (tagData != null) {
-                    t = new TagData(sig, tagData);
-                    tags.put(sig, t);
-                }
-            }
-            return t;
-        }
-
-        void clear() {
-            tags.clear();
-        }
-    }
-
-    private static HashMap<Long, TagCache> profiles;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSProfile.java	Tue Sep 17 08:07:14 2013 -0700
@@ -0,0 +1,109 @@
+/*
+ * 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 sun.java2d.cmm.lcms;
+
+import java.awt.color.CMMException;
+import java.util.Arrays;
+import java.util.HashMap;
+import sun.java2d.cmm.Profile;
+
+final class LCMSProfile extends Profile {
+    private final TagCache tagCache;
+
+    private final Object disposerReferent;
+
+    LCMSProfile(long ptr, Object ref) {
+        super(ptr);
+
+        disposerReferent = ref;
+
+        tagCache = new TagCache(this);
+    }
+
+    final long getLcmsPtr() {
+        return this.getNativePtr();
+    }
+
+    TagData getTag(int sig) {
+        return tagCache.getTag(sig);
+    }
+
+    void clearTagCache() {
+        tagCache.clear();
+    }
+
+    static class TagCache  {
+        final LCMSProfile profile;
+        private HashMap<Integer, TagData> tags;
+
+        TagCache(LCMSProfile p) {
+            profile = p;
+            tags = new HashMap<>();
+        }
+
+        TagData getTag(int sig) {
+            TagData t = tags.get(sig);
+            if (t == null) {
+                byte[] tagData = LCMS.getTagNative(profile.getNativePtr(), sig);
+                if (tagData != null) {
+                    t = new TagData(sig, tagData);
+                    tags.put(sig, t);
+                }
+            }
+            return t;
+        }
+
+        void clear() {
+            tags.clear();
+        }
+    }
+
+    static class TagData {
+        private int signature;
+        private byte[] data;
+
+        TagData(int sig, byte[] data) {
+            this.signature = sig;
+            this.data = data;
+        }
+
+        int getSize() {
+            return data.length;
+        }
+
+        byte[] getData() {
+            return Arrays.copyOf(data, data.length);
+        }
+
+        void copyDataTo(byte[] dst) {
+            System.arraycopy(data, 0, dst, 0, data.length);
+        }
+
+        int getSignature() {
+            return signature;
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java	Tue Sep 17 08:07:14 2013 -0700
@@ -62,7 +62,7 @@
     private boolean isOutIntPacked = false;
 
     ICC_Profile[] profiles;
-    long [] profileIDs;
+    LCMSProfile[] lcmsProfiles;
     int renderType;
     int transformType;
 
@@ -84,8 +84,8 @@
         /* Actually, it is not a complete transform but just part of it */
         profiles = new ICC_Profile[1];
         profiles[0] = profile;
-        profileIDs = new long[1];
-        profileIDs[0] = LCMS.getProfileID(profile);
+        lcmsProfiles = new LCMSProfile[1];
+        lcmsProfiles[0] = LCMS.getProfileID(profile);
         this.renderType = (renderType == ColorTransform.Any)?
                               ICC_Profile.icPerceptual : renderType;
         this.transformType = transformType;
@@ -105,14 +105,14 @@
             size+=((LCMSTransform)transforms[i]).profiles.length;
         }
         profiles = new ICC_Profile[size];
-        profileIDs = new long[size];
+        lcmsProfiles = new LCMSProfile[size];
         int j = 0;
         for (int i=0; i < transforms.length; i++) {
             LCMSTransform curTrans = (LCMSTransform)transforms[i];
             System.arraycopy(curTrans.profiles, 0, profiles, j,
                              curTrans.profiles.length);
-            System.arraycopy(curTrans.profileIDs, 0, profileIDs, j,
-                             curTrans.profileIDs.length);
+            System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j,
+                             curTrans.lcmsProfiles.length);
             j += curTrans.profiles.length;
         }
         renderType = ((LCMSTransform)transforms[0]).renderType;
@@ -152,7 +152,7 @@
             outFormatter = out.pixelType;
             isOutIntPacked = out.isIntPacked;
 
-            ID = LCMS.createNativeTransform(profileIDs, renderType,
+            ID = LCMS.createTransform(lcmsProfiles, renderType,
                                             inFormatter, isInIntPacked,
                                             outFormatter, isOutIntPacked,
                                             disposerReferent);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java	Tue Sep 17 08:07:14 2013 -0700
@@ -0,0 +1,62 @@
+/*
+ * 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 sun.print;
+
+import java.awt.Window;
+import java.awt.print.PrinterJob;
+import javax.print.PrintService;
+import javax.print.ServiceUIFactory;
+import javax.print.attribute.PrintRequestAttributeSet;
+
+public abstract class DocumentPropertiesUI {
+
+    /**
+     * For Win32 doc properties sheet.
+     */
+    public static final int
+        DOCUMENTPROPERTIES_ROLE = ServiceUIFactory.RESERVED_UIROLE +100;
+
+    /**
+     * Name of (this) abstract class for Document Properties.
+     */
+    public static final String
+        DOCPROPERTIESCLASSNAME = DocumentPropertiesUI.class.getName();
+
+    /**
+     * Invokes whatever code is needed to display a native dialog
+     * with the specified owner. The owner should be the cross-platform
+     * dialog. If the user cancels the dialog the return value is null.
+     * A non-null return value is always a new attribute set (or is it?)
+     * The cross-platform dialog may need to be updated to reflect the
+     * updated properties.
+     */
+    public abstract PrintRequestAttributeSet
+        showDocumentProperties(PrinterJob job,
+                               Window owner,
+                               PrintService service,
+                               PrintRequestAttributeSet aset);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/print/PrinterJobWrapper.java	Tue Sep 17 08:07:14 2013 -0700
@@ -0,0 +1,60 @@
+/*
+ * 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 sun.print;
+
+import java.awt.print.PrinterJob;
+import javax.print.attribute.PrintRequestAttribute;
+
+public class PrinterJobWrapper implements PrintRequestAttribute {
+
+    private static final long serialVersionUID = -8792124426995707237L;
+
+    private PrinterJob job;
+
+    public PrinterJobWrapper(PrinterJob job) {
+        this.job = job;
+    }
+
+    public PrinterJob getPrinterJob() {
+        return job;
+    }
+
+    public final Class getCategory() {
+        return PrinterJobWrapper.class;
+    }
+
+    public final String getName() {
+        return "printerjob-wrapper";
+    }
+
+    public String toString() {
+       return "printerjob-wrapper: " + job.toString();
+    }
+
+    public int hashCode() {
+        return job.hashCode();
+    }
+}
--- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java	Tue Sep 17 08:07:14 2013 -0700
@@ -903,6 +903,9 @@
         int x = bounds.x+bounds.width/3;
         int y = bounds.y+bounds.height/3;
         PrintService newService;
+        // temporarily add an attribute pointing back to this job.
+        PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this);
+        attributes.add(jobWrapper);
         try {
             newService =
             ServiceUI.printDialog(gc, x, y,
@@ -915,6 +918,7 @@
                                   DocFlavor.SERVICE_FORMATTED.PAGEABLE,
                                   attributes);
         }
+        attributes.remove(PrinterJobWrapper.class);
 
         if (newService == null) {
             return false;
--- a/jdk/src/share/classes/sun/print/ServiceDialog.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/classes/sun/print/ServiceDialog.java	Tue Sep 17 08:07:14 2013 -0700
@@ -46,6 +46,7 @@
 import java.awt.event.ItemListener;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowAdapter;
+import java.awt.print.PrinterJob;
 import java.io.File;
 import java.io.FilePermission;
 import java.io.IOException;
@@ -119,8 +120,6 @@
     private AppearancePanel pnlAppearance;
 
     private boolean isAWT = false;
-
-
     static {
         initResource();
     }
@@ -801,9 +800,32 @@
                     if (dialog != null) {
                         dialog.show();
                     } else {
-                        // REMIND: may want to notify the user why we're
-                        //         disabling the button
-                        btnProperties.setEnabled(false);
+                        DocumentPropertiesUI docPropertiesUI = null;
+                        try {
+                            docPropertiesUI =
+                                (DocumentPropertiesUI)uiFactory.getUI
+                                (DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE,
+                                 DocumentPropertiesUI.DOCPROPERTIESCLASSNAME);
+                        } catch (Exception ex) {
+                        }
+                        if (docPropertiesUI != null) {
+                            PrinterJobWrapper wrapper = (PrinterJobWrapper)
+                                asCurrent.get(PrinterJobWrapper.class);
+                            if (wrapper == null) {
+                                return; // should not happen, defensive only.
+                            }
+                            PrinterJob job = wrapper.getPrinterJob();
+                            if (job == null) {
+                                return;  // should not happen, defensive only.
+                            }
+                            PrintRequestAttributeSet newAttrs =
+                               docPropertiesUI.showDocumentProperties
+                               (job, ServiceDialog.this, psCurrent, asCurrent);
+                            if (newAttrs != null) {
+                                asCurrent.addAll(newAttrs);
+                                updatePanels();
+                            }
+                        }
                     }
                 }
             }
--- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c	Tue Sep 17 08:07:14 2013 -0700
@@ -930,9 +930,10 @@
      * Now fill a complete buffer, or as much of one as the stream
      * will give us if we are near the end.
      */
+    RELEASE_ARRAYS(env, data, src->next_input_byte);
+
     GET_IO_REF(input);
 
-    RELEASE_ARRAYS(env, data, src->next_input_byte);
     ret = (*env)->CallIntMethod(env,
                                 input,
                                 JPEGImageReader_readInputDataID,
@@ -1017,9 +1018,11 @@
         memcpy(sb->buf, src->next_input_byte, offset);
     }
 
-    GET_IO_REF(input);
 
     RELEASE_ARRAYS(env, data, src->next_input_byte);
+
+    GET_IO_REF(input);
+
     buflen = sb->bufferLength - offset;
     if (buflen <= 0) {
         if (!GET_ARRAYS(env, data, &(src->next_input_byte))) {
@@ -1121,9 +1124,10 @@
         return;
     }
 
+    RELEASE_ARRAYS(env, data, src->next_input_byte);
+
     GET_IO_REF(input);
 
-    RELEASE_ARRAYS(env, data, src->next_input_byte);
     ret = (*env)->CallLongMethod(env,
                                  input,
                                  JPEGImageReader_skipInputBytesID,
@@ -2306,10 +2310,10 @@
     JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
     jobject output = NULL;
 
+    RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
+
     GET_IO_REF(output);
 
-    RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
-
     (*env)->CallVoidMethod(env,
                            output,
                            JPEGImageWriter_writeOutputDataID,
@@ -2348,10 +2352,10 @@
     if (datacount != 0) {
         jobject output = NULL;
 
+        RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
+
         GET_IO_REF(output);
 
-        RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte));
-
         (*env)->CallVoidMethod(env,
                                output,
                                JPEGImageWriter_writeOutputDataID,
--- a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp	Tue Sep 17 08:07:14 2013 -0700
@@ -179,6 +179,10 @@
   FontInstanceAdapter fia(env, font2d, strike, mat, 72, 72, (le_int32) upem, (TTLayoutTableCache *) layoutTables);
   LEErrorCode success = LE_NO_ERROR;
   LayoutEngine *engine = LayoutEngine::layoutEngineFactory(&fia, script, lang, typo_flags & TYPO_MASK, success);
+  if (engine == NULL) {
+    env->SetIntField(gvdata, gvdCountFID, -1); // flag failure
+    return;
+  }
 
   if (min < 0) min = 0; if (max < min) max = min; /* defensive coding */
   // have to copy, yuck, since code does upcalls now.  this will be soooo slow
--- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c	Tue Sep 17 08:07:14 2013 -0700
@@ -94,8 +94,12 @@
 # endif
 #endif
 
+typedef struct lcmsProfile_s {
+    cmsHPROFILE pf;
+} lcmsProfile_t, *lcmsProfile_p;
+
 typedef union storeID_s {    /* store SProfile stuff in a Java Long */
-    cmsHPROFILE pf;
+    lcmsProfile_p lcmsPf;
     cmsHTRANSFORM xf;
     jobject jobj;
     jlong j;
@@ -106,7 +110,6 @@
     jint j;
 } TagSignature_t, *TagSignature_p;
 
-static jfieldID Trans_profileIDs_fID;
 static jfieldID Trans_renderType_fID;
 static jfieldID Trans_ID_fID;
 static jfieldID IL_isIntPacked_fID;
@@ -118,7 +121,6 @@
 static jfieldID IL_width_fID;
 static jfieldID IL_height_fID;
 static jfieldID IL_imageAtOnce_fID;
-static jfieldID PF_ID_fID;
 
 JavaVM *javaVM;
 
@@ -145,6 +147,18 @@
     return JNI_VERSION_1_6;
 }
 
+void LCMS_freeProfile(JNIEnv *env, jlong ptr) {
+    storeID_t sProfile;
+    sProfile.j = ptr;
+
+    if (sProfile.lcmsPf != NULL) {
+        if (sProfile.lcmsPf->pf != NULL) {
+            cmsCloseProfile(sProfile.lcmsPf->pf);
+        }
+        free(sProfile.lcmsPf);
+    }
+}
+
 void LCMS_freeTransform(JNIEnv *env, jlong ID)
 {
     storeID_t sTrans;
@@ -170,7 +184,7 @@
     jlong* ids;
 
     size = (*env)->GetArrayLength (env, profileIDs);
-    ids = (*env)->GetPrimitiveArrayCritical(env, profileIDs, 0);
+    ids = (*env)->GetLongArrayElements(env, profileIDs, 0);
 
 #ifdef _LITTLE_ENDIAN
     /* Reversing data packed into int for LE archs */
@@ -186,6 +200,8 @@
         iccArray = (cmsHPROFILE*) malloc(
             size*2*sizeof(cmsHPROFILE));
         if (iccArray == NULL) {
+            (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
+
             J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL");
             return 0L;
         }
@@ -197,7 +213,7 @@
         cmsColorSpaceSignature cs;
 
         sTrans.j = ids[i];
-        icc = sTrans.pf;
+        icc = sTrans.lcmsPf->pf;
         iccArray[j++] = icc;
 
         /* Middle non-abstract profiles should be doubled before passing to
@@ -215,13 +231,15 @@
     sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j,
         inFormatter, outFormatter, renderType, 0);
 
-    (*env)->ReleasePrimitiveArrayCritical(env, profileIDs, ids, 0);
+    (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0);
 
     if (sTrans.xf == NULL) {
         J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: "
                                        "sTrans.xf == NULL");
-        JNU_ThrowByName(env, "java/awt/color/CMMException",
-                        "Cannot get color transform");
+        if ((*env)->ExceptionOccurred(env) == NULL) {
+            JNU_ThrowByName(env, "java/awt/color/CMMException",
+                            "Cannot get color transform");
+        }
     } else {
         Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j);
     }
@@ -236,20 +254,23 @@
 /*
  * Class:     sun_java2d_cmm_lcms_LCMS
  * Method:    loadProfile
- * Signature: ([B)J
+ * Signature: ([B,Lsun/java2d/cmm/lcms/LCMSProfile;)V
  */
 JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative
-  (JNIEnv *env, jobject obj, jbyteArray data)
+  (JNIEnv *env, jobject obj, jbyteArray data, jobject disposerRef)
 {
     jbyte* dataArray;
     jint dataSize;
     storeID_t sProf;
+    cmsHPROFILE pf;
 
     if (JNU_IsNull(env, data)) {
         JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
         return 0L;
     }
 
+    sProf.j = 0L;
+
     dataArray = (*env)->GetByteArrayElements (env, data, 0);
     dataSize = (*env)->GetArrayLength (env, data);
 
@@ -258,22 +279,37 @@
         return 0L;
     }
 
-    sProf.pf = cmsOpenProfileFromMem((const void *)dataArray,
+    pf = cmsOpenProfileFromMem((const void *)dataArray,
                                      (cmsUInt32Number) dataSize);
 
     (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 
-    if (sProf.pf == NULL) {
+    if (pf == NULL) {
         JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
     } else {
         /* Sanity check: try to save the profile in order
          * to force basic validation.
          */
         cmsUInt32Number pfSize = 0;
-        if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) ||
+        if (!cmsSaveProfileToMem(pf, NULL, &pfSize) ||
             pfSize < sizeof(cmsICCHeader))
         {
             JNU_ThrowIllegalArgumentException(env, "Invalid profile data");
+
+            cmsCloseProfile(pf);
+            pf = NULL;
+        }
+    }
+
+    if (pf != NULL) {
+        // create profile holder
+        sProf.lcmsPf = (lcmsProfile_p)malloc(sizeof(lcmsProfile_t));
+        if (sProf.lcmsPf != NULL) {
+            // register the disposer record
+            sProf.lcmsPf->pf = pf;
+            Disposer_AddRecord(env, disposerRef, LCMS_freeProfile, sProf.j);
+        } else {
+            cmsCloseProfile(pf);
         }
     }
 
@@ -282,37 +318,17 @@
 
 /*
  * Class:     sun_java2d_cmm_lcms_LCMS
- * Method:    freeProfile
- * Signature: (J)V
- */
-JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative
-  (JNIEnv *env, jobject obj, jlong id)
-{
-    storeID_t sProf;
-
-    sProf.j = id;
-    if (cmsCloseProfile(sProf.pf) == 0) {
-        J2dRlsTraceLn1(J2D_TRACE_ERROR, "LCMS_freeProfile: cmsCloseProfile(%d)"
-                       "== 0", id);
-        JNU_ThrowByName(env, "java/awt/color/CMMException",
-                        "Cannot close profile");
-    }
-
-}
-
-/*
- * Class:     sun_java2d_cmm_lcms_LCMS
- * Method:    getProfileSize
+ * Method:    getProfileSizeNative
  * Signature: (J)I
  */
-JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize
+JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative
   (JNIEnv *env, jobject obj, jlong id)
 {
     storeID_t sProf;
     cmsUInt32Number pfSize = 0;
     sProf.j = id;
 
-    if (cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) && ((jint)pfSize > 0)) {
+    if (cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize) && ((jint)pfSize > 0)) {
         return (jint)pfSize;
     } else {
       JNU_ThrowByName(env, "java/awt/color/CMMException",
@@ -323,10 +339,10 @@
 
 /*
  * Class:     sun_java2d_cmm_lcms_LCMS
- * Method:    getProfileData
+ * Method:    getProfileDataNative
  * Signature: (J[B)V
  */
-JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData
+JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative
   (JNIEnv *env, jobject obj, jlong id, jbyteArray data)
 {
     storeID_t sProf;
@@ -338,7 +354,7 @@
     sProf.j = id;
 
     // determine actual profile size
-    if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize)) {
+    if (!cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize)) {
         JNU_ThrowByName(env, "java/awt/color/CMMException",
                         "Can not access specified profile.");
         return;
@@ -354,7 +370,7 @@
 
     dataArray = (*env)->GetByteArrayElements (env, data, 0);
 
-    status = cmsSaveProfileToMem(sProf.pf, dataArray, &pfSize);
+    status = cmsSaveProfileToMem(sProf.lcmsPf->pf, dataArray, &pfSize);
 
     (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 
@@ -368,7 +384,7 @@
 /* Get profile header info */
 static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
 static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize);
-static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
+static cmsHPROFILE _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size);
 
 
 /*
@@ -412,7 +428,7 @@
            return NULL;
         }
 
-        status = _getHeaderInfo(sProf.pf, dataArray, bufSize);
+        status = _getHeaderInfo(sProf.lcmsPf->pf, dataArray, bufSize);
 
         (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 
@@ -425,8 +441,8 @@
         return data;
     }
 
-    if (cmsIsTag(sProf.pf, sig.cms)) {
-        tagSize = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0);
+    if (cmsIsTag(sProf.lcmsPf->pf, sig.cms)) {
+        tagSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, NULL, 0);
     } else {
         JNU_ThrowByName(env, "java/awt/color/CMMException",
                         "ICC profile tag not found");
@@ -449,7 +465,7 @@
         return NULL;
     }
 
-    bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize);
+    bufSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, dataArray, tagSize);
 
     (*env)->ReleaseByteArrayElements (env, data, dataArray, 0);
 
@@ -470,8 +486,10 @@
   (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data)
 {
     storeID_t sProf;
+    cmsHPROFILE pfReplace = NULL;
+
     TagSignature_t sig;
-    cmsBool status;
+    cmsBool status = FALSE;
     jbyte* dataArray;
     int tagSize;
 
@@ -493,15 +511,24 @@
     }
 
     if (tagSig == SigHead) {
-        status = _setHeaderInfo(sProf.pf, dataArray, tagSize);
+        status  = _setHeaderInfo(sProf.lcmsPf->pf, dataArray, tagSize);
     } else {
-        status = _writeCookedTag(sProf.pf, sig.cms, dataArray, tagSize);
+        /*
+        * New strategy for generic tags: create a place holder,
+        * dump all existing tags there, dump externally supplied
+        * tag, and return the new profile to the java.
+        */
+        pfReplace = _writeCookedTag(sProf.lcmsPf->pf, sig.cms, dataArray, tagSize);
+        status = (pfReplace != NULL);
     }
 
     (*env)->ReleaseByteArrayElements(env, data, dataArray, 0);
 
     if (!status) {
         JNU_ThrowIllegalArgumentException(env, "Can not write tag data.");
+    } else if (pfReplace != NULL) {
+        cmsCloseProfile(sProf.lcmsPf->pf);
+        sProf.lcmsPf->pf = pfReplace;
     }
 }
 
@@ -624,12 +651,27 @@
 /*
  * Class:     sun_java2d_cmm_lcms_LCMS
  * Method:    getProfileID
- * Signature: (Ljava/awt/color/ICC_Profile;)J
+ * Signature: (Ljava/awt/color/ICC_Profile;)Lsun/java2d/cmm/lcms/LCMSProfile
  */
-JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID
+JNIEXPORT jobject JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID
   (JNIEnv *env, jclass cls, jobject pf)
 {
-    return (*env)->GetLongField (env, pf, PF_ID_fID);
+    jfieldID fid = (*env)->GetFieldID (env,
+        (*env)->GetObjectClass(env, pf),
+        "cmmProfile", "Lsun/java2d/cmm/Profile;");
+
+    jclass clsLcmsProfile = (*env)->FindClass(env,
+            "sun/java2d/cmm/lcms/LCMSProfile");
+
+    jobject cmmProfile = (*env)->GetObjectField (env, pf, fid);
+
+    if (JNU_IsNull(env, cmmProfile)) {
+        return NULL;
+    }
+    if ((*env)->IsInstanceOf(env, cmmProfile, clsLcmsProfile)) {
+        return cmmProfile;
+    }
+    return NULL;
 }
 
 /*
@@ -644,7 +686,6 @@
      * corresponding classes to avoid problems with invalidating ids by class
      * unloading
      */
-    Trans_profileIDs_fID = (*env)->GetFieldID (env, Trans, "profileIDs", "[J");
     Trans_renderType_fID = (*env)->GetFieldID (env, Trans, "renderType", "I");
     Trans_ID_fID = (*env)->GetFieldID (env, Trans, "ID", "J");
 
@@ -658,8 +699,6 @@
     IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I");
     IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z");
     IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I");
-
-    PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J");
 }
 
 static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize)
@@ -714,76 +753,114 @@
   return TRUE;
 }
 
-static cmsBool _writeCookedTag(cmsHPROFILE pfTarget,
-                               cmsTagSignature sig,
+/* Returns new profile handler, if it was created successfully,
+   NULL otherwise.
+   */
+static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget,
+                               const cmsTagSignature sig,
                                jbyte *pData, jint size)
 {
-    cmsBool status;
     cmsUInt32Number pfSize = 0;
-    cmsUInt8Number* pfBuffer = NULL;
+    const cmsInt32Number tagCount = cmsGetTagCount(pfTarget);
+    cmsInt32Number i;
+    cmsHPROFILE pfSanity = NULL;
+
+    cmsICCHeader hdr = { 0 };
 
     cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL);
-    if (NULL != p) {
-        cmsICCHeader hdr = { 0 };
+
+    if (NULL == p) {
+        return NULL;
+    }
 
-        /* Populate the placeholder's header according to target profile */
-        hdr.flags = cmsGetHeaderFlags(pfTarget);
-        hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
-        hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
-        hdr.model = cmsGetHeaderModel(pfTarget);
-        hdr.pcs = cmsGetPCS(pfTarget);
-        hdr.colorSpace = cmsGetColorSpace(pfTarget);
-        hdr.deviceClass = cmsGetDeviceClass(pfTarget);
-        hdr.version = cmsGetEncodedICCversion(pfTarget);
-        cmsGetHeaderAttributes(pfTarget, &hdr.attributes);
-        cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID);
+    // Populate the placeholder's header according to target profile
+    hdr.flags = cmsGetHeaderFlags(pfTarget);
+    hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget);
+    hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget);
+    hdr.model = cmsGetHeaderModel(pfTarget);
+    hdr.pcs = cmsGetPCS(pfTarget);
+    hdr.colorSpace = cmsGetColorSpace(pfTarget);
+    hdr.deviceClass = cmsGetDeviceClass(pfTarget);
+    hdr.version = cmsGetEncodedICCversion(pfTarget);
+    cmsGetHeaderAttributes(pfTarget, &hdr.attributes);
+    cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID);
 
-        cmsSetHeaderFlags(p, hdr.flags);
-        cmsSetHeaderManufacturer(p, hdr.manufacturer);
-        cmsSetHeaderModel(p, hdr.model);
-        cmsSetHeaderAttributes(p, hdr.attributes);
-        cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID));
-        cmsSetHeaderRenderingIntent(p, hdr.renderingIntent);
-        cmsSetPCS(p, hdr.pcs);
-        cmsSetColorSpace(p, hdr.colorSpace);
-        cmsSetDeviceClass(p, hdr.deviceClass);
-        cmsSetEncodedICCversion(p, hdr.version);
+    cmsSetHeaderFlags(p, hdr.flags);
+    cmsSetHeaderManufacturer(p, hdr.manufacturer);
+    cmsSetHeaderModel(p, hdr.model);
+    cmsSetHeaderAttributes(p, hdr.attributes);
+    cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID));
+    cmsSetHeaderRenderingIntent(p, hdr.renderingIntent);
+    cmsSetPCS(p, hdr.pcs);
+    cmsSetColorSpace(p, hdr.colorSpace);
+    cmsSetDeviceClass(p, hdr.deviceClass);
+    cmsSetEncodedICCversion(p, hdr.version);
+
+    // now write the user supplied tag
+    if (size <= 0 || !cmsWriteRawTag(p, sig, pData, size)) {
+        cmsCloseProfile(p);
+        return NULL;
+    }
 
+    // copy tags from the original profile
+    for (i = 0; i < tagCount; i++) {
+        cmsBool isTagReady = FALSE;
+        const cmsTagSignature s = cmsGetTagSignature(pfTarget, i);
+        const cmsInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0);
 
-        if (cmsWriteRawTag(p, sig, pData, size)) {
-            if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
-                pfBuffer = malloc(pfSize);
-                if (pfBuffer != NULL) {
-                    /* load raw profile data into the buffer */
-                    if (!cmsSaveProfileToMem(p, pfBuffer, &pfSize)) {
-                        free(pfBuffer);
-                        pfBuffer = NULL;
-                    }
+        if (s == sig) {
+            // skip the user supplied tag
+            continue;
+        }
+
+        // read raw tag from the original profile
+        if (tagSize > 0) {
+            cmsUInt8Number* buf = (cmsUInt8Number*)malloc(tagSize);
+            if (buf != NULL) {
+                if (tagSize ==  cmsReadRawTag(pfTarget, s, buf, tagSize)) {
+                    // now we are ready to write the tag
+                    isTagReady = cmsWriteRawTag(p, s, buf, tagSize);
                 }
+                free(buf);
             }
         }
-        cmsCloseProfile(p);
+
+        if (!isTagReady) {
+            cmsCloseProfile(p);
+            return NULL;
+        }
     }
 
-    if (pfBuffer == NULL) {
-        return FALSE;
+    // now we have all tags moved to the new profile.
+    // do some sanity checks: write it to a memory buffer and read again.
+    if (cmsSaveProfileToMem(p, NULL, &pfSize)) {
+        void* buf = malloc(pfSize);
+        if (buf != NULL) {
+            // load raw profile data into the buffer
+            if (cmsSaveProfileToMem(p, buf, &pfSize)) {
+                pfSanity = cmsOpenProfileFromMem(buf, pfSize);
+            }
+            free(buf);
+        }
     }
 
-    /* re-open the placeholder profile */
-    p = cmsOpenProfileFromMem(pfBuffer, pfSize);
-    free(pfBuffer);
-    status = FALSE;
+    if (pfSanity == NULL) {
+        // for some reason, we failed to save and read the updated profile
+        // It likely indicates that the profile is not correct, so we report
+        // a failure here.
+        cmsCloseProfile(p);
+        p =  NULL;
+    } else {
+        // do final check whether we can read and handle the the target tag.
+        const void* pTag = cmsReadTag(pfSanity, sig);
+        if (pTag == NULL) {
+            // the tag can not be cooked
+            cmsCloseProfile(p);
+            p = NULL;
+        }
+        cmsCloseProfile(pfSanity);
+        pfSanity = NULL;
+    }
 
-    if (p != NULL) {
-        /* Note that pCookedTag points to internal structures of the placeholder,
-         * so this data is valid only while the placeholder is open.
-         */
-        void *pCookedTag = cmsReadTag(p, sig);
-        if (pCookedTag != NULL) {
-            status = cmsWriteTag(pfTarget, sig, pCookedTag);
-        }
-        pCookedTag = NULL;
-        cmsCloseProfile(p);
-    }
-    return status;
+    return p;
 }
--- a/jdk/src/solaris/classes/sun/font/XRTextRenderer.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/solaris/classes/sun/font/XRTextRenderer.java	Tue Sep 17 08:07:14 2013 -0700
@@ -142,7 +142,7 @@
             }
 
             int maskFormat = containsLCDGlyphs ? XRUtils.PictStandardARGB32 : XRUtils.PictStandardA8;
-            maskBuffer.compositeText(x11sd.picture, 0, maskFormat, eltList);
+            maskBuffer.compositeText(x11sd, (int) gl.getX(), (int) gl.getY(), 0, maskFormat, eltList);
 
             eltList.clear();
         } finally {
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java	Tue Sep 17 08:07:14 2013 -0700
@@ -267,8 +267,9 @@
 
     private static native void
         XRenderCompositeTextNative(int op, int src, int dst,
-                                   long maskFormat, int[] eltArray,
-                                   int[] glyphIDs, int eltCnt, int glyphCnt);
+                                   int srcX, int srcY, long maskFormat,
+                                   int[] eltArray, int[] glyphIDs, int eltCnt,
+                                   int glyphCnt);
 
     public int XRenderCreateGlyphSet(int formatID) {
         return XRenderCreateGlyphSetNative(getFormatPtr(formatID));
@@ -278,11 +279,11 @@
 
     public void XRenderCompositeText(byte op, int src, int dst,
                                      int maskFormatID,
-                                     int src2, int src3, int dst2, int dst3,
+                                     int sx, int sy, int dx, int dy,
                                      int glyphset, GrowableEltArray elts) {
 
         GrowableIntArray glyphs = elts.getGlyphs();
-        XRenderCompositeTextNative(op, src, dst, 0, elts.getArray(),
+        XRenderCompositeTextNative(op, src, dst, sx, sy, 0, elts.getArray(),
                                    glyphs.getArray(), elts.getSize(),
                                    glyphs.getSize());
     }
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java	Tue Sep 17 08:07:14 2013 -0700
@@ -285,7 +285,12 @@
         if (xorEnabled) {
             con.GCRectangles(dst.getXid(), dst.getGC(), rects);
         } else {
-            con.renderRectangles(dst.getPicture(), compRule, solidColor, rects);
+            if (rects.getSize() == 1) {
+                con.renderRectangle(dst.getPicture(), compRule, solidColor,
+                        rects.getX(0), rects.getY(0), rects.getWidth(0), rects.getHeight(0));
+            } else {
+                con.renderRectangles(dst.getPicture(), compRule, solidColor, rects);
+            }
         }
     }
 
@@ -295,10 +300,10 @@
                 sy, 0, 0, dx, dy, w, h);
     }
 
-    public void compositeText(int dst, int glyphSet, int maskFormat,
-            GrowableEltArray elts) {
-        con.XRenderCompositeText(compRule, src.picture, dst, maskFormat, 0, 0,
-                0, 0, glyphSet, elts);
+    public void compositeText(XRSurfaceData dst, int sx, int sy,
+            int glyphSet, int maskFormat, GrowableEltArray elts) {
+        con.XRenderCompositeText(compRule, src.picture, dst.picture,
+                maskFormat, sx, sy, 0, 0, glyphSet, elts);
     }
 
     public XRColor getMaskColor() {
--- a/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java	Tue Sep 17 08:07:14 2013 -0700
@@ -225,6 +225,9 @@
  * @author Clemens Eisserer
  */
 class XRPMTransformedBlit extends TransformBlit {
+    final Rectangle compositeBounds = new Rectangle();
+    final double[] srcCoords = new double[8];
+    final double[] dstCoords = new double[8];
 
     public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {
         super(srcType, CompositeType.AnyAlpha, dstType);
@@ -235,61 +238,68 @@
      * method is functionally equal to: Shape shp =
      * xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds();
      * but performs significantly better.
+     * Returns true if the destination shape is parallel to x/y axis
      */
-    public Rectangle getCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) {
-        double[] compBounds = new double[8];
-        compBounds[0] = dstx;
-        compBounds[1] = dsty;
-        compBounds[2] = dstx + width;
-        compBounds[3] = dsty;
-        compBounds[4] = dstx + width;
-        compBounds[5] = dsty + height;
-        compBounds[6] = dstx;
-        compBounds[7] = dsty + height;
+    protected boolean adjustCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) {
+        srcCoords[0] = dstx;
+        srcCoords[1] = dsty;
+        srcCoords[2] = dstx + width;
+        srcCoords[3] = dsty;
+        srcCoords[4] = dstx + width;
+        srcCoords[5] = dsty + height;
+        srcCoords[6] = dstx;
+        srcCoords[7] = dsty + height;
+
+        tr.transform(srcCoords, 0, dstCoords, 0, 4);
 
-        tr.transform(compBounds, 0, compBounds, 0, 4);
+        double minX = Math.min(dstCoords[0], Math.min(dstCoords[2], Math.min(dstCoords[4], dstCoords[6])));
+        double minY = Math.min(dstCoords[1], Math.min(dstCoords[3], Math.min(dstCoords[5], dstCoords[7])));
+        double maxX = Math.max(dstCoords[0], Math.max(dstCoords[2], Math.max(dstCoords[4], dstCoords[6])));
+        double maxY = Math.max(dstCoords[1], Math.max(dstCoords[3], Math.max(dstCoords[5], dstCoords[7])));
 
-        double minX = Math.min(compBounds[0], Math.min(compBounds[2], Math.min(compBounds[4], compBounds[6])));
-        double minY = Math.min(compBounds[1], Math.min(compBounds[3], Math.min(compBounds[5], compBounds[7])));
-        double maxX = Math.max(compBounds[0], Math.max(compBounds[2], Math.max(compBounds[4], compBounds[6])));
-        double maxY = Math.max(compBounds[1], Math.max(compBounds[3], Math.max(compBounds[5], compBounds[7])));
+        minX = Math.round(minX);
+        minY = Math.round(minY);
+        maxX = Math.round(maxX);
+        maxY = Math.round(maxY);
 
-        minX = Math.floor(minX);
-        minY = Math.floor(minY);
-        maxX = Math.ceil(maxX);
-        maxY = Math.ceil(maxY);
+        compositeBounds.x = (int) minX;
+        compositeBounds.y = (int) minY;
+        compositeBounds.width = (int) (maxX - minX);
+        compositeBounds.height = (int) (maxY - minY);
 
-        return new Rectangle((int) minX, (int) minY, (int) (maxX - minX), (int) (maxY - minY));
+        boolean is0or180 = (dstCoords[1] == dstCoords[3]) && (dstCoords[2] == dstCoords[4]);
+        boolean is90or270 = (dstCoords[0] == dstCoords[2]) && (dstCoords[3] == dstCoords[5]);
+
+        return is0or180 || is90or270;
     }
 
-    public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int srcx, int srcy,
-            int dstx, int dsty, int width, int height) {
+    public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform,
+            int hint, int srcx, int srcy, int dstx, int dsty, int width, int height) {
         try {
             SunToolkit.awtLock();
 
-            int filter = XRUtils.ATransOpToXRQuality(hint);
+            XRSurfaceData x11sdDst = (XRSurfaceData) dst;
+            XRSurfaceData x11sdSrc = (XRSurfaceData) src;
 
-            XRSurfaceData x11sdDst = (XRSurfaceData) dst;
+            int filter = XRUtils.ATransOpToXRQuality(hint);
+            boolean isAxisAligned = adjustCompositeBounds(xform, dstx, dsty, width, height);
+
             x11sdDst.validateAsDestination(null, clip);
-            XRSurfaceData x11sdSrc = (XRSurfaceData) src;
             x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);
 
-            Rectangle bounds = getCompositeBounds(xform, dstx, dsty, width, height);
-
-            AffineTransform trx = AffineTransform.getTranslateInstance((-bounds.x), (-bounds.y));
+            AffineTransform trx = AffineTransform.getTranslateInstance(-compositeBounds.x, -compositeBounds.y);
             trx.concatenate(xform);
             AffineTransform maskTX = (AffineTransform) trx.clone();
-
             trx.translate(-srcx, -srcy);
 
             try {
                 trx.invert();
             } catch (NoninvertibleTransformException ex) {
                 trx.setToIdentity();
-                System.err.println("Reseted to identity!");
             }
 
-            boolean omitMask = isMaskOmittable(trx, comp, filter);
+            boolean omitMask = (filter == XRUtils.FAST)
+                    || (isAxisAligned && ((AlphaComposite) comp).getAlpha() == 1.0f);
 
             if (!omitMask) {
                 XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage();
@@ -297,33 +307,17 @@
                 x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter);
                 int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height);
                 x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture,
-                        0, 0, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height);
+                        0, 0, 0, 0, compositeBounds.x, compositeBounds.y, compositeBounds.width, compositeBounds.height);
             } else {
                 int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad;
 
                 x11sdSrc.validateAsSource(trx, repeat, filter);
-                x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height);
+                x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, compositeBounds.x, compositeBounds.y, compositeBounds.width, compositeBounds.height);
             }
         } finally {
             SunToolkit.awtUnlock();
         }
     }
-
-    /* TODO: Is mask ever omitable??? ... should be for 90 degree rotation and no shear, but we always need to use RepeatPad */
-    protected static boolean isMaskOmittable(AffineTransform trx, Composite comp, int filter) {
-        return (filter == XRUtils.FAST || trx.getTranslateX() == (int) trx.getTranslateX() /*
-                                                                                            * If
-                                                                                            * translate
-                                                                                            * is
-                                                                                            * integer
-                                                                                            * only
-                                                                                            */
-                && trx.getTranslateY() == (int) trx.getTranslateY() && (trx.getShearX() == 0 && trx.getShearY() == 0 // Only
-                // 90 degree
-                // rotation
-                || trx.getShearX() == -trx.getShearY())) && ((AlphaComposite) comp).getAlpha() == 1.0f; // No
-        // ExtraAlpha!=1
-    }
 }
 
 class XrSwToPMBlit extends Blit {
--- a/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c	Tue Sep 17 08:07:14 2013 -0700
@@ -911,8 +911,9 @@
 
 JNIEXPORT void JNICALL
 Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative
- (JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt,
-  jintArray eltArray, jintArray  glyphIDArray, jint eltCnt, jint glyphCnt) {
+ (JNIEnv *env, jclass cls, jint op, jint src, jint dst,
+  jint sx, jint sy, jlong maskFmt, jintArray eltArray,
+  jintArray  glyphIDArray, jint eltCnt, jint glyphCnt) {
     jint i;
     jint *ids;
     jint *elts;
@@ -991,7 +992,7 @@
 
     XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst,
                            (XRenderPictFormat *) jlong_to_ptr(maskFmt),
-                            0, 0, 0, 0, xelts, eltCnt);
+                            sx, sy, 0, 0, xelts, eltCnt);
 
     (*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT);
     (*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT);
--- a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java	Tue Sep 17 08:07:14 2013 -0700
@@ -179,6 +179,7 @@
     private static final int SET_RES_LOW = 0x00000080;
     private static final int SET_COLOR = 0x00000200;
     private static final int SET_ORIENTATION = 0x00004000;
+    private static final int SET_COLLATED    = 0x00008000;
 
     /**
      * Values must match those defined in wingdi.h & commdlg.h
@@ -189,10 +190,33 @@
     private static final int PD_NOSELECTION = 0x00000004;
     private static final int PD_COLLATE = 0x00000010;
     private static final int PD_PRINTTOFILE = 0x00000020;
-    private static final int DM_ORIENTATION = 0x00000001;
-    private static final int DM_PRINTQUALITY = 0x00000400;
-    private static final int DM_COLOR = 0x00000800;
-    private static final int DM_DUPLEX = 0x00001000;
+    private static final int DM_ORIENTATION   = 0x00000001;
+    private static final int DM_PAPERSIZE     = 0x00000002;
+    private static final int DM_COPIES        = 0x00000100;
+    private static final int DM_DEFAULTSOURCE = 0x00000200;
+    private static final int DM_PRINTQUALITY  = 0x00000400;
+    private static final int DM_COLOR         = 0x00000800;
+    private static final int DM_DUPLEX        = 0x00001000;
+    private static final int DM_YRESOLUTION   = 0x00002000;
+    private static final int DM_COLLATE       = 0x00008000;
+
+    private static final short DMCOLLATE_FALSE  = 0;
+    private static final short DMCOLLATE_TRUE   = 1;
+
+    private static final short DMORIENT_PORTRAIT  = 1;
+    private static final short DMORIENT_LANDSCAPE = 2;
+
+    private static final short DMCOLOR_MONOCHROME = 1;
+    private static final short DMCOLOR_COLOR      = 2;
+
+    private static final short DMRES_DRAFT  = -1;
+    private static final short DMRES_LOW    = -2;
+    private static final short DMRES_MEDIUM = -3;
+    private static final short DMRES_HIGH   = -4;
+
+    private static final short DMDUP_SIMPLEX    = 1;
+    private static final short DMDUP_VERTICAL   = 2;
+    private static final short DMDUP_HORIZONTAL = 3;
 
     /**
      * Pageable MAX pages
@@ -592,13 +616,23 @@
         }
         driverDoesMultipleCopies = false;
         driverDoesCollation = false;
-        setNativePrintService(service.getName());
+        setNativePrintServiceIfNeeded(service.getName());
     }
 
     /* associates this job with the specified native service */
     private native void setNativePrintService(String name)
         throws PrinterException;
 
+    private String lastNativeService = null;
+    private void setNativePrintServiceIfNeeded(String name)
+        throws PrinterException {
+
+        if (name != null && !(name.equals(lastNativeService))) {
+            setNativePrintService(name);
+            lastNativeService = name;
+        }
+    }
+
     public PrintService getPrintService() {
         if (myService == null) {
             String printerName = getNativePrintService();
@@ -616,7 +650,7 @@
             myService = PrintServiceLookup.lookupDefaultPrintService();
             if (myService != null) {
                 try {
-                    setNativePrintService(myService.getName());
+                    setNativePrintServiceIfNeeded(myService.getName());
                 } catch (Exception e) {
                     myService = null;
                 }
@@ -1754,8 +1788,13 @@
         mAttMediaSizeName = ((Win32PrintService)myService).findPaperID(msn);
     }
 
-    private void setWin32MediaAttrib(int dmIndex, int width, int length) {
-       MediaSizeName msn =
+    private void addPaperSize(PrintRequestAttributeSet aset,
+                              int dmIndex, int width, int length) {
+
+        if (aset == null) {
+            return;
+        }
+        MediaSizeName msn =
            ((Win32PrintService)myService).findWin32Media(dmIndex);
         if (msn == null) {
             msn = ((Win32PrintService)myService).
@@ -1763,10 +1802,12 @@
         }
 
         if (msn != null) {
-            if (attributes != null) {
-                attributes.add(msn);
-            }
+            aset.add(msn);
         }
+    }
+
+    private void setWin32MediaAttrib(int dmIndex, int width, int length) {
+        addPaperSize(attributes, dmIndex, width, length);
         mAttMediaSizeName = dmIndex;
     }
 
@@ -1788,7 +1829,7 @@
             // no equivalent predefined value
             mAttMediaTray = 7;              // DMBIN_AUTO
         } else if (attr == MediaTray.TOP) {
-            mAttMediaTray =1;               // DMBIN_UPPER
+            mAttMediaTray = 1;              // DMBIN_UPPER
         } else {
             if (attr instanceof Win32MediaTray) {
                 mAttMediaTray = ((Win32MediaTray)attr).winID;
@@ -1914,6 +1955,254 @@
         }
     }
 
+    private static final class DevModeValues {
+        int dmFields;
+        short copies;
+        short collate;
+        short color;
+        short duplex;
+        short orient;
+        short paper;
+        short bin;
+        short xres_quality;
+        short yres;
+    }
+
+    private void getDevModeValues(PrintRequestAttributeSet aset,
+                                  DevModeValues info) {
+
+        Copies c = (Copies)aset.get(Copies.class);
+        if (c != null) {
+            info.dmFields |= DM_COPIES;
+            info.copies = (short)c.getValue();
+        }
+
+        SheetCollate sc = (SheetCollate)aset.get(SheetCollate.class);
+        if (sc != null) {
+            info.dmFields |= DM_COLLATE;
+            info.collate = (sc == SheetCollate.COLLATED) ?
+                DMCOLLATE_TRUE : DMCOLLATE_FALSE;
+        }
+
+        Chromaticity ch = (Chromaticity)aset.get(Chromaticity.class);
+        if (ch != null) {
+            info.dmFields |= DM_COLOR;
+            if (ch == Chromaticity.COLOR) {
+                info.color = DMCOLOR_COLOR;
+            } else {
+                info.color = DMCOLOR_MONOCHROME;
+            }
+        }
+
+        Sides s = (Sides)aset.get(Sides.class);
+        if (s != null) {
+            info.dmFields |= DM_DUPLEX;
+            if (s == Sides.TWO_SIDED_LONG_EDGE) {
+                info.duplex = DMDUP_VERTICAL;
+            } else if (s == Sides.TWO_SIDED_SHORT_EDGE) {
+                info.duplex = DMDUP_HORIZONTAL;
+            } else { // Sides.ONE_SIDED
+                info.duplex = DMDUP_SIMPLEX;
+            }
+        }
+
+        OrientationRequested or =
+            (OrientationRequested)aset.get(OrientationRequested.class);
+        if (or != null) {
+            info.dmFields |= DM_ORIENTATION;
+            info.orient = (or == OrientationRequested.LANDSCAPE)
+                ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;
+        }
+
+        Media m = (Media)aset.get(Media.class);
+        if (m instanceof MediaSizeName) {
+            info.dmFields |= DM_PAPERSIZE;
+            MediaSizeName msn = (MediaSizeName)m;
+            info.paper =
+                (short)((Win32PrintService)myService).findPaperID(msn);
+        }
+
+        MediaTray mt = null;
+        if (m instanceof MediaTray) {
+            mt = (MediaTray)m;
+        }
+        if (mt == null) {
+            SunAlternateMedia sam =
+                (SunAlternateMedia)aset.get(SunAlternateMedia.class);
+            if (sam != null && (sam.getMedia() instanceof MediaTray)) {
+                mt = (MediaTray)sam.getMedia();
+            }
+        }
+
+        if (mt != null) {
+            info.dmFields |= DM_DEFAULTSOURCE;
+            info.bin = (short)(((Win32PrintService)myService).findTrayID(mt));
+        }
+
+        PrintQuality q = (PrintQuality)aset.get(PrintQuality.class);
+        if (q != null) {
+            info.dmFields |= DM_PRINTQUALITY;
+            if (q == PrintQuality.DRAFT) {
+                info.xres_quality = DMRES_DRAFT;
+            } else if (q == PrintQuality.HIGH) {
+                info.xres_quality = DMRES_HIGH;
+            } else {
+                info.xres_quality = DMRES_MEDIUM;
+            }
+        }
+
+        PrinterResolution r =
+            (PrinterResolution)aset.get(PrinterResolution.class);
+        if (r != null) {
+            info.dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION;
+            info.xres_quality =
+                (short)r.getCrossFeedResolution(PrinterResolution.DPI);
+            info.yres = (short)r.getFeedResolution(PrinterResolution.DPI);
+        }
+    }
+
+    /* This method is called from native to update the values in the
+     * attribute set which originates from the cross-platform dialog,
+     * but updated by the native DocumentPropertiesUI which updates the
+     * devmode. This syncs the devmode back in to the attributes so that
+     * we can update the cross-platform dialog.
+     * The attribute set here is a temporary one installed whilst this
+     * happens,
+     */
+    private final void setJobAttributes(PrintRequestAttributeSet attributes,
+                                        int fields, int values,
+                                        short copies,
+                                        short dmPaperSize,
+                                        short dmPaperWidth,
+                                        short dmPaperLength,
+                                        short dmDefaultSource,
+                                        short xRes,
+                                        short yRes) {
+
+        if (attributes == null) {
+            return;
+        }
+
+        if ((fields & DM_COPIES) != 0) {
+            attributes.add(new Copies(copies));
+        }
+
+        if ((fields & DM_COLLATE) != 0) {
+            if ((values & SET_COLLATED) != 0) {
+                attributes.add(SheetCollate.COLLATED);
+            } else {
+                attributes.add(SheetCollate.UNCOLLATED);
+            }
+        }
+
+        if ((fields & DM_ORIENTATION) != 0) {
+            if ((values & SET_ORIENTATION) != 0) {
+                attributes.add(OrientationRequested.LANDSCAPE);
+            } else {
+                attributes.add(OrientationRequested.PORTRAIT);
+            }
+        }
+
+        if ((fields & DM_COLOR) != 0) {
+            if ((values & SET_COLOR) != 0) {
+                attributes.add(Chromaticity.COLOR);
+            } else {
+                attributes.add(Chromaticity.MONOCHROME);
+            }
+        }
+
+        if ((fields & DM_PRINTQUALITY) != 0) {
+            /* value < 0 indicates quality setting.
+             * value > 0 indicates X resolution. In that case
+             * hopefully we will also find y-resolution specified.
+             * If its not, assume its the same as x-res.
+             * Maybe Java code should try to reconcile this against
+             * the printers claimed set of supported resolutions.
+             */
+            if (xRes < 0) {
+                PrintQuality quality;
+                if ((values & SET_RES_LOW) != 0) {
+                    quality = PrintQuality.DRAFT;
+                } else if ((fields & SET_RES_HIGH) != 0) {
+                    quality = PrintQuality.HIGH;
+                } else {
+                    quality = PrintQuality.NORMAL;
+                }
+                attributes.add(quality);
+            } else if (xRes > 0 && yRes > 0) {
+                attributes.add(
+                    new PrinterResolution(xRes, yRes, PrinterResolution.DPI));
+            }
+        }
+
+        if ((fields & DM_DUPLEX) != 0) {
+            Sides sides;
+            if ((values & SET_DUP_VERTICAL) != 0) {
+                sides = Sides.TWO_SIDED_LONG_EDGE;
+            } else if ((values & SET_DUP_HORIZONTAL) != 0) {
+                sides = Sides.TWO_SIDED_SHORT_EDGE;
+            } else {
+                sides = Sides.ONE_SIDED;
+            }
+            attributes.add(sides);
+        }
+
+        if ((fields & DM_PAPERSIZE) != 0) {
+            addPaperSize(attributes, dmPaperSize, dmPaperWidth, dmPaperLength);
+        }
+
+        if ((fields & DM_DEFAULTSOURCE) != 0) {
+            MediaTray tray =
+                ((Win32PrintService)myService).findMediaTray(dmDefaultSource);
+            attributes.add(new SunAlternateMedia(tray));
+        }
+    }
+
+    private native boolean showDocProperties(long hWnd,
+                                             PrintRequestAttributeSet aset,
+                                             int dmFields,
+                                             short copies,
+                                             short collate,
+                                             short color,
+                                             short duplex,
+                                             short orient,
+                                             short paper,
+                                             short bin,
+                                             short xres_quality,
+                                             short yres);
+
+    @SuppressWarnings("deprecation")
+    public PrintRequestAttributeSet
+        showDocumentProperties(Window owner,
+                               PrintService service,
+                               PrintRequestAttributeSet aset)
+    {
+        try {
+            setNativePrintServiceIfNeeded(service.getName());
+        } catch (PrinterException e) {
+        }
+        long hWnd = ((WWindowPeer)(owner.getPeer())).getHWnd();
+        DevModeValues info = new DevModeValues();
+        getDevModeValues(aset, info);
+        boolean ok =
+            showDocProperties(hWnd, aset,
+                              info.dmFields,
+                              info.copies,
+                              info.collate,
+                              info.color,
+                              info.duplex,
+                              info.orient,
+                              info.paper,
+                              info.bin,
+                              info.xres_quality,
+                              info.yres);
+
+        if (ok) {
+            return aset;
+        } else {
+            return null;
+        }
+    }
 
     /* Printer Resolution. See also getXRes() and getYRes() */
     private final void setResolutionDPI(int xres, int yres) {
@@ -1956,7 +2245,7 @@
         }
     //** END Functions called by native code for querying/updating attributes
 
-   }
+    }
 
 class PrintToFileErrorDialog extends Dialog implements ActionListener{
     public PrintToFileErrorDialog(Frame parent, String title, String message,
--- a/jdk/src/windows/classes/sun/print/Win32MediaTray.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/windows/classes/sun/print/Win32MediaTray.java	Tue Sep 17 08:07:14 2013 -0700
@@ -70,6 +70,10 @@
         winEnumTable.add(this);
     }
 
+    public int getDMBinID() {
+        return winID;
+    }
+
     private static final String[] myStringTable ={
         "Manual-Envelope",
         "Automatic-Feeder",
--- a/jdk/src/windows/classes/sun/print/Win32PrintService.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/windows/classes/sun/print/Win32PrintService.java	Tue Sep 17 08:07:14 2013 -0700
@@ -25,6 +25,8 @@
 
 package sun.print;
 
+import java.awt.Window;
+import java.awt.print.PrinterJob;
 import java.io.File;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -39,6 +41,7 @@
 import javax.print.attribute.AttributeSetUtilities;
 import javax.print.attribute.EnumSyntax;
 import javax.print.attribute.HashAttributeSet;
+import javax.print.attribute.PrintRequestAttributeSet;
 import javax.print.attribute.PrintServiceAttribute;
 import javax.print.attribute.PrintServiceAttributeSet;
 import javax.print.attribute.HashPrintServiceAttributeSet;
@@ -69,6 +72,7 @@
 import javax.print.attribute.standard.PrinterResolution;
 import javax.print.attribute.standard.SheetCollate;
 import javax.print.event.PrintServiceAttributeListener;
+import sun.awt.windows.WPrinterJob;
 
 public class Win32PrintService implements PrintService, AttributeUpdater,
                                           SunPrinterJobService {
@@ -282,6 +286,22 @@
         return 0;
     }
 
+    public int findTrayID(MediaTray tray) {
+
+        getMediaTrays(); // make sure they are initialised.
+
+        if (tray instanceof Win32MediaTray) {
+            Win32MediaTray winTray = (Win32MediaTray)tray;
+            return winTray.getDMBinID();
+        }
+        for (int id=0; id<dmPaperBinToPrintService.length; id++) {
+            if (tray.equals(dmPaperBinToPrintService[id])) {
+                return id+1; // DMBIN_FIRST = 1;
+            }
+        }
+        return 0; // didn't find the tray
+    }
+
     public MediaTray findMediaTray(int dmBin) {
         if (dmBin >= 1 && dmBin <= dmPaperBinToPrintService.length) {
             return dmPaperBinToPrintService[dmBin-1];
@@ -673,7 +693,6 @@
         return arr2;
     }
 
-
     private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
         if (getJobStatus(printer, 2) != 1) {
             return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
@@ -1596,8 +1615,76 @@
         }
     }
 
-    public ServiceUIFactory getServiceUIFactory() {
-        return null;
+    private Win32DocumentPropertiesUI docPropertiesUI = null;
+
+    private static class Win32DocumentPropertiesUI
+        extends DocumentPropertiesUI {
+
+        Win32PrintService service;
+
+        private Win32DocumentPropertiesUI(Win32PrintService s) {
+            service = s;
+        }
+
+        public PrintRequestAttributeSet
+            showDocumentProperties(PrinterJob job,
+                                   Window owner,
+                                   PrintService service,
+                                   PrintRequestAttributeSet aset) {
+
+            if (!(job instanceof WPrinterJob)) {
+                return null;
+            }
+            WPrinterJob wJob = (WPrinterJob)job;
+            return wJob.showDocumentProperties(owner, service, aset);
+        }
+    }
+
+    private synchronized DocumentPropertiesUI getDocumentPropertiesUI() {
+        return new Win32DocumentPropertiesUI(this);
+    }
+
+    private static class Win32ServiceUIFactory extends ServiceUIFactory {
+
+        Win32PrintService service;
+
+        Win32ServiceUIFactory(Win32PrintService s) {
+            service = s;
+        }
+
+        public Object getUI(int role, String ui) {
+            if (role <= ServiceUIFactory.MAIN_UIROLE) {
+                return null;
+            }
+            if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE &&
+                DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui))
+            {
+                return service.getDocumentPropertiesUI();
+            }
+            throw new IllegalArgumentException("Unsupported role");
+        }
+
+        public String[] getUIClassNamesForRole(int role) {
+
+            if (role <= ServiceUIFactory.MAIN_UIROLE) {
+                return null;
+            }
+            if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) {
+                String[] names = new String[0];
+                names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME;
+                return names;
+            }
+            throw new IllegalArgumentException("Unsupported role");
+        }
+    }
+
+    private Win32ServiceUIFactory uiFactory = null;
+
+    public synchronized ServiceUIFactory getServiceUIFactory() {
+        if (uiFactory == null) {
+            uiFactory = new Win32ServiceUIFactory(this);
+        }
+        return uiFactory;
     }
 
     public String toString() {
--- a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp	Tue Sep 17 08:07:14 2013 -0700
@@ -81,6 +81,7 @@
 jmethodID AwtPrintControl::setNativeAttID;
 jmethodID AwtPrintControl::setRangeCopiesID;
 jmethodID AwtPrintControl::setResID;
+jmethodID AwtPrintControl::setJobAttributesID;
 
 
 BOOL AwtPrintControl::IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) {
@@ -297,6 +298,10 @@
     AwtPrintControl::setPrinterID =
       env->GetMethodID(cls, "setPrinterNameAttrib", "(Ljava/lang/String;)V");
 
+    AwtPrintControl::setJobAttributesID =
+        env->GetMethodID(cls, "setJobAttributes",
+        "(Ljavax/print/attribute/PrintRequestAttributeSet;IISSSSSSS)V");
+
     DASSERT(AwtPrintControl::driverDoesMultipleCopiesID != NULL);
     DASSERT(AwtPrintControl::getPrintDCID != NULL);
     DASSERT(AwtPrintControl::setPrintDCID != NULL);
@@ -327,6 +332,7 @@
     DASSERT(AwtPrintControl::getSidesID != NULL);
     DASSERT(AwtPrintControl::getSelectID != NULL);
     DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL);
+    DASSERT(AwtPrintControl::setJobAttributesID != NULL);
 
 
     CATCH_BAD_ALLOC;
--- a/jdk/src/windows/native/sun/windows/awt_PrintControl.h	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.h	Tue Sep 17 08:07:14 2013 -0700
@@ -47,7 +47,6 @@
     static jmethodID setDevmodeID;
     static jmethodID getDevnamesID;
     static jmethodID setDevnamesID;
-
     static jmethodID getWin32MediaID;
     static jmethodID setWin32MediaID;
     static jmethodID getWin32MediaTrayID;
@@ -73,6 +72,7 @@
     static jmethodID setNativeAttID;
     static jmethodID setRangeCopiesID;
     static jmethodID setResID;
+    static jmethodID setJobAttributesID;
 
     static void initIDs(JNIEnv *env, jclass cls);
     static BOOL FindPrinter(jstring printerName, LPBYTE pPrinterEnum,
--- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp	Tue Sep 17 08:07:14 2013 -0700
@@ -329,6 +329,156 @@
 static int embolden(int currentWeight);
 static BOOL getPrintableArea(HDC pdc, HANDLE hDevMode, RectDouble *margin);
 
+
+
+/************************************************************************
+ * DocumentProperties native support
+ */
+
+/* Values must match those defined in WPrinterJob.java */
+static const DWORD SET_COLOR = 0x00000200;
+static const DWORD SET_ORIENTATION = 0x00004000;
+static const DWORD SET_COLLATED    = 0x00008000;
+static const DWORD SET_DUP_VERTICAL = 0x00000010;
+static const DWORD SET_DUP_HORIZONTAL = 0x00000020;
+static const DWORD SET_RES_HIGH = 0x00000040;
+static const DWORD SET_RES_LOW = 0x00000080;
+
+/*
+ * Copy DEVMODE state back into JobAttributes.
+ */
+
+static void UpdateJobAttributes(JNIEnv *env,
+                                jobject wJob,
+                                jobject attrSet,
+                                DEVMODE *devmode) {
+
+    DWORD dmValues = 0;
+    int xRes = 0, yRes = 0;
+
+    if (devmode->dmFields & DM_COLOR) {
+        if (devmode->dmColor == DMCOLOR_COLOR) {
+            dmValues |= SET_COLOR;
+        }
+    }
+
+    if (devmode->dmFields & DM_ORIENTATION) {
+        if (devmode->dmOrientation == DMORIENT_LANDSCAPE) {
+            dmValues |= SET_ORIENTATION;
+        }
+    }
+
+    if (devmode->dmFields & DM_COLLATE &&
+        devmode->dmCollate == DMCOLLATE_TRUE) {
+            dmValues |= SET_COLLATED;
+    }
+
+    if (devmode->dmFields & DM_PRINTQUALITY) {
+        /* value < 0 indicates quality setting.
+         * value > 0 indicates X resolution. In that case
+         * hopefully we will also find y-resolution specified.
+         * If its not, assume its the same as x-res.
+         * Maybe Java code should try to reconcile this against
+          * the printers claimed set of supported resolutions.
+         */
+        if (devmode->dmPrintQuality < 0) {
+            if (devmode->dmPrintQuality == DMRES_HIGH) {
+                dmValues |= SET_RES_HIGH;
+            } else if ((devmode->dmPrintQuality == DMRES_LOW) ||
+                       (devmode->dmPrintQuality == DMRES_DRAFT)) {
+                dmValues |= SET_RES_LOW;
+            }
+            /* else if (devmode->dmPrintQuality == DMRES_MEDIUM)
+             * will set to NORMAL.
+             */
+        } else {
+            xRes = devmode->dmPrintQuality;
+            yRes = (devmode->dmFields & DM_YRESOLUTION) ?
+                devmode->dmYResolution : devmode->dmPrintQuality;
+        }
+    }
+
+    if (devmode->dmFields & DM_DUPLEX) {
+        if (devmode->dmDuplex == DMDUP_HORIZONTAL) {
+            dmValues |= SET_DUP_HORIZONTAL;
+        } else if (devmode->dmDuplex == DMDUP_VERTICAL) {
+            dmValues |= SET_DUP_VERTICAL;
+        }
+    }
+
+    env->CallVoidMethod(wJob, AwtPrintControl::setJobAttributesID, attrSet,
+                        devmode->dmFields, dmValues, devmode->dmCopies,
+                        devmode->dmPaperSize, devmode->dmPaperWidth,
+                        devmode->dmPaperLength, devmode->dmDefaultSource,
+                        xRes, yRes);
+
+}
+
+JNIEXPORT jboolean JNICALL
+Java_sun_awt_windows_WPrinterJob_showDocProperties(JNIEnv *env,
+                                                   jobject wJob,
+                                                   jlong hWndParent,
+                                                   jobject attrSet,
+                                                   jint dmFields,
+                                                   jshort copies,
+                                                   jshort collate,
+                                                   jshort color,
+                                                   jshort duplex,
+                                                   jshort orient,
+                                                   jshort paper,
+                                                   jshort bin,
+                                                   jshort xres_quality,
+                                                   jshort yres)
+{
+    TRY;
+
+    HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, wJob);
+    HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, wJob);
+    DEVMODE *devmode = NULL;
+    DEVNAMES *devnames = NULL;
+    LONG rval = IDCANCEL;
+    jboolean ret = JNI_FALSE;
+
+    if (hDevMode != NULL && hDevNames != NULL) {
+        devmode = (DEVMODE *)::GlobalLock(hDevMode);
+        devnames = (DEVNAMES *)::GlobalLock(hDevNames);
+
+        LPTSTR lpdevnames = (LPTSTR)devnames;
+        // No need to call _tcsdup as we won't unlock until we are done.
+        LPTSTR printerName = lpdevnames+devnames->wDeviceOffset;
+        LPTSTR portName = lpdevnames+devnames->wOutputOffset;
+
+        HANDLE hPrinter;
+        if (::OpenPrinter(printerName, &hPrinter, NULL) == TRUE) {
+            devmode->dmFields |= dmFields;
+            devmode->dmCopies = copies;
+            devmode->dmCollate = collate;
+            devmode->dmColor = color;
+            devmode->dmDuplex = duplex;
+            devmode->dmOrientation = orient;
+            devmode->dmPrintQuality = xres_quality;
+            devmode->dmYResolution = yres;
+            devmode->dmPaperSize = paper;
+            devmode->dmDefaultSource = bin;
+
+            rval = ::DocumentProperties((HWND)hWndParent,
+                           hPrinter, printerName, devmode, devmode,
+                           DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT);
+            if (rval == IDOK) {
+                UpdateJobAttributes(env, wJob, attrSet, devmode);
+                ret = JNI_TRUE;
+            }
+            VERIFY(::ClosePrinter(hPrinter));
+        }
+        ::GlobalUnlock(hDevNames);
+        ::GlobalUnlock(hDevMode);
+    }
+
+    return ret;
+
+    CATCH_BAD_ALLOC_RET(0);
+}
+
 /************************************************************************
  * WPageDialog native methods
  */
@@ -732,7 +882,6 @@
         memset(&pd, 0, sizeof(PRINTDLG));
         pd.lStructSize = sizeof(PRINTDLG);
         pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
-
         if (::PrintDlg(&pd)) {
             printDC = pd.hDC;
             hDevMode = pd.hDevMode;
@@ -792,8 +941,19 @@
     jint imgPixelWid = GetDeviceCaps(printDC, HORZRES);
     jint imgPixelHgt = GetDeviceCaps(printDC, VERTRES);
 
+    // The DC may be obtained when we first selected the printer as a
+    // result of a call to setNativePrintService.
+    // If the Devmode was obtained later on from the DocumentProperties dialog
+    // the DC won't have been updated and its settings may be for PORTRAIT.
+    // This may happen in other cases too, but was observed for the above.
+    // To get a DC compatible with this devmode we should really call
+    // CreateDC() again to get a DC for the devmode we are using.
+    // The changes for that are a lot more risk, so to minimise that
+    // risk, assume its not LANDSCAPE unless width > height, even if the
+    // devmode says its LANDSCAPE.
     // if the values were obtained from a rotated device, swap.
-    if (getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) {
+    if ((getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) &&
+        (imgPixelWid > imgPixelHgt)) {
       jint tmp;
       tmp = xPixelRes;
       xPixelRes = yPixelRes;
@@ -941,6 +1101,9 @@
             setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE);
         }
 
+        if (dmFields & DM_COPIES) {
+            setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE);
+        }
     }
 
     CATCH_BAD_ALLOC;
--- a/jdk/test/javax/imageio/plugins/jpeg/JpegWriterLeakTest.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/test/javax/imageio/plugins/jpeg/JpegWriterLeakTest.java	Tue Sep 17 08:07:14 2013 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug     8020983
+ * @bug     8020983 8024697
  * @summary Test verifies that jpeg writer instances are collected
  *          even if destroy() or reset() methods is not invoked.
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/java2d/cmm/ProfileOp/DisposalCrashTest.java	Tue Sep 17 08:07:14 2013 -0700
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug     8024511
+ * @summary Verifies that instances of color profiles are destroyed correctly.
+ *          A crash during profile destruction indicates failure.
+ *
+ * @run     main DisposalCrashTest
+ */
+
+import static java.awt.color.ColorSpace.*;
+import java.awt.color.ICC_Profile;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Vector;
+
+public class DisposalCrashTest {
+
+    static final ReferenceQueue<ICC_Profile> queue = new ReferenceQueue<>();
+    static final Vector<Reference<? extends ICC_Profile>> v = new Vector<>();
+
+    public static void main(String[] args) {
+        int[] ids = new int[]{
+            CS_sRGB, CS_CIEXYZ, CS_GRAY, CS_LINEAR_RGB, CS_PYCC
+        };
+
+        for (int id : ids) {
+            ICC_Profile p = getCopyOf(id);
+        }
+
+        while (!v.isEmpty()) {
+            System.gc();
+            System.out.println(".");
+            try {
+                Thread.sleep(500);
+            } catch (InterruptedException e) {};
+
+            final Reference<? extends ICC_Profile> ref = queue.poll();
+            System.out.println("Got reference: " + ref);
+
+            v.remove(ref);
+        }
+
+        System.out.println("Test PASSED.");
+    }
+
+    private static ICC_Profile getCopyOf(int id) {
+        ICC_Profile std = ICC_Profile.getInstance(id);
+
+        byte[] data = std.getData();
+
+        ICC_Profile p = ICC_Profile.getInstance(data);
+
+        WeakReference<ICC_Profile> ref = new WeakReference<>(p, queue);
+
+        v.add(ref);
+
+        return p;
+    }
+}
--- a/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java	Thu Sep 12 11:09:11 2013 -0700
+++ b/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java	Tue Sep 17 08:07:14 2013 -0700
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 6476665 6523403 6733501 7042594
+ * @bug 6476665 6523403 6733501 7042594 7043064
  * @summary Verifies reading and writing profiles and tags of the standard color
  * spaces
  * @run main ReadWriteProfileTest
@@ -82,6 +82,7 @@
 
     public void run() {
         for (int i = 0; i < cspaces.length; i++) {
+            System.out.println("Profile: " + csNames[i]);
             ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]);
             byte [] data = pf.getData();
             pf = ICC_Profile.getInstance(data);
@@ -92,6 +93,10 @@
             }
 
             for (int tagSig : tags[i].keySet()) {
+                String signature = SigToString(tagSig);
+                System.out.printf("Tag: %s\n", signature);
+                System.out.flush();
+
                 byte [] tagData = pf.getData(tagSig);
                 byte [] empty = new byte[tagData.length];
                 boolean emptyDataRejected = false;
@@ -104,15 +109,23 @@
                     throw new
                         RuntimeException("Test failed: empty tag data was not rejected.");
                 }
-                pf.setData(tagSig, tagData);
-
+                try {
+                    pf.setData(tagSig, tagData);
+                } catch (IllegalArgumentException e) {
+                    // let's ignore this exception for Kodak proprietary tags
+                    if (isKodakExtention(signature)) {
+                        System.out.println("Ignore Kodak tag: " + signature);
+                    } else {
+                        throw new RuntimeException("Test failed!", e);
+                    }
+                }
                 byte [] tagData1 = pf.getData(tagSig);
 
                 if (!Arrays.equals(tagData1, tags[i].get(tagSig)))
                 {
                     System.err.println("Incorrect result of getData(int) with" +
                                        " tag " +
-                                       Integer.toHexString(tagSig) +
+                                       SigToString(tagSig) +
                                        " of " + csNames[i] + " profile");
 
                     throw new RuntimeException("Incorrect result of " +
@@ -122,6 +135,19 @@
         }
     }
 
+    private static boolean isKodakExtention(String signature) {
+        return signature.matches("K\\d\\d\\d");
+    }
+
+    private static String SigToString(int tagSig ) {
+              return String.format("%c%c%c%c",
+                        (char)(0xff & (tagSig >> 24)),
+                        (char)(0xff & (tagSig >> 16)),
+                        (char)(0xff & (tagSig >>  8)),
+                        (char)(0xff & (tagSig)));
+
+    }
+
     public static void main(String [] args) {
         ReadWriteProfileTest test = new ReadWriteProfileTest();
         test.run();