changeset 2195:d5fa47c76cbb

Automated merge with ssh://jpgodine@jfxsrc.us.oracle.com//javafx/8.0/MASTER/jfx/rt
author jgodinez
date Fri, 11 Jan 2013 09:03:56 -0800
parents 77f24088cf92 0690808f8133
children 76c97d9afe5a 2b6f25bf2b7b
files
diffstat 25 files changed, 631 insertions(+), 372 deletions(-) [+]
line wrap: on
line diff
--- a/javafx-fxml/src/javafx/fxml/FXMLLoader.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-fxml/src/javafx/fxml/FXMLLoader.java	Fri Jan 11 09:03:56 2013 -0800
@@ -87,6 +87,7 @@
 import com.sun.javafx.fxml.expression.Expression;
 import com.sun.javafx.fxml.expression.ExpressionValue;
 import com.sun.javafx.fxml.expression.KeyPath;
+import java.net.MalformedURLException;
 
 /**
  * Loads an object hierarchy from an XML document.
@@ -275,171 +276,209 @@
         @SuppressWarnings("unchecked")
         public void processPropertyAttribute(Attribute attribute) throws IOException {
             String value = attribute.value;
-
-            if (value.startsWith(ESCAPE_PREFIX)) {
-                value = value.substring(ESCAPE_PREFIX.length());
-
-                if (value.length() == 0
-                    || !(value.startsWith(ESCAPE_PREFIX)
-                        || value.startsWith(RELATIVE_PATH_PREFIX)
-                        || value.startsWith(RESOURCE_KEY_PREFIX)
-                        || value.startsWith(EXPRESSION_PREFIX)
-                        || value.startsWith(BI_DIRECTIONAL_BINDING_PREFIX))) {
+            if (isBindingExpression(value)) {
+                // Resolve the expression
+                Expression expression;
+
+                if (attribute.sourceType != null) {
+                    throw new LoadException("Cannot bind to static property.");
+                }
+
+                if (!isTyped()) {
+                    throw new LoadException("Cannot bind to untyped object.");
+                }
+
+                // TODO We may want to identify binding properties in processAttribute()
+                // and apply them after build() has been called
+                if (this.value instanceof Builder) {
+                    throw new LoadException("Cannot bind to builder property.");
+                }
+
+                value = value.substring(BINDING_EXPRESSION_PREFIX.length(),
+                        value.length() - 1);
+                expression = Expression.valueOf(value);
+
+                // Create the binding
+                BeanAdapter targetAdapter = new BeanAdapter(this.value);
+                ObservableValue<Object> propertyModel = targetAdapter.getPropertyModel(attribute.name);
+                Class<?> type = targetAdapter.getType(attribute.name);
+
+                if (propertyModel instanceof Property<?>) {
+                    ((Property<Object>)propertyModel).bind(new ExpressionValue(namespace, expression, type));
+                }
+            } else if (isBidirectionalBindingExpression(value)) {
+                throw new UnsupportedOperationException("This feature is not currently enabled.");
+            } else {
+                processValue(attribute.sourceType, attribute.name, value);
+            }
+        }
+
+        private boolean isBindingExpression(String aValue) {
+            return aValue.startsWith(BINDING_EXPRESSION_PREFIX)
+                   && aValue.endsWith(BINDING_EXPRESSION_SUFFIX);
+        }
+
+        private boolean isBidirectionalBindingExpression(String aValue) {
+            return aValue.startsWith(BI_DIRECTIONAL_BINDING_PREFIX);
+        }
+
+        private boolean processValue(Class sourceType, String propertyName, String aValue)
+            throws LoadException {
+
+            boolean processed = false;
+                //process list or array first
+                if (sourceType == null && isTyped()) {
+                    BeanAdapter valueAdapter = getValueAdapter();
+                    Class<?> type = valueAdapter.getType(propertyName);
+
+                    if (type == null) {
+                        throw new PropertyNotFoundException("Property \"" + propertyName
+                            + "\" does not exist" + " or is read-only.");
+                    }
+
+                    if (List.class.isAssignableFrom(type)
+                        && valueAdapter.isReadOnly(propertyName)) {
+                        populateListFromString(valueAdapter, propertyName, aValue);
+                        processed = true;
+                    } else if (type.isArray()) {
+                        applyProperty(propertyName, sourceType,
+                                populateArrayFromString(type, aValue));
+                        processed = true;
+                    }
+                }
+                if (!processed) {
+                    applyProperty(propertyName, sourceType, resolvePrefixedValue(aValue));
+                    processed = true;
+                }
+                return processed;
+        }
+
+        /**
+         * Resolves value prefixed with RELATIVE_PATH_PREFIX and RESOURCE_KEY_PREFIX.
+         */
+        private Object resolvePrefixedValue(String aValue) throws LoadException {
+            if (aValue.startsWith(ESCAPE_PREFIX)) {
+                aValue = aValue.substring(ESCAPE_PREFIX.length());
+
+                if (aValue.length() == 0
+                    || !(aValue.startsWith(ESCAPE_PREFIX)
+                        || aValue.startsWith(RELATIVE_PATH_PREFIX)
+                        || aValue.startsWith(RESOURCE_KEY_PREFIX)
+                        || aValue.startsWith(EXPRESSION_PREFIX)
+                        || aValue.startsWith(BI_DIRECTIONAL_BINDING_PREFIX))) {
                     throw new LoadException("Invalid escape sequence.");
                 }
-
-                applyProperty(attribute.name, attribute.sourceType, value);
-            } else if (value.startsWith(RELATIVE_PATH_PREFIX)) {
-                value = value.substring(RELATIVE_PATH_PREFIX.length());
-
-                if (value.startsWith(RELATIVE_PATH_PREFIX)) {
+                return aValue;
+            } else if (aValue.startsWith(RELATIVE_PATH_PREFIX)) {
+                aValue = aValue.substring(RELATIVE_PATH_PREFIX.length());
+                if (aValue.length() == 0) {
+                    throw new LoadException("Missing relative path.");
+                }
+                if (aValue.startsWith(RELATIVE_PATH_PREFIX)) {
                     // The prefix was escaped
                     warnDeprecatedEscapeSequence(RELATIVE_PATH_PREFIX);
-                    applyProperty(attribute.name, attribute.sourceType, value);
+                    return aValue;
                 } else {
-                    if (value.length() == 0) {
-                        throw new LoadException("Missing relative path.");
+                    try {
+                        return (aValue.charAt(0) == '/') ?
+                                classLoader.getResource(aValue.substring(1)).toString() :
+                                new URL(FXMLLoader.this.location, aValue).toString();
+                    } catch (MalformedURLException e) {
+                        System.err.println(FXMLLoader.this.location + "/" + aValue);
                     }
-
-                    URL location;
-                    if (value.charAt(0) == '/') {
-                        location = classLoader.getResource(value.substring(1));
-                    } else {
-                        if (FXMLLoader.this.location == null) {
-                            throw new LoadException("Base location is undefined.");
-                        }
-
-                        location = new URL(FXMLLoader.this.location, value);
-                    }
-
-                    applyProperty(attribute.name, attribute.sourceType, location);
                 }
-            } else if (value.startsWith(RESOURCE_KEY_PREFIX)) {
-                value = value.substring(RESOURCE_KEY_PREFIX.length());
-
-                if (value.startsWith(RESOURCE_KEY_PREFIX)) {
+            } else if (aValue.startsWith(RESOURCE_KEY_PREFIX)) {
+                aValue = aValue.substring(RESOURCE_KEY_PREFIX.length());
+                if (aValue.length() == 0) {
+                    throw new LoadException("Missing resource key.");
+                }
+                if (aValue.startsWith(RESOURCE_KEY_PREFIX)) {
                     // The prefix was escaped
                     warnDeprecatedEscapeSequence(RESOURCE_KEY_PREFIX);
-                    applyProperty(attribute.name, attribute.sourceType, value);
+                    return aValue;
                 } else {
-                    if (value.length() == 0) {
-                        throw new LoadException("Missing resource key.");
-                    }
-
                     // Resolve the resource value
                     if (resources == null) {
                         throw new LoadException("No resources specified.");
                     }
-
-                    if (!resources.containsKey(value)) {
-                        throw new LoadException("Resource \"" + value + "\" not found.");
+                    if (!resources.containsKey(aValue)) {
+                        throw new LoadException("Resource \"" + aValue + "\" not found.");
                     }
 
-                    applyProperty(attribute.name, attribute.sourceType, resources.getObject(value));
+                    return resources.getString(aValue);
                 }
-            } else if (value.startsWith(EXPRESSION_PREFIX)) {
-                value = value.substring(EXPRESSION_PREFIX.length());
-
-                if (value.startsWith(EXPRESSION_PREFIX)) {
+            } else if (aValue.startsWith(EXPRESSION_PREFIX)) {
+                aValue = aValue.substring(EXPRESSION_PREFIX.length());
+                if (aValue.length() == 0) {
+                    throw new LoadException("Missing expression.");
+                }
+                if (aValue.startsWith(EXPRESSION_PREFIX)) {
                     // The prefix was escaped
                     warnDeprecatedEscapeSequence(EXPRESSION_PREFIX);
-                    applyProperty(attribute.name, attribute.sourceType, value);
-                } else if (value.equals(NULL_KEYWORD)) {
+                    return aValue;
+                } else if (aValue.equals(NULL_KEYWORD)) {
                     // The attribute value is null
-                    applyProperty(attribute.name, attribute.sourceType, null);
-                } else {
-                    if (value.length() == 0) {
-                        throw new LoadException("Missing expression.");
-                    }
-
-                    // Resolve the expression
-                    Expression expression;
-                    if (value.startsWith(BINDING_EXPRESSION_PREFIX)
-                        && value.endsWith(BINDING_EXPRESSION_SUFFIX)) {
-                        if (attribute.sourceType != null) {
-                            throw new LoadException("Cannot bind to static property.");
-                        }
-
-                        if (!isTyped()) {
-                            throw new LoadException("Cannot bind to untyped object.");
-                        }
-
-                        // TODO We may want to identify binding properties in processAttribute()
-                        // and apply them after build() has been called
-                        if (this.value instanceof Builder) {
-                            throw new LoadException("Cannot bind to builder property.");
-                        }
-
-                        value = value.substring(1, value.length() - 1);
-                        expression = Expression.valueOf(value);
-
-                        // Create the binding
-                        BeanAdapter targetAdapter = new BeanAdapter(this.value);
-                        ObservableValue<Object> propertyModel = targetAdapter.getPropertyModel(attribute.name);
-                        Class<?> type = targetAdapter.getType(attribute.name);
-
-                        if (propertyModel instanceof Property<?>) {
-                            ((Property<Object>)propertyModel).bind(new ExpressionValue(namespace, expression, type));
-                        }
-                    } else {
-                        applyProperty(attribute.name, attribute.sourceType, Expression.get(namespace, KeyPath.parse(value)));
-                    }
+                    return null;
                 }
-            } else if (value.startsWith(BI_DIRECTIONAL_BINDING_PREFIX)) {
-                throw new UnsupportedOperationException("This feature is not currently enabled.");
+                return Expression.get(namespace, KeyPath.parse(aValue));
+            }
+            return aValue;
+        }
+
+        /**
+         * Creates an array of given type and populates it with values from
+         * a string where tokens are separated by ARRAY_COMPONENT_DELIMITER.
+         * If token is prefixed with RELATIVE_PATH_PREFIX a value added to
+         * the array becomes relative to document location.
+         */
+        private Object populateArrayFromString(
+                Class<?>type,
+                String stringValue) throws LoadException {
+
+            Object propertyValue = null;
+            // Split the string and set the values as an array
+            Class<?> componentType = type.getComponentType();
+
+            if (stringValue.length() > 0) {
+                String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
+                propertyValue = Array.newInstance(componentType, values.length);
+                for (int i = 0; i < values.length; i++) {
+                    Array.set(propertyValue, i,
+                            BeanAdapter.coerce(resolvePrefixedValue(values[i].trim()),
+                            type.getComponentType()));
+                }
             } else {
-                Object propertyValue = value;
-
-                if (attribute.sourceType == null && isTyped()) {
-                    BeanAdapter valueAdapter = getValueAdapter();
-                    Class<?> type = valueAdapter.getType(attribute.name);
-
-                    if (type == null) {
-                        throw new PropertyNotFoundException("Property \"" + attribute.name
-                            + "\" does not exist" + " or is read-only.");
-                    }
-
-                    if (List.class.isAssignableFrom(type)
-                        && valueAdapter.isReadOnly(attribute.name)) {
-                        // Split the string and add the values to the list
-                        List<Object> list = (List<Object>)valueAdapter.get(attribute.name);
-                        Type listType = valueAdapter.getGenericType(attribute.name);
-                        Type itemType = (Class<?>)BeanAdapter.getGenericListItemType(listType);
-
-                        if (itemType instanceof ParameterizedType) {
-                            itemType = ((ParameterizedType)itemType).getRawType();
-                        }
-
-                        String stringValue = value.toString();
-                        if (stringValue.length() > 0) {
-                            String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
-
-                            for (int i = 0; i < values.length; i++) {
-                                list.add(BeanAdapter.coerce(values[i].trim(), (Class<?>)itemType));
-                            }
-                        }
-
-                        propertyValue = null;
-                    } else if (type.isArray()) {
-                        // Split the string and set the values as an array
-                        Class<?> componentType = type.getComponentType();
-
-                        String stringValue = value.toString();
-                        if (stringValue.length() > 0) {
-                            String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
-                            propertyValue = Array.newInstance(componentType, values.length);
-                            for (int i = 0; i < values.length; i++) {
-                                Array.set(propertyValue, i, BeanAdapter.coerce(values[i].trim(),
-                                    type.getComponentType()));
-                            }
-                        } else {
-                            propertyValue = Array.newInstance(componentType, 0);
-                        }
-                    }
-                }
-
-                if (propertyValue != null) {
-                    applyProperty(attribute.name, attribute.sourceType, propertyValue);
+                propertyValue = Array.newInstance(componentType, 0);
+            }
+            return propertyValue;
+        }
+
+        /**
+         * Populates list with values from a string where tokens are separated
+         * by ARRAY_COMPONENT_DELIMITER. If token is prefixed with RELATIVE_PATH_PREFIX
+         * a value added to the list becomes relative to document location.
+         */
+        private void populateListFromString(
+                BeanAdapter valueAdapter,
+                String listPropertyName,
+                String stringValue) throws LoadException {
+            // Split the string and add the values to the list
+            List<Object> list = (List<Object>)valueAdapter.get(listPropertyName);
+            Type listType = valueAdapter.getGenericType(listPropertyName);
+            Type itemType = (Class<?>)BeanAdapter.getGenericListItemType(listType);
+
+            if (itemType instanceof ParameterizedType) {
+                itemType = ((ParameterizedType)itemType).getRawType();
+            }
+
+            if (stringValue.length() > 0) {
+                String[] values = stringValue.split(ARRAY_COMPONENT_DELIMITER);
+
+                for (String aValue: values) {
+                    aValue = aValue.trim();
+                    list.add(
+                            BeanAdapter.coerce(resolvePrefixedValue(aValue),
+                                               (Class<?>)itemType));
                 }
             }
         }
@@ -919,7 +958,7 @@
                 builderFactory, controllerFactory, charset,
                 loaders);
             fxmlLoader.parentLoader = FXMLLoader.this;
-            
+
             if (isCyclic(FXMLLoader.this, fxmlLoader)) {
                 throw new IOException(
                         String.format(
@@ -1090,17 +1129,7 @@
 
             Object value;
             if (root == null) {
-                value = (builderFactory == null) ? null : builderFactory.getBuilder(type);
-
-                if (value == null) {
-                    try {
-                        value = type.newInstance();
-                    } catch (InstantiationException exception) {
-                        throw new LoadException(exception);
-                    } catch (IllegalAccessException exception) {
-                        throw new LoadException(exception);
-                    }
-                }
+                throw new LoadException("Root hasn't been set. Use method setRoot() before load.");
             } else {
                 if (!type.isAssignableFrom(root.getClass())) {
                     throw new LoadException("Root is not an instance of "
@@ -1578,7 +1607,7 @@
     private ClassLoader classLoader = defaultClassLoader;
     private boolean staticLoad = false;
     private LoadListener loadListener = null;
-    
+
     private FXMLLoader parentLoader;
 
     private XMLStreamReader xmlStreamReader = null;
@@ -1642,7 +1671,7 @@
     public static final String RELATIVE_PATH_PREFIX = "@";
     public static final String RESOURCE_KEY_PREFIX = "%";
     public static final String EXPRESSION_PREFIX = "$";
-    public static final String BINDING_EXPRESSION_PREFIX = "{";
+    public static final String BINDING_EXPRESSION_PREFIX = "${";
     public static final String BINDING_EXPRESSION_SUFFIX = "}";
 
     public static final String BI_DIRECTIONAL_BINDING_PREFIX = "#{";
@@ -1831,20 +1860,20 @@
                     location.toExternalForm());
         }
         return false;
-    }            
-    
+    }
+
     private boolean isCyclic(
-                            FXMLLoader currentLoader, 
+                            FXMLLoader currentLoader,
                             FXMLLoader node) {
         if (currentLoader == null) {
             return false;
         }
         if (currentLoader.equals(node)) {
             return true;
-        }        
+        }
         return isCyclic(currentLoader.parentLoader, node);
     }
-        
+
     /**
      * Returns the controller associated with the root object.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/RT_26449Test.java	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010, 2012, 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 javafx.fxml;
+
+import java.io.IOException;
+
+import org.junit.Test;
+
+public class RT_26449Test {
+    @Test(expected=LoadException.class)
+    public void testRootNotSet() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_26449.fxml"));
+        fxmlLoader.load();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/RT_27529Test.java	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010, 2012, 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 javafx.fxml;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.ResourceBundle;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class RT_27529Test {
+    
+    @Test
+    public void testListAndArrayWithResources() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_1.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+            
+        Widget widget = (Widget)fxmlLoader.load();
+        assertEquals(Arrays.asList(new String[]{"a", "b", "c"}), widget.getStyles());
+        assertTrue(Arrays.equals(new String[]{"a", "b", "c"}, widget.getNames()));
+        assertTrue(Arrays.equals(new float[] {1.0f, 2.0f, 3.0f}, widget.getRatios()));
+    }
+    
+    @Test
+    public void testListAndArrayWithEscapes() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_2.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+        fxmlLoader.load();
+            
+        Widget widget = (Widget)fxmlLoader.getNamespace().get("widget1");
+        assertEquals(Arrays.asList(new String[]{"@a", "%b", "$c", "@c", "%d", "$e"}), widget.getStyles());
+        assertTrue(Arrays.equals(  new String[]{"@a", "%b", "$c", "@c", "%d", "$e"}, widget.getNames()));
+    }
+    
+    @Test
+    public void testListAndArrayWithRelativePath() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_3.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+            
+        Widget widget = (Widget)fxmlLoader.load();
+        assertEquals(Arrays.asList(new String[]{
+            new URL(fxmlLoader.getLocation(), "a").toString(),
+            new URL(fxmlLoader.getLocation(), "b").toString(),
+            new URL(fxmlLoader.getLocation(), "c").toString()}), widget.getStyles());
+    }
+    
+    @Test
+    public void testListAndArrayWithReference() throws IOException {
+        FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("rt_27529_4.fxml"),
+            ResourceBundle.getBundle("javafx/fxml/rt_27529"));
+            
+        fxmlLoader.load();
+        Widget widget = (Widget)fxmlLoader.getNamespace().get("widget1");
+        assertEquals(Arrays.asList(new String[]{"ABC", "ABC"}), widget.getStyles());
+        assertTrue(Arrays.equals(new String[]{"ABC", "ABC"}, widget.getNames()));
+        assertTrue(Arrays.equals(new float[] {1.0f, 1.0f}, widget.getRatios()));
+    }
+}
--- a/javafx-fxml/test/javafx/fxml/Widget.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-fxml/test/javafx/fxml/Widget.java	Fri Jan 11 09:03:56 2013 -0800
@@ -52,6 +52,7 @@
     private ArrayList<String> styles = new ArrayList<String>();
     private ArrayList<String> values = new ArrayList<String>();
     private float[] ratios = new float[]{};
+    private String[] names = new String[]{};
 
     public static final String ALIGNMENT_KEY = "alignment";
     public static final int TEN = 10;
@@ -144,6 +145,15 @@
     public void setRatios(float[] ratios) {
         this.ratios = Arrays.copyOf(ratios, ratios.length);
     }
+    
+    public String[] getNames() {
+        return Arrays.copyOf(names, names.length);
+    }
+
+    public void setNames(String[] names) {
+        this.names = Arrays.copyOf(names, names.length);
+    }
+
 
     public static Alignment getAlignment(Widget widget) {
         return (Alignment)widget.getProperties().get(ALIGNMENT_KEY);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_26449.fxml	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, 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.
+-->
+
+<?import javafx.scene.control.*?>
+
+<fx:root type="javafx.scene.layout.VBox" fx:id="default_root" xmlns:fx="http://javafx.com/fxml">
+    <Label text="Label in VBox"/>
+</fx:root>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529.properties	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,6 @@
+itema=a
+itemb=b
+itemc=c
+ratio1=1.0
+ratio2=2.0
+ratio3=3.0
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_1.fxml	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, 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.
+-->
+
+<?import javafx.fxml.*?>
+
+<Widget styles="%itema, %itemb, %itemc" names="%itema, %itemb, %itemc" ratios="%ratio1, %ratio2, %ratio3"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_2.fxml	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, 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.
+-->
+
+<?import javafx.fxml.*?>
+<?import java.lang.*?>
+<Widget xmlns:fx="http://javafx.com/fxml">
+    <Widget fx:id="widget1" 
+            styles="@@a, %%b, $$c, \@c, \%d, \$e" 
+            names="@@a, %%b, $$c, \@c, \%d, \$e,"
+            ratios="1.0, 2.0, 3.0"/>
+</Widget>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_3.fxml	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, 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.
+-->
+
+<?import javafx.fxml.*?>
+
+<Widget styles="@a, @b, @c" ratios="1.0, 2.0, 3.0"/>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javafx-fxml/test/javafx/fxml/rt_27529_4.fxml	Fri Jan 11 09:03:56 2013 -0800
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2010, 2012, 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.
+-->
+
+<?import javafx.fxml.*?>
+<?import java.lang.*?>
+
+<Widget xmlns:fx="http://javafx.com/fxml">
+    <fx:define>
+        <String fx:id="str" fx:value="ABC"/>
+        <Float fx:id="flt" fx:value="1.0f"/>
+    </fx:define>
+    <Widget fx:id="widget1" 
+            styles="$str, $str" 
+            names="$str, $str"
+            ratios="$flt, $flt"/>
+</Widget>
--- a/javafx-geom/src/com/sun/javafx/geom/transform/GeneralTransform3D.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-geom/src/com/sun/javafx/geom/transform/GeneralTransform3D.java	Fri Jan 11 09:03:56 2013 -0800
@@ -248,10 +248,8 @@
     /**
      * Sets the value of this transform to a perspective projection transform.
      * This transform maps points from Eye Coordinates (EC)
-     * to Clipping Coordinates (CC).  Note that unlike the similar function
-     * in OpenGL, the clipping coordinates generated by the resulting
-     * transform are in a right-handed coordinate system. Also note that the
-     * field of view is specified in radians.
+     * to Clipping Coordinates (CC).
+     * Note that the field of view is specified in radians.
      *
      * @param fovy specifies the field of view in the y direction, in radians
      *
@@ -280,9 +278,6 @@
 
         mat[0] = cotangent / aspect;
         mat[5] = cotangent;
-        // TODO: resolve whether perspective matrices are right-handed (ala Java 3D)
-        // or left-handed (ala OpenGL). Currently we assume OpenGL-style left-handed
-        // matrices. (RT-26887)
         mat[10] = -(zFar + zNear) / deltaZ;
         mat[11] = -2.0 * zNear * zFar / deltaZ;
         mat[14] = -1.0;
--- a/javafx-sg-common/src/com/sun/javafx/sg/PGRegion.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-sg-common/src/com/sun/javafx/sg/PGRegion.java	Fri Jan 11 09:03:56 2013 -0800
@@ -58,8 +58,9 @@
      * @param shape    The shape, may be null.
      * @param scaleShape whether to scale the shape
      * @param positionShape whether to center the shape
+     * @param cacheShape whether to attempt region caching for the shape-based region
      */
-    public void updateShape(Object shape, boolean scaleShape, boolean positionShape);
+    public void updateShape(Object shape, boolean scaleShape, boolean positionShape, boolean cacheShape);
 
     /**
      * The opaque insets as specified either by the user, or as determined by
--- a/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGRegion.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-sg-prism/src/com/sun/javafx/sg/prism/NGRegion.java	Fri Jan 11 09:03:56 2013 -0800
@@ -130,6 +130,11 @@
     private boolean centerShape = true;
 
     /**
+     * Whether we should attempt to use region caching for a region with a shape.
+     */
+    private boolean cacheShape = false;
+
+    /**
      * A cached set of the opaque insets as given to us during synchronization. We hold
      * on to this so that we can determine the opaque insets in the computeOpaqueRegion method.
      */
@@ -172,10 +177,11 @@
      * @param scaleShape whether to scale the shape
      * @param positionShape whether to center the shape
      */
-    @Override public void updateShape(Object shape, boolean scaleShape, boolean positionShape) {
+    @Override public void updateShape(Object shape, boolean scaleShape, boolean positionShape, boolean cacheShape) {
         this.shape = shape == null ? null : ((NGShape) ((javafx.scene.shape.Shape)shape).impl_getPGNode()).getShape();
         this.scaleShape = scaleShape;
         this.centerShape = positionShape;
+        this.cacheShape = cacheShape;
         invalidateOpaqueRegion();
     }
 
@@ -228,7 +234,7 @@
 
         float top=0, right=0, bottom=0, left=0;
         final List<BackgroundFill> fills = background.getFills();
-        backgroundCanBeCached = !PrismSettings.disableRegionCaching && !fills.isEmpty();
+        backgroundCanBeCached = !PrismSettings.disableRegionCaching && !fills.isEmpty() && (shape == null || cacheShape);
         if (backgroundCanBeCached) {
             for (int i = 0, max = fills.size(); i < max; i++) {
                 final BackgroundFill fill = fills.get(i);
--- a/javafx-ui-charts/src/javafx/scene/chart/BubbleChart.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-charts/src/javafx/scene/chart/BubbleChart.java	Fri Jan 11 09:03:56 2013 -0800
@@ -108,7 +108,6 @@
                         StackPane region = (StackPane)item.getNode();
                         if (region.getShape() == null) {
                             ellipse = new Ellipse(getDoubleValue(item.getExtraValue(), 1), getDoubleValue(item.getExtraValue(), 1));
-                            region.setShape(ellipse);
                         } else if (region.getShape() instanceof Ellipse) {
                             ellipse = (Ellipse)region.getShape();
                         } else {
@@ -123,6 +122,7 @@
                         region.setShape(ellipse);
                         region.setScaleShape(false);
                         region.setCenterShape(false);
+                        region.setCacheShape(false);
                         // position the bubble
                         bubble.setLayoutX(x);
                         bubble.setLayoutY(y);
--- a/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-charts/src/javafx/scene/chart/PieChart.java	Fri Jan 11 09:03:56 2013 -0800
@@ -24,13 +24,15 @@
  */
 package javafx.scene.chart;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
+import javafx.animation.Animation;
 import javafx.animation.FadeTransition;
 import javafx.animation.Interpolator;
 import javafx.animation.KeyFrame;
 import javafx.animation.KeyValue;
+import javafx.animation.Timeline;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.DoublePropertyBase;
@@ -51,21 +53,24 @@
 import javafx.geometry.Side;
 import javafx.scene.Node;
 import javafx.scene.layout.Region;
-import javafx.scene.shape.*;
+import javafx.scene.shape.Arc;
+import javafx.scene.shape.ArcTo;
+import javafx.scene.shape.ArcType;
+import javafx.scene.shape.ClosePath;
+import javafx.scene.shape.LineTo;
+import javafx.scene.shape.MoveTo;
+import javafx.scene.shape.Path;
 import javafx.scene.text.Text;
 import javafx.scene.transform.Scale;
 import javafx.util.Duration;
-
 import com.sun.javafx.charts.Legend;
 import com.sun.javafx.charts.Legend.LegendItem;
 import com.sun.javafx.collections.NonIterableChange;
+import com.sun.javafx.css.CssMetaData;
 import com.sun.javafx.css.StyleableBooleanProperty;
 import com.sun.javafx.css.StyleableDoubleProperty;
-import com.sun.javafx.css.CssMetaData;
 import com.sun.javafx.css.converters.BooleanConverter;
 import com.sun.javafx.css.converters.SizeConverter;
-import java.util.ArrayList;
-import javafx.animation.*;
 
 /**
  * Displays a PieChart. The chart content is populated by pie slices based on
@@ -334,7 +339,7 @@
         // check if symbol has already been created
         if (arcRegion == null) {
             arcRegion = new Region();
-            arcRegion.setPickOnBounds(false); 
+            arcRegion.setPickOnBounds(false);
             item.setNode(arcRegion);
         }
         // Note: not sure if we want to add or check, ie be more careful and efficient here
@@ -601,6 +606,7 @@
                         arcRegion.setShape(arc);
                         arcRegion.setScaleShape(false);
                         arcRegion.setCenterShape(false);
+                        arcRegion.setCacheShape(false);
                     }
                 }
                 double size = (isClockwise()) ? (-scale * Math.abs(item.getCurrentPieValue())) : (scale * Math.abs(item.getCurrentPieValue()));
--- a/javafx-ui-common/src/com/sun/javafx/application/PlatformImpl.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/src/com/sun/javafx/application/PlatformImpl.java	Fri Jan 11 09:03:56 2013 -0800
@@ -60,6 +60,12 @@
     private static Set<FinishListener> finishListeners =
             new CopyOnWriteArraySet<FinishListener>();
     private final static Object runLaterLock = new Object();
+    private static Boolean isGraphicsSupported;
+    private static Boolean isControlsSupported;
+    private static Boolean isWebSupported;
+    private static Boolean isSWTSupported;
+    private static Boolean isSwingSupported;
+    private static Boolean isFXMLSupported;
 
     /**
      * Set a flag indicating whether this application should show up in the
@@ -336,8 +342,53 @@
         }
     }
 
+    private static Boolean checkForClass(String classname) {
+        try {
+            Class.forName(classname, false, PlatformImpl.class.getClassLoader());
+            return Boolean.TRUE;
+        } catch (ClassNotFoundException cnfe) {
+            return Boolean.FALSE;
+        }
+    }
+
     public static boolean isSupported(ConditionalFeature feature) {
-        return Toolkit.getToolkit().isSupported(feature);
+        switch (feature) {
+            case GRAPHICS:
+                if (isGraphicsSupported == null) {
+                    isGraphicsSupported = checkForClass("javafx.stage.Stage");
+                }
+                return isGraphicsSupported;
+            case CONTROLS:
+                if (isControlsSupported == null) {
+                    isControlsSupported = checkForClass(
+                            "javafx.scene.control.Control");
+                }
+                return isControlsSupported;
+            case WEB:
+                if (isWebSupported == null) {
+                    isWebSupported = checkForClass("javafx.scene.web.WebView");
+                }
+                return isWebSupported;
+            case SWT:
+                if (isSWTSupported == null) {
+                    isSWTSupported = checkForClass("javafx.embed.swt.FXCanvas");
+                }
+                return isSWTSupported;
+            case SWING:
+                if (isSwingSupported == null) {
+                    isSwingSupported = checkForClass(
+                            "javafx.embed.swing.JFXPanel");
+                }
+                return isSwingSupported;
+            case FXML:
+                if (isFXMLSupported == null) {
+                    isFXMLSupported = checkForClass("javafx.fxml.FXMLLoader")
+                            && checkForClass("javax.xml.stream.XMLInputFactory");
+                }
+                return isFXMLSupported;
+            default:
+                return Toolkit.getToolkit().isSupported(feature);
+        }
     }
 
     public static interface FinishListener {
--- a/javafx-ui-common/src/javafx/application/ConditionalFeature.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/src/javafx/application/ConditionalFeature.java	Fri Jan 11 09:03:56 2013 -0800
@@ -38,6 +38,46 @@
 public enum ConditionalFeature {
 
     /**
+     * Indicates that JavaFX classes providing graphics capabilities are
+     * available on this platform.
+     */
+    GRAPHICS,
+
+    /**
+     * Indicates that JavaFX classes providing UI controls are available on
+     * this platform.
+     */
+    CONTROLS,
+
+    /**
+     * Indicates that the javafx.scene.web packages is available on this
+     * platform.
+     */
+    WEB,
+
+    /**
+     * Indicates that SWT integration is available on the platform. This tests
+     * for SWT integration with JavaFX, but does not test for the presence of
+     * the full SWT library.
+     */
+    SWT,
+
+    /* Indicates that the Swing library is present in the Java Runtime
+     * Environment and that Swing integration with JavaFX is available on the
+     * platform.
+     */
+    SWING,
+
+
+    /* Indicates that XML libraries are present in the JRE and that the FXML
+     * API is available on the platform. Note that it is possible for FXML APIs
+     * to be present but unusable if the underlying Java Runtime Environment
+     * does not have XML support. In this case
+     * Platform.isSupported(ConditionalFeature.FXML) wll return false.
+     */
+    FXML,
+
+    /**
      * Indicates that 3D is available on the platform.
      * If an application attempts to use 3D transforms or a 3D camera on a
      * platform that does not support 3D, then the transform or camera is
--- a/javafx-ui-common/src/javafx/scene/Scene.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/Scene.java	Fri Jan 11 09:03:56 2013 -0800
@@ -92,7 +92,6 @@
 import com.sun.javafx.cursor.CursorFrame;
 import com.sun.javafx.event.EventQueue;
 import com.sun.javafx.geom.PickRay;
-import com.sun.javafx.geom.transform.Affine2D;
 import com.sun.javafx.geom.transform.BaseTransform;
 import sun.util.logging.PlatformLogger;
 import com.sun.javafx.perf.PerformanceTracker;
@@ -325,7 +324,7 @@
                     return parent.getChildren(); //was impl_getChildren
                 }
                 public Object renderToImage(Scene scene, Object platformImage) {
-                    return scene.renderToImage(platformImage);
+                    return scene.snapshot(null).impl_getPlatformImage();
                 }
             });
             Toolkit.setSceneAccessor(new Toolkit.SceneAccessor() {
@@ -1029,51 +1028,6 @@
         return root;
     }
 
-    /**
-     * This method is superseded by {@link #snapshot(javafx.scene.image.WritableImage)}
-     *
-     * WARNING: This method is not part of the public API and is
-     * subject to change!  It is intended for use by the designer tool only.
-     *
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: RT-21222 has been filed to track this
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public Object renderToImage(Object platformImage) {
-        return renderToImage(platformImage, 1.0f);
-    }
-
-    /**
-     * Renders this {@code Scene} to the given platform-specific image
-     * (e.g. a {@code BufferedImage} in the case of the Swing profile)
-     * using the specified scaling factor.
-     * If {@code platformImage} is null, a new platform-specific image
-     * is returned.
-     * If the contents of the scene have not changed since the last time
-     * this method was called, this method returns null.
-     *
-     * WARNING: This method is not part of the public API and is
-     * subject to change!  It is intended for use by the designer tool only.
-     *
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    @Deprecated
-    public Object renderToImage(Object platformImage, float scale) {
-        if (!paused) {
-            Toolkit.getToolkit().checkFxUserThread();
-        }
-
-        // NOTE: that we no longer use the passed in platform image. Since this
-        // API is deprecated and will be removed in 3.0 this is not a concern.
-        // Also, we used to return a TK image loader and now we return
-        // the actual TK PlatformImage.
-        return doSnapshot(null, scale).impl_getPlatformImage();
-    }
-
     private void doLayoutPassWithoutPulse(int maxAttempts) {
         for (int i = 0; dirtyLayoutRoots.size() > 0 && i != maxAttempts; ++i) {
             layoutDirtyRoots();
@@ -1165,7 +1119,7 @@
     /**
      * Implementation method for snapshot
      */
-    private WritableImage doSnapshot(WritableImage img, float scale) {
+    private WritableImage doSnapshot(WritableImage img) {
         // TODO: no need to do CSS, layout or sync in the deferred case,
         // if this scene is attached to a visible stage
         doCSSLayoutSyncForSnapshot(getRoot());
@@ -1173,13 +1127,6 @@
         double w = getWidth();
         double h = getHeight();
         BaseTransform transform = BaseTransform.IDENTITY_TRANSFORM;
-        if (scale != 1.0f) {
-            Affine2D tx = new Affine2D();
-            tx.scale(scale, scale);
-            transform = tx;
-            w *= scale;
-            h *= scale;
-        }
 
         return doSnapshot(this, 0, 0, w, h,
                 getRoot(), transform, isDepthBuffer(),
@@ -1268,7 +1215,7 @@
             Toolkit.getToolkit().checkFxUserThread();
         }
 
-        return  doSnapshot(image, 1.0f);
+        return doSnapshot(image);
     }
 
     /**
@@ -1330,7 +1277,7 @@
         // any of them have been rendered.
         final Runnable snapshotRunnable = new Runnable() {
             @Override public void run() {
-                WritableImage img = doSnapshot(theImage, 1.0f);
+                WritableImage img = doSnapshot(theImage);
 //                System.err.println("Calling snapshot callback");
                 SnapshotResult result = new SnapshotResult(img, Scene.this, null);
                 try {
--- a/javafx-ui-common/src/javafx/scene/doc-files/cssref.html	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/doc-files/cssref.html	Fri Jan 11 09:03:56 2013 -0800
@@ -3700,7 +3700,7 @@
           <td>&nbsp;</td>
         </tr>
         <tr>
-          <td class="propertyname">-fx-page-information-visible:</td>
+          <td class="propertyname">-fx-page-information-visible</td>
           <td class="value"><a href="#typesize" class="typelink">&lt;boolean&gt;</a></td>
           <td>true</td>
           <td>&nbsp;</td>
--- a/javafx-ui-common/src/javafx/scene/image/Image.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/image/Image.java	Fri Jan 11 09:03:56 2013 -0800
@@ -1018,57 +1018,6 @@
     }
 
     /**
-     * This method converts a JavaFX Image to the specified image class or
-     * to an image of the same class and the same format as specified image.
-     * If the specified image class is not supported, then null will be returned.
-     *
-     * @param imgType either a Class object that specifies the type of image,
-     *      or an actual image object of the desired type and format.
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: ?????
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public Object impl_toExternalImage(Object imgType) {
-        return Toolkit.getToolkit().toExternalImage(impl_getPlatformImage(), imgType);
-    }
-
-    /**
-     * This method converts the specified image to a JavaFX Image.
-     * If the specified image class is not supported, then null will be returned.
-     *
-     * @param extImage - an image to convert.
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: ?????
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public static Image impl_fromExternalImage(Object extImage) {
-        return impl_isExternalFormatSupported(extImage.getClass())
-                ? new Image(extImage)
-                : null;
-    }
-
-    /**
-     * This method indicates whether conversion to/from the specified external
-     * format is possible.
-     *
-     * @treatAsPrivate implementation detail
-     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
-     */
-    // SB-dependency: ?????
-    // TODO: need to ensure that both SceneBuilder and JDevloper have migrated
-    // to new 2.2 public API before we remove this.
-    @Deprecated
-    public static boolean impl_isExternalFormatSupported(Class format) {
-        return Toolkit.getToolkit().isExternalFormatSupported(format);
-    }
-
-    /**
      * Indicates whether image is animated.
      */
     boolean isAnimation() {
--- a/javafx-ui-common/src/javafx/scene/layout/Region.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/src/javafx/scene/layout/Region.java	Fri Jan 11 09:03:56 2013 -0800
@@ -1046,13 +1046,13 @@
         }
         return centerShape;
     }
+
     /**
-     * Defines whether the shape is centered within the Region's width or height.
-     * {@code true} means the shape centered within the Region's width and height,
-     * {@code false} means the shape is positioned at its source position.
+     * Defines a hint to the system indicating that the Shape used to define the region's
+     * background is stable and would benefit from caching.
      *
      * @default true
-     * @css position-shape      true | false
+     * @css -fx-cache-shape      true | false
      */
     private BooleanProperty cacheShape = null;
     public final void setCacheShape(boolean value) { cacheShapeProperty().set(value); }
@@ -1864,7 +1864,7 @@
         // the shape must be specified before the background which is before the border.
         final boolean shapeChanged = impl_isDirty(DirtyBits.REGION_SHAPE);
         if (shapeChanged) {
-            pg.updateShape(_shape, isScaleShape(), isCenterShape());
+            pg.updateShape(_shape, isScaleShape(), isCenterShape(), isCacheShape());
         }
 
         final boolean backgroundChanged = impl_isDirty(DirtyBits.SHAPE_FILL);
--- a/javafx-ui-common/test/unit/javafx/scene/image/ImageTest.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-common/test/unit/javafx/scene/image/ImageTest.java	Fri Jan 11 09:03:56 2013 -0800
@@ -447,68 +447,6 @@
         return lastAsyncImageLoader;
     }
 
-    // lets test following:  ;)
-    // 
-    //  public static boolean impl_isExternalFormatSupported(Class format) {
-    //    return Toolkit.getToolkit().isExternalFormatSupported(format);
-    // }
-    @Test
-    public void isExternalFormatSupportedTest() {
-        toolkit.externalFormatClass = StubToolkit.class;
-        assertFalse(Image.impl_isExternalFormatSupported(null));
-        assertTrue(Image.impl_isExternalFormatSupported(StubToolkit.class));
-        toolkit.externalFormatClass = ImageTest.class;
-        assertFalse(Image.impl_isExternalFormatSupported(StubToolkit.class));
-        assertTrue(Image.impl_isExternalFormatSupported(ImageTest.class));
-    }
-
-    // lets test 
-    //    public Object impl_toExternalImage(Object imgType) {
-    //        return Toolkit.getToolkit().toExternalImage(getPlatformImage(), imgType);
-    //    }
-    @Test
-    public void impl_toExternalImageTest() {
-        final Object fakePlatformImage = "fakePlatformImage";
-        registerImage(fakePlatformImage, 200, 500);
-        final Image image = Image.impl_fromPlatformImage(fakePlatformImage);
-
-        StubPlatformImage spi = (StubPlatformImage) image.impl_getPlatformImage();
-        assertTrue(spi.getSource() == fakePlatformImage);
-
-        final Object format = "image format object";
-        final Object password = "password";
-
-        toolkit.toExternalImagePassword = password;
-
-        Object extImage = image.impl_toExternalImage(format);
-        Object[] data = (Object[]) extImage;
-
-        assertTrue(
-                data.length == 3
-                && data[0] == spi
-                && data[1] == format
-                && data[2] == password);
-    }
-
-    // lets test 
-    //    public Object impl_fromExternalImage(Object image)
-    // it is more comlex
-    // we have to be sure impl_isExternalFormatSupported for image.class.
-    // and until it is not "null" returned
-    @Test
-    public void impl_fromExternalImageTest() {
-        toolkit.externalFormatClass = ImageTest.class;
-        final Object fakeExternalImage = "fakeExternalImage";
-        registerImage(fakeExternalImage, 123, 456);
-
-        assertFalse(Image.impl_isExternalFormatSupported(fakeExternalImage.getClass()));
-        assertNull(Image.impl_fromExternalImage(fakeExternalImage));
-
-        toolkit.externalFormatClass = fakeExternalImage.getClass();
-        final Image image = Image.impl_fromExternalImage(fakeExternalImage);
-        verifyLoadedImage(image, 0, 0, false, false, 123, 456);
-    }
-    
     @Test
     public void createImageFromClasspathTest() {
         final String url = "javafx/scene/image/test.png";
--- a/javafx-ui-controls/src/javafx/scene/control/TableUtil.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TableUtil.java	Fri Jan 11 09:03:56 2013 -0800
@@ -28,7 +28,6 @@
 import java.util.Collections;
 import java.util.List;
 import javafx.beans.InvalidationListener;
-import javafx.beans.WeakInvalidationListener;
 import javafx.collections.ListChangeListener;
 
 /**
@@ -37,13 +36,13 @@
  */
 class TableUtil {
     
-    static <S> void removeTableColumnListener(List<? extends TableColumnBase<S,?>> list,
+    static void removeTableColumnListener(List<? extends TableColumnBase> list,
                         final InvalidationListener columnVisibleObserver,
                         final InvalidationListener columnSortableObserver,
                         final InvalidationListener columnSortTypeObserver) {
     
         if (list == null) return;
-        for (TableColumnBase<S,?> col : list) {
+        for (TableColumnBase col : list) {
             col.visibleProperty().removeListener(columnVisibleObserver);
             col.sortableProperty().removeListener(columnSortableObserver);
             col.sortTypeProperty().removeListener(columnSortTypeObserver);
@@ -55,13 +54,13 @@
         }
     }
 
-    static <S> void addTableColumnListener(List<? extends TableColumnBase<S,?>> list,
+    static void addTableColumnListener(List<? extends TableColumnBase> list,
                         final InvalidationListener columnVisibleObserver,
                         final InvalidationListener columnSortableObserver,
                         final InvalidationListener columnSortTypeObserver) {
         
         if (list == null) return;
-        for (TableColumnBase<S,?> col : list) {
+        for (TableColumnBase col : list) {
             col.visibleProperty().addListener(columnVisibleObserver);
             col.sortableProperty().addListener(columnSortableObserver);
             col.sortTypeProperty().addListener(columnSortTypeObserver);
@@ -73,19 +72,19 @@
         }
     }
 
-    static <S> void removeColumnsListener(List<? extends TableColumnBase<S,?>> list, ListChangeListener cl) {
+    static void removeColumnsListener(List<? extends TableColumnBase> list, ListChangeListener cl) {
         if (list == null) return;
 
-        for (TableColumnBase<S,?> col : list) {
+        for (TableColumnBase col : list) {
             col.getColumns().removeListener(cl);
             removeColumnsListener(col.getColumns(), cl);
         }
     }
 
-    static <S> void addColumnsListener(List<? extends TableColumnBase<S,?>> list, ListChangeListener cl) {
+    static void addColumnsListener(List<? extends TableColumnBase> list, ListChangeListener cl) {
         if (list == null) return;
 
-        for (TableColumnBase<S,?> col : list) {
+        for (TableColumnBase col : list) {
             col.getColumns().addListener(cl);
             addColumnsListener(col.getColumns(), cl);
         }
--- a/javafx-ui-controls/src/javafx/scene/control/TreeTableColumn.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/javafx-ui-controls/src/javafx/scene/control/TreeTableColumn.java	Fri Jan 11 09:03:56 2013 -0800
@@ -24,10 +24,6 @@
  */
 package javafx.scene.control;
 
-import com.sun.javafx.css.Styleable;
-import com.sun.javafx.css.CssMetaData;
-import com.sun.javafx.event.EventHandlerManager;
-import com.sun.javafx.scene.control.skin.TableViewSkinBase;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -49,6 +45,9 @@
 import javafx.event.EventType;
 import javafx.scene.Node;
 import javafx.util.Callback;
+import com.sun.javafx.css.CssMetaData;
+import com.sun.javafx.css.Styleable;
+import com.sun.javafx.scene.control.skin.TableViewSkinBase;
 
 /**
  * A {@link TreeTableView} is made up of a number of TreeTableColumn instances. Each
@@ -728,7 +727,7 @@
          * @param newValue The value input by the end user.
          */
         public CellEditEvent(TreeTableView<S> table, TreeTablePosition<S,T> pos,
-                EventType<TreeTableColumn.CellEditEvent> eventType, T newValue) {
+                EventType<TreeTableColumn.CellEditEvent<S,T>> eventType, T newValue) {
             super(table, Event.NULL_SOURCE_TARGET, eventType);
 
             if (table == null) {
--- a/test-stub-toolkit/src/com/sun/javafx/pgstub/StubRegion.java	Thu Jan 10 15:42:07 2013 -0800
+++ b/test-stub-toolkit/src/com/sun/javafx/pgstub/StubRegion.java	Fri Jan 11 09:03:56 2013 -0800
@@ -42,7 +42,7 @@
     }
     public void updateBackground(Object background) {
     }
-    public void updateShape(Object shape, boolean scale, boolean center) {
+    public void updateShape(Object shape, boolean scale, boolean center, boolean cacheShape) {
     }
     public void setSize(float width, float height) {
     }